blob: 3029028e4e7692db64e1d6f4e162d65e42e7a26f [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac02010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownefd32662011-03-08 15:13:06 -080036
Jeff Brownb4ff35d2011-01-02 16:37:43 -080037#include "InputReader.h"
38
Jeff Brown46b9ac02010-04-22 18:58:52 -070039#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080040#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080041#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070042
43#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070044#include <stdlib.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070045#include <unistd.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070046#include <errno.h>
47#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070048#include <math.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070049
Jeff Brown8d608662010-08-30 03:02:23 -070050#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070051#define INDENT2 " "
52#define INDENT3 " "
53#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070054
Jeff Brown46b9ac02010-04-22 18:58:52 -070055namespace android {
56
57// --- Static Functions ---
58
59template<typename T>
60inline static T abs(const T& value) {
61 return value < 0 ? - value : value;
62}
63
64template<typename T>
65inline static T min(const T& a, const T& b) {
66 return a < b ? a : b;
67}
68
Jeff Brown5c225b12010-06-16 01:53:36 -070069template<typename T>
70inline static void swap(T& a, T& b) {
71 T temp = a;
72 a = b;
73 b = temp;
74}
75
Jeff Brown8d608662010-08-30 03:02:23 -070076inline static float avg(float x, float y) {
77 return (x + y) / 2;
78}
79
80inline static float pythag(float x, float y) {
81 return sqrtf(x * x + y * y);
82}
83
Jeff Brown517bb4c2011-01-14 19:09:23 -080084inline static int32_t signExtendNybble(int32_t value) {
85 return value >= 8 ? value - 16 : value;
86}
87
Jeff Brownef3d7e82010-09-30 14:33:04 -070088static inline const char* toString(bool value) {
89 return value ? "true" : "false";
90}
91
Jeff Brown9626b142011-03-03 02:09:54 -080092static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
93 const int32_t map[][4], size_t mapSize) {
94 if (orientation != DISPLAY_ORIENTATION_0) {
95 for (size_t i = 0; i < mapSize; i++) {
96 if (value == map[i][0]) {
97 return map[i][orientation];
98 }
99 }
100 }
101 return value;
102}
103
Jeff Brown46b9ac02010-04-22 18:58:52 -0700104static const int32_t keyCodeRotationMap[][4] = {
105 // key codes enumerated counter-clockwise with the original (unrotated) key first
106 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -0700107 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
108 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
109 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
110 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac02010-04-22 18:58:52 -0700111};
Jeff Brown9626b142011-03-03 02:09:54 -0800112static const size_t keyCodeRotationMapSize =
Jeff Brown46b9ac02010-04-22 18:58:52 -0700113 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
114
115int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9626b142011-03-03 02:09:54 -0800116 return rotateValueUsingRotationMap(keyCode, orientation,
117 keyCodeRotationMap, keyCodeRotationMapSize);
118}
119
120static const int32_t edgeFlagRotationMap[][4] = {
121 // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
122 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
123 { AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT,
124 AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT },
125 { AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP,
126 AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM },
127 { AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT,
128 AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT },
129 { AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM,
130 AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP },
131};
132static const size_t edgeFlagRotationMapSize =
133 sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
134
135static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
136 return rotateValueUsingRotationMap(edgeFlag, orientation,
137 edgeFlagRotationMap, edgeFlagRotationMapSize);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700138}
139
Jeff Brown6d0fec22010-07-23 21:28:06 -0700140static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
141 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
142}
143
Jeff Brownefd32662011-03-08 15:13:06 -0800144static uint32_t getButtonStateForScanCode(int32_t scanCode) {
145 // Currently all buttons are mapped to the primary button.
146 switch (scanCode) {
147 case BTN_LEFT:
148 case BTN_RIGHT:
149 case BTN_MIDDLE:
150 case BTN_SIDE:
151 case BTN_EXTRA:
152 case BTN_FORWARD:
153 case BTN_BACK:
154 case BTN_TASK:
155 return BUTTON_STATE_PRIMARY;
156 default:
157 return 0;
158 }
159}
160
161// Returns true if the pointer should be reported as being down given the specified
162// button states.
163static bool isPointerDown(uint32_t buttonState) {
164 return buttonState & BUTTON_STATE_PRIMARY;
165}
166
167static int32_t calculateEdgeFlagsUsingPointerBounds(
168 const sp<PointerControllerInterface>& pointerController, float x, float y) {
169 int32_t edgeFlags = 0;
170 float minX, minY, maxX, maxY;
171 if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
172 if (x <= minX) {
173 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
174 } else if (x >= maxX) {
175 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
176 }
177 if (y <= minY) {
178 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
179 } else if (y >= maxY) {
180 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
181 }
182 }
183 return edgeFlags;
184}
185
Jeff Brown46b9ac02010-04-22 18:58:52 -0700186
Jeff Brown46b9ac02010-04-22 18:58:52 -0700187// --- InputReader ---
188
189InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700190 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700191 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700192 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brownfe508922011-01-18 15:10:10 -0800193 mGlobalMetaState(0), mDisableVirtualKeysTimeout(-1) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700194 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700195 updateGlobalMetaState();
196 updateInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700197}
198
199InputReader::~InputReader() {
200 for (size_t i = 0; i < mDevices.size(); i++) {
201 delete mDevices.valueAt(i);
202 }
203}
204
205void InputReader::loopOnce() {
206 RawEvent rawEvent;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700207 mEventHub->getEvent(& rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700208
209#if DEBUG_RAW_EVENTS
Jeff Brown90655042010-12-02 13:50:46 -0800210 LOGD("Input event: device=%d type=0x%x scancode=%d keycode=%d value=%d",
Jeff Brown46b9ac02010-04-22 18:58:52 -0700211 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
212 rawEvent.value);
213#endif
214
215 process(& rawEvent);
216}
217
218void InputReader::process(const RawEvent* rawEvent) {
219 switch (rawEvent->type) {
220 case EventHubInterface::DEVICE_ADDED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700221 addDevice(rawEvent->deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700222 break;
223
224 case EventHubInterface::DEVICE_REMOVED:
Jeff Brown7342bb92010-10-01 18:55:43 -0700225 removeDevice(rawEvent->deviceId);
226 break;
227
228 case EventHubInterface::FINISHED_DEVICE_SCAN:
Jeff Brownc3db8582010-10-20 15:33:38 -0700229 handleConfigurationChanged(rawEvent->when);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700230 break;
231
Jeff Brown6d0fec22010-07-23 21:28:06 -0700232 default:
233 consumeEvent(rawEvent);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700234 break;
235 }
236}
237
Jeff Brown7342bb92010-10-01 18:55:43 -0700238void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700239 String8 name = mEventHub->getDeviceName(deviceId);
240 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
241
242 InputDevice* device = createDevice(deviceId, name, classes);
243 device->configure();
244
Jeff Brown8d608662010-08-30 03:02:23 -0700245 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800246 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700247 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800248 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700249 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700250 }
251
Jeff Brown6d0fec22010-07-23 21:28:06 -0700252 bool added = false;
253 { // acquire device registry writer lock
254 RWLock::AutoWLock _wl(mDeviceRegistryLock);
255
256 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
257 if (deviceIndex < 0) {
258 mDevices.add(deviceId, device);
259 added = true;
260 }
261 } // release device registry writer lock
262
263 if (! added) {
264 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
265 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700266 return;
267 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700268}
269
Jeff Brown7342bb92010-10-01 18:55:43 -0700270void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700271 bool removed = false;
272 InputDevice* device = NULL;
273 { // acquire device registry writer lock
274 RWLock::AutoWLock _wl(mDeviceRegistryLock);
275
276 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
277 if (deviceIndex >= 0) {
278 device = mDevices.valueAt(deviceIndex);
279 mDevices.removeItemsAt(deviceIndex, 1);
280 removed = true;
281 }
282 } // release device registry writer lock
283
284 if (! removed) {
285 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700286 return;
287 }
288
Jeff Brown6d0fec22010-07-23 21:28:06 -0700289 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800290 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700291 device->getId(), device->getName().string());
292 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800293 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700294 device->getId(), device->getName().string(), device->getSources());
295 }
296
Jeff Brown8d608662010-08-30 03:02:23 -0700297 device->reset();
298
Jeff Brown6d0fec22010-07-23 21:28:06 -0700299 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700300}
301
Jeff Brown6d0fec22010-07-23 21:28:06 -0700302InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
303 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700304
Jeff Brown56194eb2011-03-02 19:23:13 -0800305 // External devices.
306 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
307 device->setExternal(true);
308 }
309
Jeff Brown6d0fec22010-07-23 21:28:06 -0700310 // Switch-like devices.
311 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
312 device->addMapper(new SwitchInputMapper(device));
313 }
314
315 // Keyboard-like devices.
Jeff Brownefd32662011-03-08 15:13:06 -0800316 uint32_t keyboardSource = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700317 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
318 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800319 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700320 }
321 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
322 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
323 }
324 if (classes & INPUT_DEVICE_CLASS_DPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800325 keyboardSource |= AINPUT_SOURCE_DPAD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700326 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800327 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800328 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
Jeff Browncb1404e2011-01-15 18:14:15 -0800329 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700330
Jeff Brownefd32662011-03-08 15:13:06 -0800331 if (keyboardSource != 0) {
332 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700333 }
334
Jeff Brown83c09682010-12-23 17:50:18 -0800335 // Cursor-like devices.
336 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
337 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700338 }
339
Jeff Brown58a2da82011-01-25 16:02:22 -0800340 // Touchscreens and touchpad devices.
341 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800342 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800343 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800344 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700345 }
346
Jeff Browncb1404e2011-01-15 18:14:15 -0800347 // Joystick-like devices.
348 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
349 device->addMapper(new JoystickInputMapper(device));
350 }
351
Jeff Brown6d0fec22010-07-23 21:28:06 -0700352 return device;
353}
354
355void InputReader::consumeEvent(const RawEvent* rawEvent) {
356 int32_t deviceId = rawEvent->deviceId;
357
358 { // acquire device registry reader lock
359 RWLock::AutoRLock _rl(mDeviceRegistryLock);
360
361 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
362 if (deviceIndex < 0) {
363 LOGW("Discarding event for unknown deviceId %d.", deviceId);
364 return;
365 }
366
367 InputDevice* device = mDevices.valueAt(deviceIndex);
368 if (device->isIgnored()) {
369 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
370 return;
371 }
372
373 device->process(rawEvent);
374 } // release device registry reader lock
375}
376
Jeff Brownc3db8582010-10-20 15:33:38 -0700377void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 // Reset global meta state because it depends on the list of all configured devices.
379 updateGlobalMetaState();
380
381 // Update input configuration.
382 updateInputConfiguration();
383
384 // Enqueue configuration changed.
385 mDispatcher->notifyConfigurationChanged(when);
386}
387
388void InputReader::configureExcludedDevices() {
389 Vector<String8> excludedDeviceNames;
390 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
391
392 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
393 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
394 }
395}
396
397void InputReader::updateGlobalMetaState() {
398 { // acquire state lock
399 AutoMutex _l(mStateLock);
400
401 mGlobalMetaState = 0;
402
403 { // acquire device registry reader lock
404 RWLock::AutoRLock _rl(mDeviceRegistryLock);
405
406 for (size_t i = 0; i < mDevices.size(); i++) {
407 InputDevice* device = mDevices.valueAt(i);
408 mGlobalMetaState |= device->getMetaState();
409 }
410 } // release device registry reader lock
411 } // release state lock
412}
413
414int32_t InputReader::getGlobalMetaState() {
415 { // acquire state lock
416 AutoMutex _l(mStateLock);
417
418 return mGlobalMetaState;
419 } // release state lock
420}
421
422void InputReader::updateInputConfiguration() {
423 { // acquire state lock
424 AutoMutex _l(mStateLock);
425
426 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
427 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
428 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
429 { // acquire device registry reader lock
430 RWLock::AutoRLock _rl(mDeviceRegistryLock);
431
432 InputDeviceInfo deviceInfo;
433 for (size_t i = 0; i < mDevices.size(); i++) {
434 InputDevice* device = mDevices.valueAt(i);
435 device->getDeviceInfo(& deviceInfo);
436 uint32_t sources = deviceInfo.getSources();
437
438 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
439 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
440 }
441 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
442 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
443 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
444 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
445 }
446 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
447 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700448 }
449 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700450 } // release device registry reader lock
Jeff Brown46b9ac02010-04-22 18:58:52 -0700451
Jeff Brown6d0fec22010-07-23 21:28:06 -0700452 mInputConfiguration.touchScreen = touchScreenConfig;
453 mInputConfiguration.keyboard = keyboardConfig;
454 mInputConfiguration.navigation = navigationConfig;
455 } // release state lock
456}
457
Jeff Brownfe508922011-01-18 15:10:10 -0800458void InputReader::disableVirtualKeysUntil(nsecs_t time) {
459 mDisableVirtualKeysTimeout = time;
460}
461
462bool InputReader::shouldDropVirtualKey(nsecs_t now,
463 InputDevice* device, int32_t keyCode, int32_t scanCode) {
464 if (now < mDisableVirtualKeysTimeout) {
465 LOGI("Dropping virtual key from device %s because virtual keys are "
466 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
467 device->getName().string(),
468 (mDisableVirtualKeysTimeout - now) * 0.000001,
469 keyCode, scanCode);
470 return true;
471 } else {
472 return false;
473 }
474}
475
Jeff Brown05dc66a2011-03-02 14:41:58 -0800476void InputReader::fadePointer() {
477 { // acquire device registry reader lock
478 RWLock::AutoRLock _rl(mDeviceRegistryLock);
479
480 for (size_t i = 0; i < mDevices.size(); i++) {
481 InputDevice* device = mDevices.valueAt(i);
482 device->fadePointer();
483 }
484 } // release device registry reader lock
485}
486
Jeff Brown6d0fec22010-07-23 21:28:06 -0700487void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
488 { // acquire state lock
489 AutoMutex _l(mStateLock);
490
491 *outConfiguration = mInputConfiguration;
492 } // release state lock
493}
494
495status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
496 { // acquire device registry reader lock
497 RWLock::AutoRLock _rl(mDeviceRegistryLock);
498
499 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
500 if (deviceIndex < 0) {
501 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700502 }
503
Jeff Brown6d0fec22010-07-23 21:28:06 -0700504 InputDevice* device = mDevices.valueAt(deviceIndex);
505 if (device->isIgnored()) {
506 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700507 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700508
509 device->getDeviceInfo(outDeviceInfo);
510 return OK;
511 } // release device registy reader lock
512}
513
514void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
515 outDeviceIds.clear();
516
517 { // acquire device registry reader lock
518 RWLock::AutoRLock _rl(mDeviceRegistryLock);
519
520 size_t numDevices = mDevices.size();
521 for (size_t i = 0; i < numDevices; i++) {
522 InputDevice* device = mDevices.valueAt(i);
523 if (! device->isIgnored()) {
524 outDeviceIds.add(device->getId());
525 }
526 }
527 } // release device registy reader lock
528}
529
530int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
531 int32_t keyCode) {
532 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
533}
534
535int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
536 int32_t scanCode) {
537 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
538}
539
540int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
541 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
542}
543
544int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
545 GetStateFunc getStateFunc) {
546 { // acquire device registry reader lock
547 RWLock::AutoRLock _rl(mDeviceRegistryLock);
548
549 int32_t result = AKEY_STATE_UNKNOWN;
550 if (deviceId >= 0) {
551 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
552 if (deviceIndex >= 0) {
553 InputDevice* device = mDevices.valueAt(deviceIndex);
554 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
555 result = (device->*getStateFunc)(sourceMask, code);
556 }
557 }
558 } else {
559 size_t numDevices = mDevices.size();
560 for (size_t i = 0; i < numDevices; i++) {
561 InputDevice* device = mDevices.valueAt(i);
562 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
563 result = (device->*getStateFunc)(sourceMask, code);
564 if (result >= AKEY_STATE_DOWN) {
565 return result;
566 }
567 }
568 }
569 }
570 return result;
571 } // release device registy reader lock
572}
573
574bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
575 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
576 memset(outFlags, 0, numCodes);
577 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
578}
579
580bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
581 const int32_t* keyCodes, uint8_t* outFlags) {
582 { // acquire device registry reader lock
583 RWLock::AutoRLock _rl(mDeviceRegistryLock);
584 bool result = false;
585 if (deviceId >= 0) {
586 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
587 if (deviceIndex >= 0) {
588 InputDevice* device = mDevices.valueAt(deviceIndex);
589 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
590 result = device->markSupportedKeyCodes(sourceMask,
591 numCodes, keyCodes, outFlags);
592 }
593 }
594 } else {
595 size_t numDevices = mDevices.size();
596 for (size_t i = 0; i < numDevices; i++) {
597 InputDevice* device = mDevices.valueAt(i);
598 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
599 result |= device->markSupportedKeyCodes(sourceMask,
600 numCodes, keyCodes, outFlags);
601 }
602 }
603 }
604 return result;
605 } // release device registy reader lock
606}
607
Jeff Brownb88102f2010-09-08 11:49:43 -0700608void InputReader::dump(String8& dump) {
Jeff Brownf2f48712010-10-01 17:46:21 -0700609 mEventHub->dump(dump);
610 dump.append("\n");
611
612 dump.append("Input Reader State:\n");
613
Jeff Brownef3d7e82010-09-30 14:33:04 -0700614 { // acquire device registry reader lock
615 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700616
Jeff Brownef3d7e82010-09-30 14:33:04 -0700617 for (size_t i = 0; i < mDevices.size(); i++) {
618 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700619 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700620 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700621}
622
Jeff Brown6d0fec22010-07-23 21:28:06 -0700623
624// --- InputReaderThread ---
625
626InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
627 Thread(/*canCallJava*/ true), mReader(reader) {
628}
629
630InputReaderThread::~InputReaderThread() {
631}
632
633bool InputReaderThread::threadLoop() {
634 mReader->loopOnce();
635 return true;
636}
637
638
639// --- InputDevice ---
640
641InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
Jeff Brown56194eb2011-03-02 19:23:13 -0800642 mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700643}
644
645InputDevice::~InputDevice() {
646 size_t numMappers = mMappers.size();
647 for (size_t i = 0; i < numMappers; i++) {
648 delete mMappers[i];
649 }
650 mMappers.clear();
651}
652
Jeff Brownef3d7e82010-09-30 14:33:04 -0700653void InputDevice::dump(String8& dump) {
654 InputDeviceInfo deviceInfo;
655 getDeviceInfo(& deviceInfo);
656
Jeff Brown90655042010-12-02 13:50:46 -0800657 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700658 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800659 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700660 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
661 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800662
Jeff Brownefd32662011-03-08 15:13:06 -0800663 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
Jeff Browncc0c1592011-02-19 05:07:28 -0800664 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700665 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800666 for (size_t i = 0; i < ranges.size(); i++) {
Jeff Brownefd32662011-03-08 15:13:06 -0800667 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
668 const char* label = getAxisLabel(range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800669 char name[32];
670 if (label) {
671 strncpy(name, label, sizeof(name));
672 name[sizeof(name) - 1] = '\0';
673 } else {
Jeff Brownefd32662011-03-08 15:13:06 -0800674 snprintf(name, sizeof(name), "%d", range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800675 }
Jeff Brownefd32662011-03-08 15:13:06 -0800676 dump.appendFormat(INDENT3 "%s: source=0x%08x, "
677 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
678 name, range.source, range.min, range.max, range.flat, range.fuzz);
Jeff Browncc0c1592011-02-19 05:07:28 -0800679 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700680 }
681
682 size_t numMappers = mMappers.size();
683 for (size_t i = 0; i < numMappers; i++) {
684 InputMapper* mapper = mMappers[i];
685 mapper->dump(dump);
686 }
687}
688
Jeff Brown6d0fec22010-07-23 21:28:06 -0700689void InputDevice::addMapper(InputMapper* mapper) {
690 mMappers.add(mapper);
691}
692
693void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700694 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800695 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700696 }
697
Jeff Brown6d0fec22010-07-23 21:28:06 -0700698 mSources = 0;
699
700 size_t numMappers = mMappers.size();
701 for (size_t i = 0; i < numMappers; i++) {
702 InputMapper* mapper = mMappers[i];
703 mapper->configure();
704 mSources |= mapper->getSources();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700705 }
706}
707
Jeff Brown6d0fec22010-07-23 21:28:06 -0700708void InputDevice::reset() {
709 size_t numMappers = mMappers.size();
710 for (size_t i = 0; i < numMappers; i++) {
711 InputMapper* mapper = mMappers[i];
712 mapper->reset();
713 }
714}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700715
Jeff Brown6d0fec22010-07-23 21:28:06 -0700716void InputDevice::process(const RawEvent* rawEvent) {
717 size_t numMappers = mMappers.size();
718 for (size_t i = 0; i < numMappers; i++) {
719 InputMapper* mapper = mMappers[i];
720 mapper->process(rawEvent);
721 }
722}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700723
Jeff Brown6d0fec22010-07-23 21:28:06 -0700724void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
725 outDeviceInfo->initialize(mId, mName);
726
727 size_t numMappers = mMappers.size();
728 for (size_t i = 0; i < numMappers; i++) {
729 InputMapper* mapper = mMappers[i];
730 mapper->populateDeviceInfo(outDeviceInfo);
731 }
732}
733
734int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
735 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
736}
737
738int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
739 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
740}
741
742int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
743 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
744}
745
746int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
747 int32_t result = AKEY_STATE_UNKNOWN;
748 size_t numMappers = mMappers.size();
749 for (size_t i = 0; i < numMappers; i++) {
750 InputMapper* mapper = mMappers[i];
751 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
752 result = (mapper->*getStateFunc)(sourceMask, code);
753 if (result >= AKEY_STATE_DOWN) {
754 return result;
755 }
756 }
757 }
758 return result;
759}
760
761bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
762 const int32_t* keyCodes, uint8_t* outFlags) {
763 bool result = false;
764 size_t numMappers = mMappers.size();
765 for (size_t i = 0; i < numMappers; i++) {
766 InputMapper* mapper = mMappers[i];
767 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
768 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
769 }
770 }
771 return result;
772}
773
774int32_t InputDevice::getMetaState() {
775 int32_t result = 0;
776 size_t numMappers = mMappers.size();
777 for (size_t i = 0; i < numMappers; i++) {
778 InputMapper* mapper = mMappers[i];
779 result |= mapper->getMetaState();
780 }
781 return result;
782}
783
Jeff Brown05dc66a2011-03-02 14:41:58 -0800784void InputDevice::fadePointer() {
785 size_t numMappers = mMappers.size();
786 for (size_t i = 0; i < numMappers; i++) {
787 InputMapper* mapper = mMappers[i];
788 mapper->fadePointer();
789 }
790}
791
Jeff Brown6d0fec22010-07-23 21:28:06 -0700792
793// --- InputMapper ---
794
795InputMapper::InputMapper(InputDevice* device) :
796 mDevice(device), mContext(device->getContext()) {
797}
798
799InputMapper::~InputMapper() {
800}
801
802void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
803 info->addSource(getSources());
804}
805
Jeff Brownef3d7e82010-09-30 14:33:04 -0700806void InputMapper::dump(String8& dump) {
807}
808
Jeff Brown6d0fec22010-07-23 21:28:06 -0700809void InputMapper::configure() {
810}
811
812void InputMapper::reset() {
813}
814
815int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
816 return AKEY_STATE_UNKNOWN;
817}
818
819int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
820 return AKEY_STATE_UNKNOWN;
821}
822
823int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
824 return AKEY_STATE_UNKNOWN;
825}
826
827bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
828 const int32_t* keyCodes, uint8_t* outFlags) {
829 return false;
830}
831
832int32_t InputMapper::getMetaState() {
833 return 0;
834}
835
Jeff Brown05dc66a2011-03-02 14:41:58 -0800836void InputMapper::fadePointer() {
837}
838
Jeff Browncb1404e2011-01-15 18:14:15 -0800839void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
840 const RawAbsoluteAxisInfo& axis, const char* name) {
841 if (axis.valid) {
842 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
843 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
844 } else {
845 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
846 }
847}
848
Jeff Brown6d0fec22010-07-23 21:28:06 -0700849
850// --- SwitchInputMapper ---
851
852SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
853 InputMapper(device) {
854}
855
856SwitchInputMapper::~SwitchInputMapper() {
857}
858
859uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -0800860 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700861}
862
863void SwitchInputMapper::process(const RawEvent* rawEvent) {
864 switch (rawEvent->type) {
865 case EV_SW:
866 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
867 break;
868 }
869}
870
871void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -0700872 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700873}
874
875int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
876 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
877}
878
879
880// --- KeyboardInputMapper ---
881
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800882KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brownefd32662011-03-08 15:13:06 -0800883 uint32_t source, int32_t keyboardType) :
884 InputMapper(device), mSource(source),
Jeff Brown6d0fec22010-07-23 21:28:06 -0700885 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700886 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700887}
888
889KeyboardInputMapper::~KeyboardInputMapper() {
890}
891
Jeff Brown6328cdc2010-07-29 18:18:33 -0700892void KeyboardInputMapper::initializeLocked() {
893 mLocked.metaState = AMETA_NONE;
894 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700895}
896
897uint32_t KeyboardInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -0800898 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700899}
900
901void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
902 InputMapper::populateDeviceInfo(info);
903
904 info->setKeyboardType(mKeyboardType);
905}
906
Jeff Brownef3d7e82010-09-30 14:33:04 -0700907void KeyboardInputMapper::dump(String8& dump) {
908 { // acquire lock
909 AutoMutex _l(mLock);
910 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800911 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -0700912 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
913 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
914 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
915 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
916 } // release lock
917}
918
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800919
920void KeyboardInputMapper::configure() {
921 InputMapper::configure();
922
923 // Configure basic parameters.
924 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800925
926 // Reset LEDs.
927 {
928 AutoMutex _l(mLock);
929 resetLedStateLocked();
930 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800931}
932
933void KeyboardInputMapper::configureParameters() {
934 mParameters.orientationAware = false;
935 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
936 mParameters.orientationAware);
937
938 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
939}
940
941void KeyboardInputMapper::dumpParameters(String8& dump) {
942 dump.append(INDENT3 "Parameters:\n");
943 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
944 mParameters.associatedDisplayId);
945 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
946 toString(mParameters.orientationAware));
947}
948
Jeff Brown6d0fec22010-07-23 21:28:06 -0700949void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -0700950 for (;;) {
951 int32_t keyCode, scanCode;
952 { // acquire lock
953 AutoMutex _l(mLock);
954
955 // Synthesize key up event on reset if keys are currently down.
956 if (mLocked.keyDowns.isEmpty()) {
957 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -0800958 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -0700959 break; // done
960 }
961
962 const KeyDown& keyDown = mLocked.keyDowns.top();
963 keyCode = keyDown.keyCode;
964 scanCode = keyDown.scanCode;
965 } // release lock
966
Jeff Brown6d0fec22010-07-23 21:28:06 -0700967 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -0700968 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700969 }
970
971 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700972 getContext()->updateGlobalMetaState();
973}
974
975void KeyboardInputMapper::process(const RawEvent* rawEvent) {
976 switch (rawEvent->type) {
977 case EV_KEY: {
978 int32_t scanCode = rawEvent->scanCode;
979 if (isKeyboardOrGamepadKey(scanCode)) {
980 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
981 rawEvent->flags);
982 }
983 break;
984 }
985 }
986}
987
988bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
989 return scanCode < BTN_MOUSE
990 || scanCode >= KEY_OK
Jeff Brown9e8e40c2011-03-03 03:39:29 -0800991 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
Jeff Browncb1404e2011-01-15 18:14:15 -0800992 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700993}
994
Jeff Brown6328cdc2010-07-29 18:18:33 -0700995void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
996 int32_t scanCode, uint32_t policyFlags) {
997 int32_t newMetaState;
998 nsecs_t downTime;
999 bool metaStateChanged = false;
1000
1001 { // acquire lock
1002 AutoMutex _l(mLock);
1003
1004 if (down) {
1005 // Rotate key codes according to orientation if needed.
1006 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001007 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001008 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001009 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1010 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001011 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001012 }
1013
1014 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001015 }
1016
Jeff Brown6328cdc2010-07-29 18:18:33 -07001017 // Add key down.
1018 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1019 if (keyDownIndex >= 0) {
1020 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001021 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001022 } else {
1023 // key down
Jeff Brownfe508922011-01-18 15:10:10 -08001024 if ((policyFlags & POLICY_FLAG_VIRTUAL)
1025 && mContext->shouldDropVirtualKey(when,
1026 getDevice(), keyCode, scanCode)) {
1027 return;
1028 }
1029
Jeff Brown6328cdc2010-07-29 18:18:33 -07001030 mLocked.keyDowns.push();
1031 KeyDown& keyDown = mLocked.keyDowns.editTop();
1032 keyDown.keyCode = keyCode;
1033 keyDown.scanCode = scanCode;
1034 }
1035
1036 mLocked.downTime = when;
1037 } else {
1038 // Remove key down.
1039 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1040 if (keyDownIndex >= 0) {
1041 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001042 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001043 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1044 } else {
1045 // key was not actually down
1046 LOGI("Dropping key up from device %s because the key was not down. "
1047 "keyCode=%d, scanCode=%d",
1048 getDeviceName().string(), keyCode, scanCode);
1049 return;
1050 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001051 }
1052
Jeff Brown6328cdc2010-07-29 18:18:33 -07001053 int32_t oldMetaState = mLocked.metaState;
1054 newMetaState = updateMetaState(keyCode, down, oldMetaState);
1055 if (oldMetaState != newMetaState) {
1056 mLocked.metaState = newMetaState;
1057 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -07001058 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001059 }
Jeff Brownfd035822010-06-30 16:10:35 -07001060
Jeff Brown6328cdc2010-07-29 18:18:33 -07001061 downTime = mLocked.downTime;
1062 } // release lock
1063
Jeff Brown56194eb2011-03-02 19:23:13 -08001064 // Key down on external an keyboard should wake the device.
1065 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1066 // For internal keyboards, the key layout file should specify the policy flags for
1067 // each wake key individually.
1068 // TODO: Use the input device configuration to control this behavior more finely.
1069 if (down && getDevice()->isExternal()
1070 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1071 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1072 }
1073
Jeff Brown6328cdc2010-07-29 18:18:33 -07001074 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001075 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001076 }
1077
Jeff Brown05dc66a2011-03-02 14:41:58 -08001078 if (down && !isMetaKey(keyCode)) {
1079 getContext()->fadePointer();
1080 }
1081
Jeff Brownefd32662011-03-08 15:13:06 -08001082 getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001083 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1084 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001085}
1086
Jeff Brown6328cdc2010-07-29 18:18:33 -07001087ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1088 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001089 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001090 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001091 return i;
1092 }
1093 }
1094 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001095}
1096
Jeff Brown6d0fec22010-07-23 21:28:06 -07001097int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1098 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1099}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001100
Jeff Brown6d0fec22010-07-23 21:28:06 -07001101int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1102 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1103}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001104
Jeff Brown6d0fec22010-07-23 21:28:06 -07001105bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1106 const int32_t* keyCodes, uint8_t* outFlags) {
1107 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1108}
1109
1110int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001111 { // acquire lock
1112 AutoMutex _l(mLock);
1113 return mLocked.metaState;
1114 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001115}
1116
Jeff Brown49ed71d2010-12-06 17:13:33 -08001117void KeyboardInputMapper::resetLedStateLocked() {
1118 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1119 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1120 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1121
1122 updateLedStateLocked(true);
1123}
1124
1125void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1126 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1127 ledState.on = false;
1128}
1129
Jeff Brown497a92c2010-09-12 17:55:08 -07001130void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1131 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001132 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001133 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001134 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001135 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001136 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001137}
1138
1139void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1140 int32_t led, int32_t modifier, bool reset) {
1141 if (ledState.avail) {
1142 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001143 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001144 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1145 ledState.on = desiredState;
1146 }
1147 }
1148}
1149
Jeff Brown6d0fec22010-07-23 21:28:06 -07001150
Jeff Brown83c09682010-12-23 17:50:18 -08001151// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001152
Jeff Brown83c09682010-12-23 17:50:18 -08001153CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001154 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001155 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001156}
1157
Jeff Brown83c09682010-12-23 17:50:18 -08001158CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001159}
1160
Jeff Brown83c09682010-12-23 17:50:18 -08001161uint32_t CursorInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001162 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001163}
1164
Jeff Brown83c09682010-12-23 17:50:18 -08001165void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001166 InputMapper::populateDeviceInfo(info);
1167
Jeff Brown83c09682010-12-23 17:50:18 -08001168 if (mParameters.mode == Parameters::MODE_POINTER) {
1169 float minX, minY, maxX, maxY;
1170 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brownefd32662011-03-08 15:13:06 -08001171 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
1172 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001173 }
1174 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001175 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
1176 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001177 }
Jeff Brownefd32662011-03-08 15:13:06 -08001178 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001179
1180 if (mHaveVWheel) {
Jeff Brownefd32662011-03-08 15:13:06 -08001181 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001182 }
1183 if (mHaveHWheel) {
Jeff Brownefd32662011-03-08 15:13:06 -08001184 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001185 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001186}
1187
Jeff Brown83c09682010-12-23 17:50:18 -08001188void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001189 { // acquire lock
1190 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001191 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001192 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001193 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1194 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001195 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1196 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001197 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1198 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1199 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1200 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001201 dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
1202 dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState)));
Jeff Brownef3d7e82010-09-30 14:33:04 -07001203 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1204 } // release lock
1205}
1206
Jeff Brown83c09682010-12-23 17:50:18 -08001207void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001208 InputMapper::configure();
1209
1210 // Configure basic parameters.
1211 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001212
1213 // Configure device mode.
1214 switch (mParameters.mode) {
1215 case Parameters::MODE_POINTER:
Jeff Brownefd32662011-03-08 15:13:06 -08001216 mSource = AINPUT_SOURCE_MOUSE;
Jeff Brown83c09682010-12-23 17:50:18 -08001217 mXPrecision = 1.0f;
1218 mYPrecision = 1.0f;
1219 mXScale = 1.0f;
1220 mYScale = 1.0f;
1221 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1222 break;
1223 case Parameters::MODE_NAVIGATION:
Jeff Brownefd32662011-03-08 15:13:06 -08001224 mSource = AINPUT_SOURCE_TRACKBALL;
Jeff Brown83c09682010-12-23 17:50:18 -08001225 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1226 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1227 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1228 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1229 break;
1230 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001231
1232 mVWheelScale = 1.0f;
1233 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001234
1235 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1236 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001237}
1238
Jeff Brown83c09682010-12-23 17:50:18 -08001239void CursorInputMapper::configureParameters() {
1240 mParameters.mode = Parameters::MODE_POINTER;
1241 String8 cursorModeString;
1242 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1243 if (cursorModeString == "navigation") {
1244 mParameters.mode = Parameters::MODE_NAVIGATION;
1245 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1246 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1247 }
1248 }
1249
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001250 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001251 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001252 mParameters.orientationAware);
1253
Jeff Brown83c09682010-12-23 17:50:18 -08001254 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1255 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001256}
1257
Jeff Brown83c09682010-12-23 17:50:18 -08001258void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001259 dump.append(INDENT3 "Parameters:\n");
1260 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1261 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001262
1263 switch (mParameters.mode) {
1264 case Parameters::MODE_POINTER:
1265 dump.append(INDENT4 "Mode: pointer\n");
1266 break;
1267 case Parameters::MODE_NAVIGATION:
1268 dump.append(INDENT4 "Mode: navigation\n");
1269 break;
1270 default:
1271 assert(false);
1272 }
1273
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001274 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1275 toString(mParameters.orientationAware));
1276}
1277
Jeff Brown83c09682010-12-23 17:50:18 -08001278void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001279 mAccumulator.clear();
1280
Jeff Brownefd32662011-03-08 15:13:06 -08001281 mLocked.buttonState = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001282 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001283}
1284
Jeff Brown83c09682010-12-23 17:50:18 -08001285void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001286 for (;;) {
Jeff Brownefd32662011-03-08 15:13:06 -08001287 uint32_t buttonState;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001288 { // acquire lock
1289 AutoMutex _l(mLock);
1290
Jeff Brownefd32662011-03-08 15:13:06 -08001291 buttonState = mLocked.buttonState;
1292 if (!buttonState) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001293 initializeLocked();
1294 break; // done
1295 }
1296 } // release lock
1297
Jeff Brown83c09682010-12-23 17:50:18 -08001298 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001299 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownefd32662011-03-08 15:13:06 -08001300 mAccumulator.clear();
1301 mAccumulator.buttonDown = 0;
1302 mAccumulator.buttonUp = buttonState;
1303 mAccumulator.fields = Accumulator::FIELD_BUTTONS;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001304 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001305 }
1306
Jeff Brown6d0fec22010-07-23 21:28:06 -07001307 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001308}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001309
Jeff Brown83c09682010-12-23 17:50:18 -08001310void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001311 switch (rawEvent->type) {
Jeff Brownefd32662011-03-08 15:13:06 -08001312 case EV_KEY: {
1313 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
1314 if (buttonState) {
1315 if (rawEvent->value) {
1316 mAccumulator.buttonDown = buttonState;
1317 mAccumulator.buttonUp = 0;
1318 } else {
1319 mAccumulator.buttonDown = 0;
1320 mAccumulator.buttonUp = buttonState;
1321 }
1322 mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
1323
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001324 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1325 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001326 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001327 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001328 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001329 break;
Jeff Brownefd32662011-03-08 15:13:06 -08001330 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001331
Jeff Brown6d0fec22010-07-23 21:28:06 -07001332 case EV_REL:
1333 switch (rawEvent->scanCode) {
1334 case REL_X:
1335 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1336 mAccumulator.relX = rawEvent->value;
1337 break;
1338 case REL_Y:
1339 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1340 mAccumulator.relY = rawEvent->value;
1341 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001342 case REL_WHEEL:
1343 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1344 mAccumulator.relWheel = rawEvent->value;
1345 break;
1346 case REL_HWHEEL:
1347 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1348 mAccumulator.relHWheel = rawEvent->value;
1349 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001350 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001351 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001352
Jeff Brown6d0fec22010-07-23 21:28:06 -07001353 case EV_SYN:
1354 switch (rawEvent->scanCode) {
1355 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001356 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001357 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001358 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001359 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001360 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001361}
1362
Jeff Brown83c09682010-12-23 17:50:18 -08001363void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001364 uint32_t fields = mAccumulator.fields;
1365 if (fields == 0) {
1366 return; // no new state changes, so nothing to do
1367 }
1368
Jeff Brown9626b142011-03-03 02:09:54 -08001369 int32_t motionEventAction;
1370 int32_t motionEventEdgeFlags;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001371 PointerCoords pointerCoords;
1372 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001373 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001374 { // acquire lock
1375 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001376
Jeff Brownefd32662011-03-08 15:13:06 -08001377 bool down, downChanged;
1378 bool wasDown = isPointerDown(mLocked.buttonState);
1379 bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
1380 if (buttonsChanged) {
1381 mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
1382 & ~mAccumulator.buttonUp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001383
Jeff Brownefd32662011-03-08 15:13:06 -08001384 down = isPointerDown(mLocked.buttonState);
1385
1386 if (!wasDown && down) {
1387 mLocked.downTime = when;
1388 downChanged = true;
1389 } else if (wasDown && !down) {
1390 downChanged = true;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001391 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001392 downChanged = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001393 }
Jeff Brownefd32662011-03-08 15:13:06 -08001394 } else {
1395 down = wasDown;
1396 downChanged = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001397 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001398
Jeff Brown6328cdc2010-07-29 18:18:33 -07001399 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001400 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1401 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001402
Jeff Brown6328cdc2010-07-29 18:18:33 -07001403 if (downChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08001404 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1405 } else if (down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001406 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001407 } else {
1408 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001409 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001410
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001411 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001412 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001413 // Rotate motion based on display orientation if needed.
1414 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1415 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001416 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1417 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001418 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001419 }
1420
1421 float temp;
1422 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001423 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001424 temp = deltaX;
1425 deltaX = deltaY;
1426 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001427 break;
1428
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001429 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001430 deltaX = -deltaX;
1431 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001432 break;
1433
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001434 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001435 temp = deltaX;
1436 deltaX = -deltaY;
1437 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001438 break;
1439 }
1440 }
Jeff Brown83c09682010-12-23 17:50:18 -08001441
Jeff Brown91c69ab2011-02-14 17:03:18 -08001442 pointerCoords.clear();
1443
Jeff Brown9626b142011-03-03 02:09:54 -08001444 motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
1445
Jeff Brown83c09682010-12-23 17:50:18 -08001446 if (mPointerController != NULL) {
1447 mPointerController->move(deltaX, deltaY);
Jeff Brownefd32662011-03-08 15:13:06 -08001448 if (buttonsChanged) {
1449 mPointerController->setButtonState(mLocked.buttonState);
Jeff Brown83c09682010-12-23 17:50:18 -08001450 }
Jeff Brownefd32662011-03-08 15:13:06 -08001451
Jeff Brown91c69ab2011-02-14 17:03:18 -08001452 float x, y;
1453 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001454 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1455 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown9626b142011-03-03 02:09:54 -08001456
1457 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownefd32662011-03-08 15:13:06 -08001458 motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds(
1459 mPointerController, x, y);
Jeff Brown9626b142011-03-03 02:09:54 -08001460 }
Jeff Brown83c09682010-12-23 17:50:18 -08001461 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001462 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1463 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001464 }
1465
Jeff Brownefd32662011-03-08 15:13:06 -08001466 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001467
1468 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001469 vscroll = mAccumulator.relWheel;
1470 } else {
1471 vscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001472 }
1473 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
Jeff Brown33bbfd22011-02-24 20:55:35 -08001474 hscroll = mAccumulator.relHWheel;
1475 } else {
1476 hscroll = 0;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001477 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001478 if (hscroll != 0 || vscroll != 0) {
1479 mPointerController->unfade();
1480 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001481 } // release lock
1482
Jeff Brown56194eb2011-03-02 19:23:13 -08001483 // Moving an external trackball or mouse should wake the device.
1484 // We don't do this for internal cursor devices to prevent them from waking up
1485 // the device in your pocket.
1486 // TODO: Use the input device configuration to control this behavior more finely.
1487 uint32_t policyFlags = 0;
1488 if (getDevice()->isExternal()) {
1489 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1490 }
1491
Jeff Brown6d0fec22010-07-23 21:28:06 -07001492 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001493 int32_t pointerId = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08001494 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brown9626b142011-03-03 02:09:54 -08001495 motionEventAction, 0, metaState, motionEventEdgeFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001496 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1497
1498 mAccumulator.clear();
Jeff Brown33bbfd22011-02-24 20:55:35 -08001499
1500 if (vscroll != 0 || hscroll != 0) {
1501 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1502 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1503
Jeff Brownefd32662011-03-08 15:13:06 -08001504 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brown33bbfd22011-02-24 20:55:35 -08001505 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1506 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1507 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001508}
1509
Jeff Brown83c09682010-12-23 17:50:18 -08001510int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001511 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1512 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1513 } else {
1514 return AKEY_STATE_UNKNOWN;
1515 }
1516}
1517
Jeff Brown05dc66a2011-03-02 14:41:58 -08001518void CursorInputMapper::fadePointer() {
1519 { // acquire lock
1520 AutoMutex _l(mLock);
Jeff Brownefd32662011-03-08 15:13:06 -08001521 if (mPointerController != NULL) {
1522 mPointerController->fade();
1523 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001524 } // release lock
1525}
1526
Jeff Brown6d0fec22010-07-23 21:28:06 -07001527
1528// --- TouchInputMapper ---
1529
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001530TouchInputMapper::TouchInputMapper(InputDevice* device) :
1531 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001532 mLocked.surfaceOrientation = -1;
1533 mLocked.surfaceWidth = -1;
1534 mLocked.surfaceHeight = -1;
1535
1536 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001537}
1538
1539TouchInputMapper::~TouchInputMapper() {
1540}
1541
1542uint32_t TouchInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001543 return mTouchSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001544}
1545
1546void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1547 InputMapper::populateDeviceInfo(info);
1548
Jeff Brown6328cdc2010-07-29 18:18:33 -07001549 { // acquire lock
1550 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001551
Jeff Brown6328cdc2010-07-29 18:18:33 -07001552 // Ensure surface information is up to date so that orientation changes are
1553 // noticed immediately.
Jeff Brownefd32662011-03-08 15:13:06 -08001554 if (!configureSurfaceLocked()) {
1555 return;
1556 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001557
Jeff Brownefd32662011-03-08 15:13:06 -08001558 info->addMotionRange(mLocked.orientedRanges.x);
1559 info->addMotionRange(mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001560
1561 if (mLocked.orientedRanges.havePressure) {
Jeff Brownefd32662011-03-08 15:13:06 -08001562 info->addMotionRange(mLocked.orientedRanges.pressure);
Jeff Brown8d608662010-08-30 03:02:23 -07001563 }
1564
1565 if (mLocked.orientedRanges.haveSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001566 info->addMotionRange(mLocked.orientedRanges.size);
Jeff Brown8d608662010-08-30 03:02:23 -07001567 }
1568
Jeff Brownc6d282b2010-10-14 21:42:15 -07001569 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001570 info->addMotionRange(mLocked.orientedRanges.touchMajor);
1571 info->addMotionRange(mLocked.orientedRanges.touchMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07001572 }
1573
Jeff Brownc6d282b2010-10-14 21:42:15 -07001574 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001575 info->addMotionRange(mLocked.orientedRanges.toolMajor);
1576 info->addMotionRange(mLocked.orientedRanges.toolMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07001577 }
1578
1579 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brownefd32662011-03-08 15:13:06 -08001580 info->addMotionRange(mLocked.orientedRanges.orientation);
Jeff Brown8d608662010-08-30 03:02:23 -07001581 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001582 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001583}
1584
Jeff Brownef3d7e82010-09-30 14:33:04 -07001585void TouchInputMapper::dump(String8& dump) {
1586 { // acquire lock
1587 AutoMutex _l(mLock);
1588 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001589 dumpParameters(dump);
1590 dumpVirtualKeysLocked(dump);
1591 dumpRawAxes(dump);
1592 dumpCalibration(dump);
1593 dumpSurfaceLocked(dump);
Jeff Brownefd32662011-03-08 15:13:06 -08001594
Jeff Brown511ee5f2010-10-18 13:32:20 -07001595 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001596 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1597 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1598 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1599 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1600 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1601 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1602 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1603 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1604 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1605 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1606 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001607 dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale);
1608
1609 dump.appendFormat(INDENT3 "Last Touch:\n");
1610 dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001611 } // release lock
1612}
1613
Jeff Brown6328cdc2010-07-29 18:18:33 -07001614void TouchInputMapper::initializeLocked() {
1615 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001616 mLastTouch.clear();
1617 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001618
1619 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1620 mAveragingTouchFilter.historyStart[i] = 0;
1621 mAveragingTouchFilter.historyEnd[i] = 0;
1622 }
1623
1624 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001625
1626 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001627
1628 mLocked.orientedRanges.havePressure = false;
1629 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001630 mLocked.orientedRanges.haveTouchSize = false;
1631 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001632 mLocked.orientedRanges.haveOrientation = false;
1633}
1634
Jeff Brown6d0fec22010-07-23 21:28:06 -07001635void TouchInputMapper::configure() {
1636 InputMapper::configure();
1637
1638 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001639 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001640
Jeff Brown83c09682010-12-23 17:50:18 -08001641 // Configure sources.
1642 switch (mParameters.deviceType) {
1643 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
Jeff Brownefd32662011-03-08 15:13:06 -08001644 mTouchSource = AINPUT_SOURCE_TOUCHSCREEN;
Jeff Brown83c09682010-12-23 17:50:18 -08001645 break;
1646 case Parameters::DEVICE_TYPE_TOUCH_PAD:
Jeff Brownefd32662011-03-08 15:13:06 -08001647 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
Jeff Brown83c09682010-12-23 17:50:18 -08001648 break;
1649 default:
1650 assert(false);
1651 }
1652
Jeff Brown6d0fec22010-07-23 21:28:06 -07001653 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001654 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001655
1656 // Prepare input device calibration.
1657 parseCalibration();
1658 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001659
Jeff Brown6328cdc2010-07-29 18:18:33 -07001660 { // acquire lock
1661 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001662
Jeff Brown8d608662010-08-30 03:02:23 -07001663 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001664 configureSurfaceLocked();
1665 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001666}
1667
Jeff Brown8d608662010-08-30 03:02:23 -07001668void TouchInputMapper::configureParameters() {
1669 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1670 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1671 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001672 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001673
1674 String8 deviceTypeString;
Jeff Brown58a2da82011-01-25 16:02:22 -08001675 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001676 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1677 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001678 if (deviceTypeString == "touchScreen") {
1679 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brownefd32662011-03-08 15:13:06 -08001680 } else if (deviceTypeString == "touchPad") {
1681 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1682 } else {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001683 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1684 }
1685 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001686
Jeff Brownefd32662011-03-08 15:13:06 -08001687 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001688 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1689 mParameters.orientationAware);
1690
Jeff Brownefd32662011-03-08 15:13:06 -08001691 mParameters.associatedDisplayId = mParameters.orientationAware
1692 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
1693 ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001694}
1695
Jeff Brownef3d7e82010-09-30 14:33:04 -07001696void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001697 dump.append(INDENT3 "Parameters:\n");
1698
1699 switch (mParameters.deviceType) {
1700 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1701 dump.append(INDENT4 "DeviceType: touchScreen\n");
1702 break;
1703 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1704 dump.append(INDENT4 "DeviceType: touchPad\n");
1705 break;
1706 default:
1707 assert(false);
1708 }
1709
1710 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1711 mParameters.associatedDisplayId);
1712 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1713 toString(mParameters.orientationAware));
1714
1715 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001716 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001717 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001718 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001719 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001720 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001721}
1722
Jeff Brown8d608662010-08-30 03:02:23 -07001723void TouchInputMapper::configureRawAxes() {
1724 mRawAxes.x.clear();
1725 mRawAxes.y.clear();
1726 mRawAxes.pressure.clear();
1727 mRawAxes.touchMajor.clear();
1728 mRawAxes.touchMinor.clear();
1729 mRawAxes.toolMajor.clear();
1730 mRawAxes.toolMinor.clear();
1731 mRawAxes.orientation.clear();
1732}
1733
Jeff Brownef3d7e82010-09-30 14:33:04 -07001734void TouchInputMapper::dumpRawAxes(String8& dump) {
1735 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001736 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1737 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1738 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1739 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1740 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1741 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1742 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1743 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001744}
1745
Jeff Brown6328cdc2010-07-29 18:18:33 -07001746bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown9626b142011-03-03 02:09:54 -08001747 // Ensure we have valid X and Y axes.
1748 if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
1749 LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
1750 "The device will be inoperable.", getDeviceName().string());
1751 return false;
1752 }
1753
Jeff Brown6d0fec22010-07-23 21:28:06 -07001754 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001755 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown9626b142011-03-03 02:09:54 -08001756 int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
1757 int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001758
1759 if (mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001760 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001761 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
Jeff Brownefd32662011-03-08 15:13:06 -08001762 &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
1763 &mLocked.associatedDisplayOrientation)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001764 return false;
1765 }
Jeff Brownefd32662011-03-08 15:13:06 -08001766
1767 // A touch screen inherits the dimensions of the display.
1768 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
1769 width = mLocked.associatedDisplayWidth;
1770 height = mLocked.associatedDisplayHeight;
1771 }
1772
1773 // The device inherits the orientation of the display if it is orientation aware.
1774 if (mParameters.orientationAware) {
1775 orientation = mLocked.associatedDisplayOrientation;
1776 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001777 }
1778
Jeff Brown6328cdc2010-07-29 18:18:33 -07001779 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001780 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001781 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001782 }
1783
Jeff Brown6328cdc2010-07-29 18:18:33 -07001784 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001785 if (sizeChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08001786 LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001787 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07001788
Jeff Brown6328cdc2010-07-29 18:18:33 -07001789 mLocked.surfaceWidth = width;
1790 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001791
Jeff Brown8d608662010-08-30 03:02:23 -07001792 // Configure X and Y factors.
Jeff Brown9626b142011-03-03 02:09:54 -08001793 mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
1794 mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
1795 mLocked.xPrecision = 1.0f / mLocked.xScale;
1796 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001797
Jeff Brownefd32662011-03-08 15:13:06 -08001798 mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
1799 mLocked.orientedRanges.x.source = mTouchSource;
1800 mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
1801 mLocked.orientedRanges.y.source = mTouchSource;
1802
Jeff Brown9626b142011-03-03 02:09:54 -08001803 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001804
Jeff Brown8d608662010-08-30 03:02:23 -07001805 // Scale factor for terms that are not oriented in a particular axis.
1806 // If the pixels are square then xScale == yScale otherwise we fake it
1807 // by choosing an average.
1808 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001809
Jeff Brown8d608662010-08-30 03:02:23 -07001810 // Size of diagonal axis.
1811 float diagonalSize = pythag(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001812
Jeff Brown8d608662010-08-30 03:02:23 -07001813 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001814 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
1815 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08001816
1817 mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
1818 mLocked.orientedRanges.touchMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07001819 mLocked.orientedRanges.touchMajor.min = 0;
1820 mLocked.orientedRanges.touchMajor.max = diagonalSize;
1821 mLocked.orientedRanges.touchMajor.flat = 0;
1822 mLocked.orientedRanges.touchMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08001823
Jeff Brown8d608662010-08-30 03:02:23 -07001824 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08001825 mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001826 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001827
Jeff Brown8d608662010-08-30 03:02:23 -07001828 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001829 mLocked.toolSizeLinearScale = 0;
1830 mLocked.toolSizeLinearBias = 0;
1831 mLocked.toolSizeAreaScale = 0;
1832 mLocked.toolSizeAreaBias = 0;
1833 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
1834 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
1835 if (mCalibration.haveToolSizeLinearScale) {
1836 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07001837 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07001838 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07001839 / mRawAxes.toolMajor.maxValue;
1840 }
1841
Jeff Brownc6d282b2010-10-14 21:42:15 -07001842 if (mCalibration.haveToolSizeLinearBias) {
1843 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1844 }
1845 } else if (mCalibration.toolSizeCalibration ==
1846 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
1847 if (mCalibration.haveToolSizeLinearScale) {
1848 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
1849 } else {
1850 mLocked.toolSizeLinearScale = min(width, height);
1851 }
1852
1853 if (mCalibration.haveToolSizeLinearBias) {
1854 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
1855 }
1856
1857 if (mCalibration.haveToolSizeAreaScale) {
1858 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
1859 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1860 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
1861 }
1862
1863 if (mCalibration.haveToolSizeAreaBias) {
1864 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07001865 }
1866 }
1867
Jeff Brownc6d282b2010-10-14 21:42:15 -07001868 mLocked.orientedRanges.haveToolSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08001869
1870 mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
1871 mLocked.orientedRanges.toolMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07001872 mLocked.orientedRanges.toolMajor.min = 0;
1873 mLocked.orientedRanges.toolMajor.max = diagonalSize;
1874 mLocked.orientedRanges.toolMajor.flat = 0;
1875 mLocked.orientedRanges.toolMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08001876
Jeff Brown8d608662010-08-30 03:02:23 -07001877 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08001878 mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07001879 }
1880
1881 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001882 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001883 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
1884 RawAbsoluteAxisInfo rawPressureAxis;
1885 switch (mCalibration.pressureSource) {
1886 case Calibration::PRESSURE_SOURCE_PRESSURE:
1887 rawPressureAxis = mRawAxes.pressure;
1888 break;
1889 case Calibration::PRESSURE_SOURCE_TOUCH:
1890 rawPressureAxis = mRawAxes.touchMajor;
1891 break;
1892 default:
1893 rawPressureAxis.clear();
1894 }
1895
Jeff Brown8d608662010-08-30 03:02:23 -07001896 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
1897 || mCalibration.pressureCalibration
1898 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
1899 if (mCalibration.havePressureScale) {
1900 mLocked.pressureScale = mCalibration.pressureScale;
1901 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
1902 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
1903 }
1904 }
1905
1906 mLocked.orientedRanges.havePressure = true;
Jeff Brownefd32662011-03-08 15:13:06 -08001907
1908 mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
1909 mLocked.orientedRanges.pressure.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07001910 mLocked.orientedRanges.pressure.min = 0;
1911 mLocked.orientedRanges.pressure.max = 1.0;
1912 mLocked.orientedRanges.pressure.flat = 0;
1913 mLocked.orientedRanges.pressure.fuzz = 0;
1914 }
1915
1916 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07001917 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001918 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001919 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
1920 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
1921 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
1922 }
1923 }
1924
1925 mLocked.orientedRanges.haveSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08001926
1927 mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
1928 mLocked.orientedRanges.size.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07001929 mLocked.orientedRanges.size.min = 0;
1930 mLocked.orientedRanges.size.max = 1.0;
1931 mLocked.orientedRanges.size.flat = 0;
1932 mLocked.orientedRanges.size.fuzz = 0;
1933 }
1934
1935 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07001936 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07001937 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07001938 if (mCalibration.orientationCalibration
1939 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
1940 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
1941 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
1942 }
1943 }
1944
Jeff Brownefd32662011-03-08 15:13:06 -08001945 mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
1946 mLocked.orientedRanges.orientation.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07001947 mLocked.orientedRanges.orientation.min = - M_PI_2;
1948 mLocked.orientedRanges.orientation.max = M_PI_2;
1949 mLocked.orientedRanges.orientation.flat = 0;
1950 mLocked.orientedRanges.orientation.fuzz = 0;
1951 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001952 }
1953
1954 if (orientationChanged || sizeChanged) {
Jeff Brown9626b142011-03-03 02:09:54 -08001955 // Compute oriented surface dimensions, precision, scales and ranges.
1956 // Note that the maximum value reported is an inclusive maximum value so it is one
1957 // unit less than the total width or height of surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001958 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001959 case DISPLAY_ORIENTATION_90:
1960 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001961 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
1962 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
Jeff Brown9626b142011-03-03 02:09:54 -08001963
Jeff Brown6328cdc2010-07-29 18:18:33 -07001964 mLocked.orientedXPrecision = mLocked.yPrecision;
1965 mLocked.orientedYPrecision = mLocked.xPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08001966
1967 mLocked.orientedRanges.x.min = 0;
1968 mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
1969 * mLocked.yScale;
1970 mLocked.orientedRanges.x.flat = 0;
1971 mLocked.orientedRanges.x.fuzz = mLocked.yScale;
1972
1973 mLocked.orientedRanges.y.min = 0;
1974 mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
1975 * mLocked.xScale;
1976 mLocked.orientedRanges.y.flat = 0;
1977 mLocked.orientedRanges.y.fuzz = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001978 break;
Jeff Brown9626b142011-03-03 02:09:54 -08001979
Jeff Brown6d0fec22010-07-23 21:28:06 -07001980 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07001981 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
1982 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
Jeff Brown9626b142011-03-03 02:09:54 -08001983
Jeff Brown6328cdc2010-07-29 18:18:33 -07001984 mLocked.orientedXPrecision = mLocked.xPrecision;
1985 mLocked.orientedYPrecision = mLocked.yPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08001986
1987 mLocked.orientedRanges.x.min = 0;
1988 mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
1989 * mLocked.xScale;
1990 mLocked.orientedRanges.x.flat = 0;
1991 mLocked.orientedRanges.x.fuzz = mLocked.xScale;
1992
1993 mLocked.orientedRanges.y.min = 0;
1994 mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
1995 * mLocked.yScale;
1996 mLocked.orientedRanges.y.flat = 0;
1997 mLocked.orientedRanges.y.fuzz = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001998 break;
1999 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002000 }
2001
2002 return true;
2003}
2004
Jeff Brownef3d7e82010-09-30 14:33:04 -07002005void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
2006 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
2007 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
2008 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07002009}
2010
Jeff Brown6328cdc2010-07-29 18:18:33 -07002011void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07002012 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08002013 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002014
Jeff Brown6328cdc2010-07-29 18:18:33 -07002015 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002016
Jeff Brown6328cdc2010-07-29 18:18:33 -07002017 if (virtualKeyDefinitions.size() == 0) {
2018 return;
2019 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002020
Jeff Brown6328cdc2010-07-29 18:18:33 -07002021 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
2022
Jeff Brown8d608662010-08-30 03:02:23 -07002023 int32_t touchScreenLeft = mRawAxes.x.minValue;
2024 int32_t touchScreenTop = mRawAxes.y.minValue;
Jeff Brown9626b142011-03-03 02:09:54 -08002025 int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2026 int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002027
2028 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07002029 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07002030 virtualKeyDefinitions[i];
2031
2032 mLocked.virtualKeys.add();
2033 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
2034
2035 virtualKey.scanCode = virtualKeyDefinition.scanCode;
2036 int32_t keyCode;
2037 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08002038 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002039 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002040 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
2041 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002042 mLocked.virtualKeys.pop(); // drop the key
2043 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002044 }
2045
Jeff Brown6328cdc2010-07-29 18:18:33 -07002046 virtualKey.keyCode = keyCode;
2047 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002048
Jeff Brown6328cdc2010-07-29 18:18:33 -07002049 // convert the key definition's display coordinates into touch coordinates for a hit box
2050 int32_t halfWidth = virtualKeyDefinition.width / 2;
2051 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002052
Jeff Brown6328cdc2010-07-29 18:18:33 -07002053 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
2054 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2055 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
2056 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2057 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
2058 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2059 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
2060 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brownef3d7e82010-09-30 14:33:04 -07002061 }
2062}
2063
2064void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
2065 if (!mLocked.virtualKeys.isEmpty()) {
2066 dump.append(INDENT3 "Virtual Keys:\n");
2067
2068 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
2069 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
2070 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
2071 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
2072 i, virtualKey.scanCode, virtualKey.keyCode,
2073 virtualKey.hitLeft, virtualKey.hitRight,
2074 virtualKey.hitTop, virtualKey.hitBottom);
2075 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002076 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002077}
2078
Jeff Brown8d608662010-08-30 03:02:23 -07002079void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002080 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07002081 Calibration& out = mCalibration;
2082
Jeff Brownc6d282b2010-10-14 21:42:15 -07002083 // Touch Size
2084 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2085 String8 touchSizeCalibrationString;
2086 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2087 if (touchSizeCalibrationString == "none") {
2088 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2089 } else if (touchSizeCalibrationString == "geometric") {
2090 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2091 } else if (touchSizeCalibrationString == "pressure") {
2092 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2093 } else if (touchSizeCalibrationString != "default") {
2094 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2095 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002096 }
2097 }
2098
Jeff Brownc6d282b2010-10-14 21:42:15 -07002099 // Tool Size
2100 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2101 String8 toolSizeCalibrationString;
2102 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2103 if (toolSizeCalibrationString == "none") {
2104 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2105 } else if (toolSizeCalibrationString == "geometric") {
2106 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2107 } else if (toolSizeCalibrationString == "linear") {
2108 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2109 } else if (toolSizeCalibrationString == "area") {
2110 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2111 } else if (toolSizeCalibrationString != "default") {
2112 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2113 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002114 }
2115 }
2116
Jeff Brownc6d282b2010-10-14 21:42:15 -07002117 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2118 out.toolSizeLinearScale);
2119 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2120 out.toolSizeLinearBias);
2121 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2122 out.toolSizeAreaScale);
2123 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2124 out.toolSizeAreaBias);
2125 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2126 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07002127
2128 // Pressure
2129 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2130 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002131 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002132 if (pressureCalibrationString == "none") {
2133 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2134 } else if (pressureCalibrationString == "physical") {
2135 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2136 } else if (pressureCalibrationString == "amplitude") {
2137 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2138 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002139 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002140 pressureCalibrationString.string());
2141 }
2142 }
2143
2144 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2145 String8 pressureSourceString;
2146 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2147 if (pressureSourceString == "pressure") {
2148 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2149 } else if (pressureSourceString == "touch") {
2150 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2151 } else if (pressureSourceString != "default") {
2152 LOGW("Invalid value for touch.pressure.source: '%s'",
2153 pressureSourceString.string());
2154 }
2155 }
2156
2157 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2158 out.pressureScale);
2159
2160 // Size
2161 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2162 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002163 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002164 if (sizeCalibrationString == "none") {
2165 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2166 } else if (sizeCalibrationString == "normalized") {
2167 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2168 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002169 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002170 sizeCalibrationString.string());
2171 }
2172 }
2173
2174 // Orientation
2175 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2176 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002177 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002178 if (orientationCalibrationString == "none") {
2179 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2180 } else if (orientationCalibrationString == "interpolated") {
2181 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002182 } else if (orientationCalibrationString == "vector") {
2183 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002184 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002185 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002186 orientationCalibrationString.string());
2187 }
2188 }
2189}
2190
2191void TouchInputMapper::resolveCalibration() {
2192 // Pressure
2193 switch (mCalibration.pressureSource) {
2194 case Calibration::PRESSURE_SOURCE_DEFAULT:
2195 if (mRawAxes.pressure.valid) {
2196 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2197 } else if (mRawAxes.touchMajor.valid) {
2198 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2199 }
2200 break;
2201
2202 case Calibration::PRESSURE_SOURCE_PRESSURE:
2203 if (! mRawAxes.pressure.valid) {
2204 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2205 "the pressure axis is not available.");
2206 }
2207 break;
2208
2209 case Calibration::PRESSURE_SOURCE_TOUCH:
2210 if (! mRawAxes.touchMajor.valid) {
2211 LOGW("Calibration property touch.pressure.source is 'touch' but "
2212 "the touchMajor axis is not available.");
2213 }
2214 break;
2215
2216 default:
2217 break;
2218 }
2219
2220 switch (mCalibration.pressureCalibration) {
2221 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2222 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2223 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2224 } else {
2225 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2226 }
2227 break;
2228
2229 default:
2230 break;
2231 }
2232
Jeff Brownc6d282b2010-10-14 21:42:15 -07002233 // Tool Size
2234 switch (mCalibration.toolSizeCalibration) {
2235 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002236 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002237 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002238 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002239 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002240 }
2241 break;
2242
2243 default:
2244 break;
2245 }
2246
Jeff Brownc6d282b2010-10-14 21:42:15 -07002247 // Touch Size
2248 switch (mCalibration.touchSizeCalibration) {
2249 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002250 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002251 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2252 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002253 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002254 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002255 }
2256 break;
2257
2258 default:
2259 break;
2260 }
2261
2262 // Size
2263 switch (mCalibration.sizeCalibration) {
2264 case Calibration::SIZE_CALIBRATION_DEFAULT:
2265 if (mRawAxes.toolMajor.valid) {
2266 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2267 } else {
2268 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2269 }
2270 break;
2271
2272 default:
2273 break;
2274 }
2275
2276 // Orientation
2277 switch (mCalibration.orientationCalibration) {
2278 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2279 if (mRawAxes.orientation.valid) {
2280 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2281 } else {
2282 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2283 }
2284 break;
2285
2286 default:
2287 break;
2288 }
2289}
2290
Jeff Brownef3d7e82010-09-30 14:33:04 -07002291void TouchInputMapper::dumpCalibration(String8& dump) {
2292 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002293
Jeff Brownc6d282b2010-10-14 21:42:15 -07002294 // Touch Size
2295 switch (mCalibration.touchSizeCalibration) {
2296 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2297 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002298 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002299 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2300 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002301 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002302 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2303 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002304 break;
2305 default:
2306 assert(false);
2307 }
2308
Jeff Brownc6d282b2010-10-14 21:42:15 -07002309 // Tool Size
2310 switch (mCalibration.toolSizeCalibration) {
2311 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2312 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002313 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002314 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2315 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002316 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002317 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2318 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2319 break;
2320 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2321 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002322 break;
2323 default:
2324 assert(false);
2325 }
2326
Jeff Brownc6d282b2010-10-14 21:42:15 -07002327 if (mCalibration.haveToolSizeLinearScale) {
2328 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2329 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002330 }
2331
Jeff Brownc6d282b2010-10-14 21:42:15 -07002332 if (mCalibration.haveToolSizeLinearBias) {
2333 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2334 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002335 }
2336
Jeff Brownc6d282b2010-10-14 21:42:15 -07002337 if (mCalibration.haveToolSizeAreaScale) {
2338 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2339 mCalibration.toolSizeAreaScale);
2340 }
2341
2342 if (mCalibration.haveToolSizeAreaBias) {
2343 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2344 mCalibration.toolSizeAreaBias);
2345 }
2346
2347 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002348 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002349 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002350 }
2351
2352 // Pressure
2353 switch (mCalibration.pressureCalibration) {
2354 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002355 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002356 break;
2357 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002358 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002359 break;
2360 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002361 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002362 break;
2363 default:
2364 assert(false);
2365 }
2366
2367 switch (mCalibration.pressureSource) {
2368 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002369 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002370 break;
2371 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002372 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002373 break;
2374 case Calibration::PRESSURE_SOURCE_DEFAULT:
2375 break;
2376 default:
2377 assert(false);
2378 }
2379
2380 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002381 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2382 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002383 }
2384
2385 // Size
2386 switch (mCalibration.sizeCalibration) {
2387 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002388 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002389 break;
2390 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002391 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002392 break;
2393 default:
2394 assert(false);
2395 }
2396
2397 // Orientation
2398 switch (mCalibration.orientationCalibration) {
2399 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002400 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002401 break;
2402 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002403 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002404 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002405 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2406 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2407 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002408 default:
2409 assert(false);
2410 }
2411}
2412
Jeff Brown6d0fec22010-07-23 21:28:06 -07002413void TouchInputMapper::reset() {
2414 // Synthesize touch up event if touch is currently down.
2415 // This will also take care of finishing virtual key processing if needed.
2416 if (mLastTouch.pointerCount != 0) {
2417 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2418 mCurrentTouch.clear();
2419 syncTouch(when, true);
2420 }
2421
Jeff Brown6328cdc2010-07-29 18:18:33 -07002422 { // acquire lock
2423 AutoMutex _l(mLock);
2424 initializeLocked();
2425 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002426
Jeff Brown6328cdc2010-07-29 18:18:33 -07002427 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002428}
2429
2430void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002431 // Preprocess pointer data.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002432 if (mParameters.useBadTouchFilter) {
2433 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002434 havePointerIds = false;
2435 }
2436 }
2437
Jeff Brown6d0fec22010-07-23 21:28:06 -07002438 if (mParameters.useJumpyTouchFilter) {
2439 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002440 havePointerIds = false;
2441 }
2442 }
2443
2444 if (! havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002445 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002446 }
2447
Jeff Brown6d0fec22010-07-23 21:28:06 -07002448 TouchData temp;
2449 TouchData* savedTouch;
2450 if (mParameters.useAveragingTouchFilter) {
2451 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002452 savedTouch = & temp;
2453
Jeff Brown6d0fec22010-07-23 21:28:06 -07002454 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002455 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002456 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002457 }
2458
Jeff Brown56194eb2011-03-02 19:23:13 -08002459 uint32_t policyFlags = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -08002460 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brownefd32662011-03-08 15:13:06 -08002461 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2462 // If this is a touch screen, hide the pointer on an initial down.
2463 getContext()->fadePointer();
2464 }
Jeff Brown56194eb2011-03-02 19:23:13 -08002465
2466 // Initial downs on external touch devices should wake the device.
2467 // We don't do this for internal touch screens to prevent them from waking
2468 // up in your pocket.
2469 // TODO: Use the input device configuration to control this behavior more finely.
2470 if (getDevice()->isExternal()) {
2471 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2472 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002473 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002474
Jeff Brown05dc66a2011-03-02 14:41:58 -08002475 // Process touches and virtual keys.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002476 TouchResult touchResult = consumeOffScreenTouches(when, policyFlags);
2477 if (touchResult == DISPATCH_TOUCH) {
Jeff Brownefd32662011-03-08 15:13:06 -08002478 suppressSwipeOntoVirtualKeys(when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002479 dispatchTouches(when, policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002480 }
2481
Jeff Brown6328cdc2010-07-29 18:18:33 -07002482 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002483 if (touchResult == DROP_STROKE) {
2484 mLastTouch.clear();
2485 } else {
2486 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002487 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002488}
2489
Jeff Brown6d0fec22010-07-23 21:28:06 -07002490TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2491 nsecs_t when, uint32_t policyFlags) {
2492 int32_t keyEventAction, keyEventFlags;
2493 int32_t keyCode, scanCode, downTime;
2494 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002495
Jeff Brown6328cdc2010-07-29 18:18:33 -07002496 { // acquire lock
2497 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002498
Jeff Brown6328cdc2010-07-29 18:18:33 -07002499 // Update surface size and orientation, including virtual key positions.
2500 if (! configureSurfaceLocked()) {
2501 return DROP_STROKE;
2502 }
2503
2504 // Check for virtual key press.
2505 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002506 if (mCurrentTouch.pointerCount == 0) {
2507 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002508 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002509#if DEBUG_VIRTUAL_KEYS
2510 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002511 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002512#endif
2513 keyEventAction = AKEY_EVENT_ACTION_UP;
2514 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2515 touchResult = SKIP_TOUCH;
2516 goto DispatchVirtualKey;
2517 }
2518
2519 if (mCurrentTouch.pointerCount == 1) {
2520 int32_t x = mCurrentTouch.pointers[0].x;
2521 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002522 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2523 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002524 // Pointer is still within the space of the virtual key.
2525 return SKIP_TOUCH;
2526 }
2527 }
2528
2529 // Pointer left virtual key area or another pointer also went down.
2530 // Send key cancellation and drop the stroke so subsequent motions will be
2531 // considered fresh downs. This is useful when the user swipes away from the
2532 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002533 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002534#if DEBUG_VIRTUAL_KEYS
2535 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002536 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002537#endif
2538 keyEventAction = AKEY_EVENT_ACTION_UP;
2539 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2540 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002541
2542 // Check whether the pointer moved inside the display area where we should
2543 // start a new stroke.
2544 int32_t x = mCurrentTouch.pointers[0].x;
2545 int32_t y = mCurrentTouch.pointers[0].y;
2546 if (isPointInsideSurfaceLocked(x, y)) {
2547 mLastTouch.clear();
2548 touchResult = DISPATCH_TOUCH;
2549 } else {
2550 touchResult = DROP_STROKE;
2551 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002552 } else {
2553 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2554 // Pointer just went down. Handle off-screen touches, if needed.
2555 int32_t x = mCurrentTouch.pointers[0].x;
2556 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002557 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002558 // If exactly one pointer went down, check for virtual key hit.
2559 // Otherwise we will drop the entire stroke.
2560 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002561 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002562 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002563 if (mContext->shouldDropVirtualKey(when, getDevice(),
2564 virtualKey->keyCode, virtualKey->scanCode)) {
2565 return DROP_STROKE;
2566 }
2567
Jeff Brown6328cdc2010-07-29 18:18:33 -07002568 mLocked.currentVirtualKey.down = true;
2569 mLocked.currentVirtualKey.downTime = when;
2570 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2571 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002572#if DEBUG_VIRTUAL_KEYS
2573 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002574 mLocked.currentVirtualKey.keyCode,
2575 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002576#endif
2577 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2578 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2579 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2580 touchResult = SKIP_TOUCH;
2581 goto DispatchVirtualKey;
2582 }
2583 }
2584 return DROP_STROKE;
2585 }
2586 }
2587 return DISPATCH_TOUCH;
2588 }
2589
2590 DispatchVirtualKey:
2591 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002592 keyCode = mLocked.currentVirtualKey.keyCode;
2593 scanCode = mLocked.currentVirtualKey.scanCode;
2594 downTime = mLocked.currentVirtualKey.downTime;
2595 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002596
2597 // Dispatch virtual key.
2598 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002599 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002600 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2601 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2602 return touchResult;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002603}
2604
Jeff Brownefd32662011-03-08 15:13:06 -08002605void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
Jeff Brownfe508922011-01-18 15:10:10 -08002606 // Disable all virtual key touches that happen within a short time interval of the
2607 // most recent touch. The idea is to filter out stray virtual key presses when
2608 // interacting with the touch screen.
2609 //
2610 // Problems we're trying to solve:
2611 //
2612 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2613 // virtual key area that is implemented by a separate touch panel and accidentally
2614 // triggers a virtual key.
2615 //
2616 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2617 // area and accidentally triggers a virtual key. This often happens when virtual keys
2618 // are layed out below the screen near to where the on screen keyboard's space bar
2619 // is displayed.
2620 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2621 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2622 }
2623}
2624
Jeff Brown6d0fec22010-07-23 21:28:06 -07002625void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2626 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2627 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002628 if (currentPointerCount == 0 && lastPointerCount == 0) {
2629 return; // nothing to do!
2630 }
2631
Jeff Brown6d0fec22010-07-23 21:28:06 -07002632 BitSet32 currentIdBits = mCurrentTouch.idBits;
2633 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002634
2635 if (currentIdBits == lastIdBits) {
2636 // No pointer id changes so this is a move event.
2637 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -07002638 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002639 dispatchTouch(when, policyFlags, & mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002640 currentIdBits, -1, currentPointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002641 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002642 // There may be pointers going up and pointers going down and pointers moving
2643 // all at the same time.
Jeff Brown46b9ac02010-04-22 18:58:52 -07002644 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
2645 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
2646 BitSet32 activeIdBits(lastIdBits.value);
Jeff Brown8d608662010-08-30 03:02:23 -07002647 uint32_t pointerCount = lastPointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002648
Jeff Brownc3db8582010-10-20 15:33:38 -07002649 // Produce an intermediate representation of the touch data that consists of the
2650 // old location of pointers that have just gone up and the new location of pointers that
2651 // have just moved but omits the location of pointers that have just gone down.
2652 TouchData interimTouch;
2653 interimTouch.copyFrom(mLastTouch);
2654
2655 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
2656 bool moveNeeded = false;
2657 while (!moveIdBits.isEmpty()) {
2658 uint32_t moveId = moveIdBits.firstMarkedBit();
2659 moveIdBits.clearBit(moveId);
2660
2661 int32_t oldIndex = mLastTouch.idToIndex[moveId];
2662 int32_t newIndex = mCurrentTouch.idToIndex[moveId];
2663 if (mLastTouch.pointers[oldIndex] != mCurrentTouch.pointers[newIndex]) {
2664 interimTouch.pointers[oldIndex] = mCurrentTouch.pointers[newIndex];
2665 moveNeeded = true;
2666 }
2667 }
2668
2669 // Dispatch pointer up events using the interim pointer locations.
2670 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002671 uint32_t upId = upIdBits.firstMarkedBit();
2672 upIdBits.clearBit(upId);
2673 BitSet32 oldActiveIdBits = activeIdBits;
2674 activeIdBits.clearBit(upId);
2675
2676 int32_t motionEventAction;
2677 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002678 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002679 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002680 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002681 }
2682
Jeff Brownc3db8582010-10-20 15:33:38 -07002683 dispatchTouch(when, policyFlags, &interimTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002684 oldActiveIdBits, upId, pointerCount, motionEventAction);
2685 pointerCount -= 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002686 }
2687
Jeff Brownc3db8582010-10-20 15:33:38 -07002688 // Dispatch move events if any of the remaining pointers moved from their old locations.
2689 // Although applications receive new locations as part of individual pointer up
2690 // events, they do not generally handle them except when presented in a move event.
2691 if (moveNeeded) {
2692 dispatchTouch(when, policyFlags, &mCurrentTouch,
2693 activeIdBits, -1, pointerCount, AMOTION_EVENT_ACTION_MOVE);
2694 }
2695
2696 // Dispatch pointer down events using the new pointer locations.
2697 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002698 uint32_t downId = downIdBits.firstMarkedBit();
2699 downIdBits.clearBit(downId);
2700 BitSet32 oldActiveIdBits = activeIdBits;
2701 activeIdBits.markBit(downId);
2702
2703 int32_t motionEventAction;
2704 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07002705 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002706 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002707 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -07002708 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002709 }
2710
Jeff Brown8d608662010-08-30 03:02:23 -07002711 pointerCount += 1;
Jeff Brownc3db8582010-10-20 15:33:38 -07002712 dispatchTouch(when, policyFlags, &mCurrentTouch,
Jeff Brown8d608662010-08-30 03:02:23 -07002713 activeIdBits, downId, pointerCount, motionEventAction);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002714 }
2715 }
2716}
2717
Jeff Brown6d0fec22010-07-23 21:28:06 -07002718void TouchInputMapper::dispatchTouch(nsecs_t when, uint32_t policyFlags,
Jeff Brown8d608662010-08-30 03:02:23 -07002719 TouchData* touch, BitSet32 idBits, uint32_t changedId, uint32_t pointerCount,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002720 int32_t motionEventAction) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002721 int32_t pointerIds[MAX_POINTERS];
2722 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brown9626b142011-03-03 02:09:54 -08002723 int32_t motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002724 float xPrecision, yPrecision;
2725
2726 { // acquire lock
2727 AutoMutex _l(mLock);
2728
2729 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
Jeff Brownefd32662011-03-08 15:13:06 -08002730 // display or surface coordinates (PointerCoords) and adjust for display orientation.
Jeff Brown8d608662010-08-30 03:02:23 -07002731 for (uint32_t outIndex = 0; ! idBits.isEmpty(); outIndex++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002732 uint32_t id = idBits.firstMarkedBit();
2733 idBits.clearBit(id);
Jeff Brown8d608662010-08-30 03:02:23 -07002734 uint32_t inIndex = touch->idToIndex[id];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002735
Jeff Brown8d608662010-08-30 03:02:23 -07002736 const PointerData& in = touch->pointers[inIndex];
Jeff Brown6328cdc2010-07-29 18:18:33 -07002737
Jeff Brown8d608662010-08-30 03:02:23 -07002738 // ToolMajor and ToolMinor
2739 float toolMajor, toolMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002740 switch (mCalibration.toolSizeCalibration) {
2741 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002742 toolMajor = in.toolMajor * mLocked.geometricScale;
2743 if (mRawAxes.toolMinor.valid) {
2744 toolMinor = in.toolMinor * mLocked.geometricScale;
2745 } else {
2746 toolMinor = toolMajor;
2747 }
2748 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002749 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
Jeff Brown8d608662010-08-30 03:02:23 -07002750 toolMajor = in.toolMajor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002751 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002752 : 0;
2753 if (mRawAxes.toolMinor.valid) {
2754 toolMinor = in.toolMinor != 0
Jeff Brownc6d282b2010-10-14 21:42:15 -07002755 ? in.toolMinor * mLocked.toolSizeLinearScale
2756 + mLocked.toolSizeLinearBias
Jeff Brown8d608662010-08-30 03:02:23 -07002757 : 0;
2758 } else {
2759 toolMinor = toolMajor;
2760 }
2761 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002762 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2763 if (in.toolMajor != 0) {
2764 float diameter = sqrtf(in.toolMajor
2765 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
2766 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
2767 } else {
2768 toolMajor = 0;
2769 }
2770 toolMinor = toolMajor;
2771 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002772 default:
2773 toolMajor = 0;
2774 toolMinor = 0;
2775 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002776 }
2777
Jeff Brownc6d282b2010-10-14 21:42:15 -07002778 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
Jeff Brown8d608662010-08-30 03:02:23 -07002779 toolMajor /= pointerCount;
2780 toolMinor /= pointerCount;
2781 }
2782
2783 // Pressure
2784 float rawPressure;
2785 switch (mCalibration.pressureSource) {
2786 case Calibration::PRESSURE_SOURCE_PRESSURE:
2787 rawPressure = in.pressure;
2788 break;
2789 case Calibration::PRESSURE_SOURCE_TOUCH:
2790 rawPressure = in.touchMajor;
2791 break;
2792 default:
2793 rawPressure = 0;
2794 }
2795
2796 float pressure;
2797 switch (mCalibration.pressureCalibration) {
2798 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
2799 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
2800 pressure = rawPressure * mLocked.pressureScale;
2801 break;
2802 default:
2803 pressure = 1;
2804 break;
2805 }
2806
2807 // TouchMajor and TouchMinor
2808 float touchMajor, touchMinor;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002809 switch (mCalibration.touchSizeCalibration) {
2810 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
Jeff Brown8d608662010-08-30 03:02:23 -07002811 touchMajor = in.touchMajor * mLocked.geometricScale;
2812 if (mRawAxes.touchMinor.valid) {
2813 touchMinor = in.touchMinor * mLocked.geometricScale;
2814 } else {
2815 touchMinor = touchMajor;
2816 }
2817 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002818 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
Jeff Brown8d608662010-08-30 03:02:23 -07002819 touchMajor = toolMajor * pressure;
2820 touchMinor = toolMinor * pressure;
2821 break;
2822 default:
2823 touchMajor = 0;
2824 touchMinor = 0;
2825 break;
2826 }
2827
2828 if (touchMajor > toolMajor) {
2829 touchMajor = toolMajor;
2830 }
2831 if (touchMinor > toolMinor) {
2832 touchMinor = toolMinor;
2833 }
2834
2835 // Size
2836 float size;
2837 switch (mCalibration.sizeCalibration) {
2838 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
2839 float rawSize = mRawAxes.toolMinor.valid
2840 ? avg(in.toolMajor, in.toolMinor)
2841 : in.toolMajor;
2842 size = rawSize * mLocked.sizeScale;
2843 break;
2844 }
2845 default:
2846 size = 0;
2847 break;
2848 }
2849
2850 // Orientation
2851 float orientation;
2852 switch (mCalibration.orientationCalibration) {
2853 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
2854 orientation = in.orientation * mLocked.orientationScale;
2855 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002856 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
2857 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
2858 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
2859 if (c1 != 0 || c2 != 0) {
2860 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brownc3451d42011-02-15 19:13:20 -08002861 float scale = 1.0f + pythag(c1, c2) / 16.0f;
2862 touchMajor *= scale;
2863 touchMinor /= scale;
2864 toolMajor *= scale;
2865 toolMinor /= scale;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002866 } else {
2867 orientation = 0;
2868 }
2869 break;
2870 }
Jeff Brown8d608662010-08-30 03:02:23 -07002871 default:
2872 orientation = 0;
2873 }
2874
Jeff Brown9626b142011-03-03 02:09:54 -08002875 // X and Y
2876 // Adjust coords for surface orientation.
2877 float x, y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002878 switch (mLocked.surfaceOrientation) {
Jeff Brown9626b142011-03-03 02:09:54 -08002879 case DISPLAY_ORIENTATION_90:
2880 x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
2881 y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002882 orientation -= M_PI_2;
2883 if (orientation < - M_PI_2) {
2884 orientation += M_PI;
2885 }
2886 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002887 case DISPLAY_ORIENTATION_180:
2888 x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
2889 y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002890 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002891 case DISPLAY_ORIENTATION_270:
2892 x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
2893 y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002894 orientation += M_PI_2;
2895 if (orientation > M_PI_2) {
2896 orientation -= M_PI;
2897 }
2898 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002899 default:
2900 x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
2901 y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
2902 break;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002903 }
2904
Jeff Brown8d608662010-08-30 03:02:23 -07002905 // Write output coords.
2906 PointerCoords& out = pointerCoords[outIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002907 out.clear();
Jeff Brownebbd5d12011-02-17 13:01:34 -08002908 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
2909 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
2910 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
2911 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
2912 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
2913 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
2914 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
2915 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
2916 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002917
Jeff Brown8d608662010-08-30 03:02:23 -07002918 pointerIds[outIndex] = int32_t(id);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002919
2920 if (id == changedId) {
Jeff Brown8d608662010-08-30 03:02:23 -07002921 motionEventAction |= outIndex << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002922 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002923 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002924
2925 // Check edge flags by looking only at the first pointer since the flags are
2926 // global to the event.
2927 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown9626b142011-03-03 02:09:54 -08002928 uint32_t inIndex = touch->idToIndex[pointerIds[0]];
2929 const PointerData& in = touch->pointers[inIndex];
Jeff Brown91c69ab2011-02-14 17:03:18 -08002930
Jeff Brown9626b142011-03-03 02:09:54 -08002931 if (in.x <= mRawAxes.x.minValue) {
2932 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
2933 mLocked.surfaceOrientation);
2934 } else if (in.x >= mRawAxes.x.maxValue) {
2935 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
2936 mLocked.surfaceOrientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002937 }
Jeff Brown9626b142011-03-03 02:09:54 -08002938 if (in.y <= mRawAxes.y.minValue) {
2939 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
2940 mLocked.surfaceOrientation);
2941 } else if (in.y >= mRawAxes.y.maxValue) {
2942 motionEventEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
2943 mLocked.surfaceOrientation);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002944 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002945 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002946
2947 xPrecision = mLocked.orientedXPrecision;
2948 yPrecision = mLocked.orientedYPrecision;
2949 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07002950
Jeff Brownefd32662011-03-08 15:13:06 -08002951 getDispatcher()->notifyMotion(when, getDeviceId(), mTouchSource, policyFlags,
Jeff Brown85a31762010-09-01 17:01:00 -07002952 motionEventAction, 0, getContext()->getGlobalMetaState(), motionEventEdgeFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -07002953 pointerCount, pointerIds, pointerCoords,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002954 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002955}
2956
Jeff Brown6328cdc2010-07-29 18:18:33 -07002957bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown9626b142011-03-03 02:09:54 -08002958 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
2959 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002960}
2961
Jeff Brown6328cdc2010-07-29 18:18:33 -07002962const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
2963 int32_t x, int32_t y) {
2964 size_t numVirtualKeys = mLocked.virtualKeys.size();
2965 for (size_t i = 0; i < numVirtualKeys; i++) {
2966 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07002967
2968#if DEBUG_VIRTUAL_KEYS
2969 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
2970 "left=%d, top=%d, right=%d, bottom=%d",
2971 x, y,
2972 virtualKey.keyCode, virtualKey.scanCode,
2973 virtualKey.hitLeft, virtualKey.hitTop,
2974 virtualKey.hitRight, virtualKey.hitBottom);
2975#endif
2976
2977 if (virtualKey.isHit(x, y)) {
2978 return & virtualKey;
2979 }
2980 }
2981
2982 return NULL;
2983}
2984
2985void TouchInputMapper::calculatePointerIds() {
2986 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2987 uint32_t lastPointerCount = mLastTouch.pointerCount;
2988
2989 if (currentPointerCount == 0) {
2990 // No pointers to assign.
2991 mCurrentTouch.idBits.clear();
2992 } else if (lastPointerCount == 0) {
2993 // All pointers are new.
2994 mCurrentTouch.idBits.clear();
2995 for (uint32_t i = 0; i < currentPointerCount; i++) {
2996 mCurrentTouch.pointers[i].id = i;
2997 mCurrentTouch.idToIndex[i] = i;
2998 mCurrentTouch.idBits.markBit(i);
2999 }
3000 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
3001 // Only one pointer and no change in count so it must have the same id as before.
3002 uint32_t id = mLastTouch.pointers[0].id;
3003 mCurrentTouch.pointers[0].id = id;
3004 mCurrentTouch.idToIndex[id] = 0;
3005 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
3006 } else {
3007 // General case.
3008 // We build a heap of squared euclidean distances between current and last pointers
3009 // associated with the current and last pointer indices. Then, we find the best
3010 // match (by distance) for each current pointer.
3011 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
3012
3013 uint32_t heapSize = 0;
3014 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
3015 currentPointerIndex++) {
3016 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
3017 lastPointerIndex++) {
3018 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
3019 - mLastTouch.pointers[lastPointerIndex].x;
3020 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
3021 - mLastTouch.pointers[lastPointerIndex].y;
3022
3023 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3024
3025 // Insert new element into the heap (sift up).
3026 heap[heapSize].currentPointerIndex = currentPointerIndex;
3027 heap[heapSize].lastPointerIndex = lastPointerIndex;
3028 heap[heapSize].distance = distance;
3029 heapSize += 1;
3030 }
3031 }
3032
3033 // Heapify
3034 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
3035 startIndex -= 1;
3036 for (uint32_t parentIndex = startIndex; ;) {
3037 uint32_t childIndex = parentIndex * 2 + 1;
3038 if (childIndex >= heapSize) {
3039 break;
3040 }
3041
3042 if (childIndex + 1 < heapSize
3043 && heap[childIndex + 1].distance < heap[childIndex].distance) {
3044 childIndex += 1;
3045 }
3046
3047 if (heap[parentIndex].distance <= heap[childIndex].distance) {
3048 break;
3049 }
3050
3051 swap(heap[parentIndex], heap[childIndex]);
3052 parentIndex = childIndex;
3053 }
3054 }
3055
3056#if DEBUG_POINTER_ASSIGNMENT
3057 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
3058 for (size_t i = 0; i < heapSize; i++) {
3059 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
3060 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
3061 heap[i].distance);
3062 }
3063#endif
3064
3065 // Pull matches out by increasing order of distance.
3066 // To avoid reassigning pointers that have already been matched, the loop keeps track
3067 // of which last and current pointers have been matched using the matchedXXXBits variables.
3068 // It also tracks the used pointer id bits.
3069 BitSet32 matchedLastBits(0);
3070 BitSet32 matchedCurrentBits(0);
3071 BitSet32 usedIdBits(0);
3072 bool first = true;
3073 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
3074 for (;;) {
3075 if (first) {
3076 // The first time through the loop, we just consume the root element of
3077 // the heap (the one with smallest distance).
3078 first = false;
3079 } else {
3080 // Previous iterations consumed the root element of the heap.
3081 // Pop root element off of the heap (sift down).
3082 heapSize -= 1;
3083 assert(heapSize > 0);
3084
3085 // Sift down.
3086 heap[0] = heap[heapSize];
3087 for (uint32_t parentIndex = 0; ;) {
3088 uint32_t childIndex = parentIndex * 2 + 1;
3089 if (childIndex >= heapSize) {
3090 break;
3091 }
3092
3093 if (childIndex + 1 < heapSize
3094 && heap[childIndex + 1].distance < heap[childIndex].distance) {
3095 childIndex += 1;
3096 }
3097
3098 if (heap[parentIndex].distance <= heap[childIndex].distance) {
3099 break;
3100 }
3101
3102 swap(heap[parentIndex], heap[childIndex]);
3103 parentIndex = childIndex;
3104 }
3105
3106#if DEBUG_POINTER_ASSIGNMENT
3107 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
3108 for (size_t i = 0; i < heapSize; i++) {
3109 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
3110 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
3111 heap[i].distance);
3112 }
3113#endif
3114 }
3115
3116 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
3117 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
3118
3119 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
3120 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
3121
3122 matchedCurrentBits.markBit(currentPointerIndex);
3123 matchedLastBits.markBit(lastPointerIndex);
3124
3125 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
3126 mCurrentTouch.pointers[currentPointerIndex].id = id;
3127 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3128 usedIdBits.markBit(id);
3129
3130#if DEBUG_POINTER_ASSIGNMENT
3131 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
3132 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
3133#endif
3134 break;
3135 }
3136 }
3137
3138 // Assign fresh ids to new pointers.
3139 if (currentPointerCount > lastPointerCount) {
3140 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
3141 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
3142 uint32_t id = usedIdBits.firstUnmarkedBit();
3143
3144 mCurrentTouch.pointers[currentPointerIndex].id = id;
3145 mCurrentTouch.idToIndex[id] = currentPointerIndex;
3146 usedIdBits.markBit(id);
3147
3148#if DEBUG_POINTER_ASSIGNMENT
3149 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
3150 currentPointerIndex, id);
3151#endif
3152
3153 if (--i == 0) break; // done
3154 matchedCurrentBits.markBit(currentPointerIndex);
3155 }
3156 }
3157
3158 // Fix id bits.
3159 mCurrentTouch.idBits = usedIdBits;
3160 }
3161}
3162
3163/* Special hack for devices that have bad screen data: if one of the
3164 * points has moved more than a screen height from the last position,
3165 * then drop it. */
3166bool TouchInputMapper::applyBadTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003167 uint32_t pointerCount = mCurrentTouch.pointerCount;
3168
3169 // Nothing to do if there are no points.
3170 if (pointerCount == 0) {
3171 return false;
3172 }
3173
3174 // Don't do anything if a finger is going down or up. We run
3175 // here before assigning pointer IDs, so there isn't a good
3176 // way to do per-finger matching.
3177 if (pointerCount != mLastTouch.pointerCount) {
3178 return false;
3179 }
3180
3181 // We consider a single movement across more than a 7/16 of
3182 // the long size of the screen to be bad. This was a magic value
3183 // determined by looking at the maximum distance it is feasible
3184 // to actually move in one sample.
Jeff Brown9626b142011-03-03 02:09:54 -08003185 int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003186
3187 // XXX The original code in InputDevice.java included commented out
3188 // code for testing the X axis. Note that when we drop a point
3189 // we don't actually restore the old X either. Strange.
3190 // The old code also tries to track when bad points were previously
3191 // detected but it turns out that due to the placement of a "break"
3192 // at the end of the loop, we never set mDroppedBadPoint to true
3193 // so it is effectively dead code.
3194 // Need to figure out if the old code is busted or just overcomplicated
3195 // but working as intended.
3196
3197 // Look through all new points and see if any are farther than
3198 // acceptable from all previous points.
3199 for (uint32_t i = pointerCount; i-- > 0; ) {
3200 int32_t y = mCurrentTouch.pointers[i].y;
3201 int32_t closestY = INT_MAX;
3202 int32_t closestDeltaY = 0;
3203
3204#if DEBUG_HACKS
3205 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
3206#endif
3207
3208 for (uint32_t j = pointerCount; j-- > 0; ) {
3209 int32_t lastY = mLastTouch.pointers[j].y;
3210 int32_t deltaY = abs(y - lastY);
3211
3212#if DEBUG_HACKS
3213 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
3214 j, lastY, deltaY);
3215#endif
3216
3217 if (deltaY < maxDeltaY) {
3218 goto SkipSufficientlyClosePoint;
3219 }
3220 if (deltaY < closestDeltaY) {
3221 closestDeltaY = deltaY;
3222 closestY = lastY;
3223 }
3224 }
3225
3226 // Must not have found a close enough match.
3227#if DEBUG_HACKS
3228 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
3229 i, y, closestY, closestDeltaY, maxDeltaY);
3230#endif
3231
3232 mCurrentTouch.pointers[i].y = closestY;
3233 return true; // XXX original code only corrects one point
3234
3235 SkipSufficientlyClosePoint: ;
3236 }
3237
3238 // No change.
3239 return false;
3240}
3241
3242/* Special hack for devices that have bad screen data: drop points where
3243 * the coordinate value for one axis has jumped to the other pointer's location.
3244 */
3245bool TouchInputMapper::applyJumpyTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003246 uint32_t pointerCount = mCurrentTouch.pointerCount;
3247 if (mLastTouch.pointerCount != pointerCount) {
3248#if DEBUG_HACKS
3249 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
3250 mLastTouch.pointerCount, pointerCount);
3251 for (uint32_t i = 0; i < pointerCount; i++) {
3252 LOGD(" Pointer %d (%d, %d)", i,
3253 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3254 }
3255#endif
3256
3257 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
3258 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
3259 // Just drop the first few events going from 1 to 2 pointers.
3260 // They're bad often enough that they're not worth considering.
3261 mCurrentTouch.pointerCount = 1;
3262 mJumpyTouchFilter.jumpyPointsDropped += 1;
3263
3264#if DEBUG_HACKS
3265 LOGD("JumpyTouchFilter: Pointer 2 dropped");
3266#endif
3267 return true;
3268 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
3269 // The event when we go from 2 -> 1 tends to be messed up too
3270 mCurrentTouch.pointerCount = 2;
3271 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
3272 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
3273 mJumpyTouchFilter.jumpyPointsDropped += 1;
3274
3275#if DEBUG_HACKS
3276 for (int32_t i = 0; i < 2; i++) {
3277 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
3278 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
3279 }
3280#endif
3281 return true;
3282 }
3283 }
3284 // Reset jumpy points dropped on other transitions or if limit exceeded.
3285 mJumpyTouchFilter.jumpyPointsDropped = 0;
3286
3287#if DEBUG_HACKS
3288 LOGD("JumpyTouchFilter: Transition - drop limit reset");
3289#endif
3290 return false;
3291 }
3292
3293 // We have the same number of pointers as last time.
3294 // A 'jumpy' point is one where the coordinate value for one axis
3295 // has jumped to the other pointer's location. No need to do anything
3296 // else if we only have one pointer.
3297 if (pointerCount < 2) {
3298 return false;
3299 }
3300
3301 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown9626b142011-03-03 02:09:54 -08003302 int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003303
3304 // We only replace the single worst jumpy point as characterized by pointer distance
3305 // in a single axis.
3306 int32_t badPointerIndex = -1;
3307 int32_t badPointerReplacementIndex = -1;
3308 int32_t badPointerDistance = INT_MIN; // distance to be corrected
3309
3310 for (uint32_t i = pointerCount; i-- > 0; ) {
3311 int32_t x = mCurrentTouch.pointers[i].x;
3312 int32_t y = mCurrentTouch.pointers[i].y;
3313
3314#if DEBUG_HACKS
3315 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
3316#endif
3317
3318 // Check if a touch point is too close to another's coordinates
3319 bool dropX = false, dropY = false;
3320 for (uint32_t j = 0; j < pointerCount; j++) {
3321 if (i == j) {
3322 continue;
3323 }
3324
3325 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
3326 dropX = true;
3327 break;
3328 }
3329
3330 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
3331 dropY = true;
3332 break;
3333 }
3334 }
3335 if (! dropX && ! dropY) {
3336 continue; // not jumpy
3337 }
3338
3339 // Find a replacement candidate by comparing with older points on the
3340 // complementary (non-jumpy) axis.
3341 int32_t distance = INT_MIN; // distance to be corrected
3342 int32_t replacementIndex = -1;
3343
3344 if (dropX) {
3345 // X looks too close. Find an older replacement point with a close Y.
3346 int32_t smallestDeltaY = INT_MAX;
3347 for (uint32_t j = 0; j < pointerCount; j++) {
3348 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
3349 if (deltaY < smallestDeltaY) {
3350 smallestDeltaY = deltaY;
3351 replacementIndex = j;
3352 }
3353 }
3354 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
3355 } else {
3356 // Y looks too close. Find an older replacement point with a close X.
3357 int32_t smallestDeltaX = INT_MAX;
3358 for (uint32_t j = 0; j < pointerCount; j++) {
3359 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
3360 if (deltaX < smallestDeltaX) {
3361 smallestDeltaX = deltaX;
3362 replacementIndex = j;
3363 }
3364 }
3365 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
3366 }
3367
3368 // If replacing this pointer would correct a worse error than the previous ones
3369 // considered, then use this replacement instead.
3370 if (distance > badPointerDistance) {
3371 badPointerIndex = i;
3372 badPointerReplacementIndex = replacementIndex;
3373 badPointerDistance = distance;
3374 }
3375 }
3376
3377 // Correct the jumpy pointer if one was found.
3378 if (badPointerIndex >= 0) {
3379#if DEBUG_HACKS
3380 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
3381 badPointerIndex,
3382 mLastTouch.pointers[badPointerReplacementIndex].x,
3383 mLastTouch.pointers[badPointerReplacementIndex].y);
3384#endif
3385
3386 mCurrentTouch.pointers[badPointerIndex].x =
3387 mLastTouch.pointers[badPointerReplacementIndex].x;
3388 mCurrentTouch.pointers[badPointerIndex].y =
3389 mLastTouch.pointers[badPointerReplacementIndex].y;
3390 mJumpyTouchFilter.jumpyPointsDropped += 1;
3391 return true;
3392 }
3393 }
3394
3395 mJumpyTouchFilter.jumpyPointsDropped = 0;
3396 return false;
3397}
3398
3399/* Special hack for devices that have bad screen data: aggregate and
3400 * compute averages of the coordinate data, to reduce the amount of
3401 * jitter seen by applications. */
3402void TouchInputMapper::applyAveragingTouchFilter() {
3403 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
3404 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
3405 int32_t x = mCurrentTouch.pointers[currentIndex].x;
3406 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07003407 int32_t pressure;
3408 switch (mCalibration.pressureSource) {
3409 case Calibration::PRESSURE_SOURCE_PRESSURE:
3410 pressure = mCurrentTouch.pointers[currentIndex].pressure;
3411 break;
3412 case Calibration::PRESSURE_SOURCE_TOUCH:
3413 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
3414 break;
3415 default:
3416 pressure = 1;
3417 break;
3418 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003419
3420 if (mLastTouch.idBits.hasBit(id)) {
3421 // Pointer was down before and is still down now.
3422 // Compute average over history trace.
3423 uint32_t start = mAveragingTouchFilter.historyStart[id];
3424 uint32_t end = mAveragingTouchFilter.historyEnd[id];
3425
3426 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
3427 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
3428 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
3429
3430#if DEBUG_HACKS
3431 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
3432 id, distance);
3433#endif
3434
3435 if (distance < AVERAGING_DISTANCE_LIMIT) {
3436 // Increment end index in preparation for recording new historical data.
3437 end += 1;
3438 if (end > AVERAGING_HISTORY_SIZE) {
3439 end = 0;
3440 }
3441
3442 // If the end index has looped back to the start index then we have filled
3443 // the historical trace up to the desired size so we drop the historical
3444 // data at the start of the trace.
3445 if (end == start) {
3446 start += 1;
3447 if (start > AVERAGING_HISTORY_SIZE) {
3448 start = 0;
3449 }
3450 }
3451
3452 // Add the raw data to the historical trace.
3453 mAveragingTouchFilter.historyStart[id] = start;
3454 mAveragingTouchFilter.historyEnd[id] = end;
3455 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
3456 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
3457 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
3458
3459 // Average over all historical positions in the trace by total pressure.
3460 int32_t averagedX = 0;
3461 int32_t averagedY = 0;
3462 int32_t totalPressure = 0;
3463 for (;;) {
3464 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
3465 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
3466 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
3467 .pointers[id].pressure;
3468
3469 averagedX += historicalX * historicalPressure;
3470 averagedY += historicalY * historicalPressure;
3471 totalPressure += historicalPressure;
3472
3473 if (start == end) {
3474 break;
3475 }
3476
3477 start += 1;
3478 if (start > AVERAGING_HISTORY_SIZE) {
3479 start = 0;
3480 }
3481 }
3482
Jeff Brown8d608662010-08-30 03:02:23 -07003483 if (totalPressure != 0) {
3484 averagedX /= totalPressure;
3485 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003486
3487#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07003488 LOGD("AveragingTouchFilter: Pointer id %d - "
3489 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
3490 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003491#endif
3492
Jeff Brown8d608662010-08-30 03:02:23 -07003493 mCurrentTouch.pointers[currentIndex].x = averagedX;
3494 mCurrentTouch.pointers[currentIndex].y = averagedY;
3495 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003496 } else {
3497#if DEBUG_HACKS
3498 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
3499#endif
3500 }
3501 } else {
3502#if DEBUG_HACKS
3503 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
3504#endif
3505 }
3506
3507 // Reset pointer history.
3508 mAveragingTouchFilter.historyStart[id] = 0;
3509 mAveragingTouchFilter.historyEnd[id] = 0;
3510 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
3511 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
3512 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
3513 }
3514}
3515
3516int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003517 { // acquire lock
3518 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003519
Jeff Brown6328cdc2010-07-29 18:18:33 -07003520 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003521 return AKEY_STATE_VIRTUAL;
3522 }
3523
Jeff Brown6328cdc2010-07-29 18:18:33 -07003524 size_t numVirtualKeys = mLocked.virtualKeys.size();
3525 for (size_t i = 0; i < numVirtualKeys; i++) {
3526 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003527 if (virtualKey.keyCode == keyCode) {
3528 return AKEY_STATE_UP;
3529 }
3530 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003531 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003532
3533 return AKEY_STATE_UNKNOWN;
3534}
3535
3536int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003537 { // acquire lock
3538 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003539
Jeff Brown6328cdc2010-07-29 18:18:33 -07003540 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003541 return AKEY_STATE_VIRTUAL;
3542 }
3543
Jeff Brown6328cdc2010-07-29 18:18:33 -07003544 size_t numVirtualKeys = mLocked.virtualKeys.size();
3545 for (size_t i = 0; i < numVirtualKeys; i++) {
3546 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003547 if (virtualKey.scanCode == scanCode) {
3548 return AKEY_STATE_UP;
3549 }
3550 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003551 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003552
3553 return AKEY_STATE_UNKNOWN;
3554}
3555
3556bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
3557 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003558 { // acquire lock
3559 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003560
Jeff Brown6328cdc2010-07-29 18:18:33 -07003561 size_t numVirtualKeys = mLocked.virtualKeys.size();
3562 for (size_t i = 0; i < numVirtualKeys; i++) {
3563 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07003564
3565 for (size_t i = 0; i < numCodes; i++) {
3566 if (virtualKey.keyCode == keyCodes[i]) {
3567 outFlags[i] = 1;
3568 }
3569 }
3570 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003571 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003572
3573 return true;
3574}
3575
3576
3577// --- SingleTouchInputMapper ---
3578
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003579SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
3580 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003581 initialize();
3582}
3583
3584SingleTouchInputMapper::~SingleTouchInputMapper() {
3585}
3586
3587void SingleTouchInputMapper::initialize() {
3588 mAccumulator.clear();
3589
3590 mDown = false;
3591 mX = 0;
3592 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07003593 mPressure = 0; // default to 0 for devices that don't report pressure
3594 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown6d0fec22010-07-23 21:28:06 -07003595}
3596
3597void SingleTouchInputMapper::reset() {
3598 TouchInputMapper::reset();
3599
Jeff Brown6d0fec22010-07-23 21:28:06 -07003600 initialize();
3601 }
3602
3603void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
3604 switch (rawEvent->type) {
3605 case EV_KEY:
3606 switch (rawEvent->scanCode) {
3607 case BTN_TOUCH:
3608 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
3609 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003610 // Don't sync immediately. Wait until the next SYN_REPORT since we might
3611 // not have received valid position information yet. This logic assumes that
3612 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003613 break;
3614 }
3615 break;
3616
3617 case EV_ABS:
3618 switch (rawEvent->scanCode) {
3619 case ABS_X:
3620 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
3621 mAccumulator.absX = rawEvent->value;
3622 break;
3623 case ABS_Y:
3624 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
3625 mAccumulator.absY = rawEvent->value;
3626 break;
3627 case ABS_PRESSURE:
3628 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
3629 mAccumulator.absPressure = rawEvent->value;
3630 break;
3631 case ABS_TOOL_WIDTH:
3632 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
3633 mAccumulator.absToolWidth = rawEvent->value;
3634 break;
3635 }
3636 break;
3637
3638 case EV_SYN:
3639 switch (rawEvent->scanCode) {
3640 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003641 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003642 break;
3643 }
3644 break;
3645 }
3646}
3647
3648void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003649 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003650 if (fields == 0) {
3651 return; // no new state changes, so nothing to do
3652 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003653
3654 if (fields & Accumulator::FIELD_BTN_TOUCH) {
3655 mDown = mAccumulator.btnTouch;
3656 }
3657
3658 if (fields & Accumulator::FIELD_ABS_X) {
3659 mX = mAccumulator.absX;
3660 }
3661
3662 if (fields & Accumulator::FIELD_ABS_Y) {
3663 mY = mAccumulator.absY;
3664 }
3665
3666 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
3667 mPressure = mAccumulator.absPressure;
3668 }
3669
3670 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07003671 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003672 }
3673
3674 mCurrentTouch.clear();
3675
3676 if (mDown) {
3677 mCurrentTouch.pointerCount = 1;
3678 mCurrentTouch.pointers[0].id = 0;
3679 mCurrentTouch.pointers[0].x = mX;
3680 mCurrentTouch.pointers[0].y = mY;
3681 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07003682 mCurrentTouch.pointers[0].touchMajor = 0;
3683 mCurrentTouch.pointers[0].touchMinor = 0;
3684 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
3685 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003686 mCurrentTouch.pointers[0].orientation = 0;
3687 mCurrentTouch.idToIndex[0] = 0;
3688 mCurrentTouch.idBits.markBit(0);
3689 }
3690
3691 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003692
3693 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003694}
3695
Jeff Brown8d608662010-08-30 03:02:23 -07003696void SingleTouchInputMapper::configureRawAxes() {
3697 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003698
Jeff Brown8d608662010-08-30 03:02:23 -07003699 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
3700 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
3701 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
3702 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003703}
3704
3705
3706// --- MultiTouchInputMapper ---
3707
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003708MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
3709 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003710 initialize();
3711}
3712
3713MultiTouchInputMapper::~MultiTouchInputMapper() {
3714}
3715
3716void MultiTouchInputMapper::initialize() {
3717 mAccumulator.clear();
3718}
3719
3720void MultiTouchInputMapper::reset() {
3721 TouchInputMapper::reset();
3722
Jeff Brown6d0fec22010-07-23 21:28:06 -07003723 initialize();
3724}
3725
3726void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
3727 switch (rawEvent->type) {
3728 case EV_ABS: {
3729 uint32_t pointerIndex = mAccumulator.pointerCount;
3730 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
3731
3732 switch (rawEvent->scanCode) {
3733 case ABS_MT_POSITION_X:
3734 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
3735 pointer->absMTPositionX = rawEvent->value;
3736 break;
3737 case ABS_MT_POSITION_Y:
3738 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
3739 pointer->absMTPositionY = rawEvent->value;
3740 break;
3741 case ABS_MT_TOUCH_MAJOR:
3742 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
3743 pointer->absMTTouchMajor = rawEvent->value;
3744 break;
3745 case ABS_MT_TOUCH_MINOR:
3746 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
3747 pointer->absMTTouchMinor = rawEvent->value;
3748 break;
3749 case ABS_MT_WIDTH_MAJOR:
3750 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
3751 pointer->absMTWidthMajor = rawEvent->value;
3752 break;
3753 case ABS_MT_WIDTH_MINOR:
3754 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
3755 pointer->absMTWidthMinor = rawEvent->value;
3756 break;
3757 case ABS_MT_ORIENTATION:
3758 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
3759 pointer->absMTOrientation = rawEvent->value;
3760 break;
3761 case ABS_MT_TRACKING_ID:
3762 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
3763 pointer->absMTTrackingId = rawEvent->value;
3764 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003765 case ABS_MT_PRESSURE:
3766 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
3767 pointer->absMTPressure = rawEvent->value;
3768 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003769 }
3770 break;
3771 }
3772
3773 case EV_SYN:
3774 switch (rawEvent->scanCode) {
3775 case SYN_MT_REPORT: {
3776 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
3777 uint32_t pointerIndex = mAccumulator.pointerCount;
3778
3779 if (mAccumulator.pointers[pointerIndex].fields) {
3780 if (pointerIndex == MAX_POINTERS) {
3781 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
3782 MAX_POINTERS);
3783 } else {
3784 pointerIndex += 1;
3785 mAccumulator.pointerCount = pointerIndex;
3786 }
3787 }
3788
3789 mAccumulator.pointers[pointerIndex].clear();
3790 break;
3791 }
3792
3793 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003794 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003795 break;
3796 }
3797 break;
3798 }
3799}
3800
3801void MultiTouchInputMapper::sync(nsecs_t when) {
3802 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07003803 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003804
Jeff Brown6d0fec22010-07-23 21:28:06 -07003805 uint32_t inCount = mAccumulator.pointerCount;
3806 uint32_t outCount = 0;
3807 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003808
Jeff Brown6d0fec22010-07-23 21:28:06 -07003809 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003810
Jeff Brown6d0fec22010-07-23 21:28:06 -07003811 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003812 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
3813 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003814
Jeff Brown6d0fec22010-07-23 21:28:06 -07003815 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003816 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
3817 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07003818 continue;
3819 }
3820
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003821 PointerData& outPointer = mCurrentTouch.pointers[outCount];
3822 outPointer.x = inPointer.absMTPositionX;
3823 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003824
Jeff Brown8d608662010-08-30 03:02:23 -07003825 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
3826 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07003827 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
3828 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003829 continue;
3830 }
Jeff Brown8d608662010-08-30 03:02:23 -07003831 outPointer.pressure = inPointer.absMTPressure;
3832 } else {
3833 // Default pressure to 0 if absent.
3834 outPointer.pressure = 0;
3835 }
3836
3837 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
3838 if (inPointer.absMTTouchMajor <= 0) {
3839 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
3840 // a pointer going up. Drop this finger.
3841 continue;
3842 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003843 outPointer.touchMajor = inPointer.absMTTouchMajor;
3844 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003845 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003846 outPointer.touchMajor = 0;
3847 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003848
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003849 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
3850 outPointer.touchMinor = inPointer.absMTTouchMinor;
3851 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003852 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003853 outPointer.touchMinor = outPointer.touchMajor;
3854 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003855
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003856 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
3857 outPointer.toolMajor = inPointer.absMTWidthMajor;
3858 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003859 // Default tool area to 0 if absent.
3860 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003861 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003862
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003863 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
3864 outPointer.toolMinor = inPointer.absMTWidthMinor;
3865 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003866 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003867 outPointer.toolMinor = outPointer.toolMajor;
3868 }
3869
3870 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
3871 outPointer.orientation = inPointer.absMTOrientation;
3872 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07003873 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003874 outPointer.orientation = 0;
3875 }
3876
Jeff Brown8d608662010-08-30 03:02:23 -07003877 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003878 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003879 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
3880 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003881
Jeff Brown6d0fec22010-07-23 21:28:06 -07003882 if (id > MAX_POINTER_ID) {
3883#if DEBUG_POINTERS
3884 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07003885 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07003886 id, MAX_POINTER_ID);
3887#endif
3888 havePointerIds = false;
3889 }
3890 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003891 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003892 mCurrentTouch.idToIndex[id] = outCount;
3893 mCurrentTouch.idBits.markBit(id);
3894 }
3895 } else {
3896 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003897 }
3898 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003899
Jeff Brown6d0fec22010-07-23 21:28:06 -07003900 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003901 }
3902
Jeff Brown6d0fec22010-07-23 21:28:06 -07003903 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003904
Jeff Brown6d0fec22010-07-23 21:28:06 -07003905 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07003906
3907 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003908}
3909
Jeff Brown8d608662010-08-30 03:02:23 -07003910void MultiTouchInputMapper::configureRawAxes() {
3911 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003912
Jeff Brown8d608662010-08-30 03:02:23 -07003913 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
3914 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
3915 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
3916 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
3917 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
3918 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
3919 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
3920 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07003921}
3922
Jeff Brown46b9ac02010-04-22 18:58:52 -07003923
Jeff Browncb1404e2011-01-15 18:14:15 -08003924// --- JoystickInputMapper ---
3925
3926JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
3927 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08003928}
3929
3930JoystickInputMapper::~JoystickInputMapper() {
3931}
3932
3933uint32_t JoystickInputMapper::getSources() {
3934 return AINPUT_SOURCE_JOYSTICK;
3935}
3936
3937void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
3938 InputMapper::populateDeviceInfo(info);
3939
Jeff Brown6f2fba42011-02-19 01:08:02 -08003940 for (size_t i = 0; i < mAxes.size(); i++) {
3941 const Axis& axis = mAxes.valueAt(i);
Jeff Brownefd32662011-03-08 15:13:06 -08003942 info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
3943 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08003944 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
Jeff Brownefd32662011-03-08 15:13:06 -08003945 info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
3946 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08003947 }
Jeff Browncb1404e2011-01-15 18:14:15 -08003948 }
3949}
3950
3951void JoystickInputMapper::dump(String8& dump) {
3952 dump.append(INDENT2 "Joystick Input Mapper:\n");
3953
Jeff Brown6f2fba42011-02-19 01:08:02 -08003954 dump.append(INDENT3 "Axes:\n");
3955 size_t numAxes = mAxes.size();
3956 for (size_t i = 0; i < numAxes; i++) {
3957 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08003958 const char* label = getAxisLabel(axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003959 if (label) {
Jeff Brown85297452011-03-04 13:07:49 -08003960 dump.appendFormat(INDENT4 "%s", label);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003961 } else {
Jeff Brown85297452011-03-04 13:07:49 -08003962 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003963 }
Jeff Brown85297452011-03-04 13:07:49 -08003964 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
3965 label = getAxisLabel(axis.axisInfo.highAxis);
3966 if (label) {
3967 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
3968 } else {
3969 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
3970 axis.axisInfo.splitValue);
3971 }
3972 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
3973 dump.append(" (invert)");
3974 }
3975
3976 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
3977 axis.min, axis.max, axis.flat, axis.fuzz);
3978 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
3979 "highScale=%0.5f, highOffset=%0.5f\n",
3980 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003981 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
3982 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
3983 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08003984 }
3985}
3986
3987void JoystickInputMapper::configure() {
3988 InputMapper::configure();
3989
Jeff Brown6f2fba42011-02-19 01:08:02 -08003990 // Collect all axes.
3991 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
3992 RawAbsoluteAxisInfo rawAxisInfo;
3993 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
3994 if (rawAxisInfo.valid) {
Jeff Brown85297452011-03-04 13:07:49 -08003995 // Map axis.
3996 AxisInfo axisInfo;
3997 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
Jeff Brown6f2fba42011-02-19 01:08:02 -08003998 if (!explicitlyMapped) {
3999 // Axis is not explicitly mapped, will choose a generic axis later.
Jeff Brown85297452011-03-04 13:07:49 -08004000 axisInfo.mode = AxisInfo::MODE_NORMAL;
4001 axisInfo.axis = -1;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004002 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004003
Jeff Brown85297452011-03-04 13:07:49 -08004004 // Apply flat override.
4005 int32_t rawFlat = axisInfo.flatOverride < 0
4006 ? rawAxisInfo.flat : axisInfo.flatOverride;
4007
4008 // Calculate scaling factors and limits.
Jeff Brown6f2fba42011-02-19 01:08:02 -08004009 Axis axis;
Jeff Brown85297452011-03-04 13:07:49 -08004010 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
4011 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
4012 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
4013 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
4014 scale, 0.0f, highScale, 0.0f,
4015 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
4016 } else if (isCenteredAxis(axisInfo.axis)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004017 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
4018 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
Jeff Brown85297452011-03-04 13:07:49 -08004019 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
4020 scale, offset, scale, offset,
4021 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08004022 } else {
4023 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
Jeff Brown85297452011-03-04 13:07:49 -08004024 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
4025 scale, 0.0f, scale, 0.0f,
4026 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08004027 }
4028
4029 // To eliminate noise while the joystick is at rest, filter out small variations
4030 // in axis values up front.
4031 axis.filter = axis.flat * 0.25f;
4032
4033 mAxes.add(abs, axis);
4034 }
4035 }
4036
4037 // If there are too many axes, start dropping them.
4038 // Prefer to keep explicitly mapped axes.
4039 if (mAxes.size() > PointerCoords::MAX_AXES) {
4040 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
4041 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
4042 pruneAxes(true);
4043 pruneAxes(false);
4044 }
4045
4046 // Assign generic axis ids to remaining axes.
4047 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
4048 size_t numAxes = mAxes.size();
4049 for (size_t i = 0; i < numAxes; i++) {
4050 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08004051 if (axis.axisInfo.axis < 0) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004052 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
4053 && haveAxis(nextGenericAxisId)) {
4054 nextGenericAxisId += 1;
4055 }
4056
4057 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
Jeff Brown85297452011-03-04 13:07:49 -08004058 axis.axisInfo.axis = nextGenericAxisId;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004059 nextGenericAxisId += 1;
4060 } else {
4061 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
4062 "have already been assigned to other axes.",
4063 getDeviceName().string(), mAxes.keyAt(i));
4064 mAxes.removeItemsAt(i--);
4065 numAxes -= 1;
4066 }
4067 }
4068 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004069}
4070
Jeff Brown85297452011-03-04 13:07:49 -08004071bool JoystickInputMapper::haveAxis(int32_t axisId) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004072 size_t numAxes = mAxes.size();
4073 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08004074 const Axis& axis = mAxes.valueAt(i);
4075 if (axis.axisInfo.axis == axisId
4076 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
4077 && axis.axisInfo.highAxis == axisId)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004078 return true;
4079 }
4080 }
4081 return false;
4082}
Jeff Browncb1404e2011-01-15 18:14:15 -08004083
Jeff Brown6f2fba42011-02-19 01:08:02 -08004084void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
4085 size_t i = mAxes.size();
4086 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
4087 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
4088 continue;
4089 }
4090 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
4091 getDeviceName().string(), mAxes.keyAt(i));
4092 mAxes.removeItemsAt(i);
4093 }
4094}
4095
4096bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
4097 switch (axis) {
4098 case AMOTION_EVENT_AXIS_X:
4099 case AMOTION_EVENT_AXIS_Y:
4100 case AMOTION_EVENT_AXIS_Z:
4101 case AMOTION_EVENT_AXIS_RX:
4102 case AMOTION_EVENT_AXIS_RY:
4103 case AMOTION_EVENT_AXIS_RZ:
4104 case AMOTION_EVENT_AXIS_HAT_X:
4105 case AMOTION_EVENT_AXIS_HAT_Y:
4106 case AMOTION_EVENT_AXIS_ORIENTATION:
Jeff Brown85297452011-03-04 13:07:49 -08004107 case AMOTION_EVENT_AXIS_RUDDER:
4108 case AMOTION_EVENT_AXIS_WHEEL:
Jeff Brown6f2fba42011-02-19 01:08:02 -08004109 return true;
4110 default:
4111 return false;
4112 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004113}
4114
4115void JoystickInputMapper::reset() {
4116 // Recenter all axes.
4117 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08004118
Jeff Brown6f2fba42011-02-19 01:08:02 -08004119 size_t numAxes = mAxes.size();
4120 for (size_t i = 0; i < numAxes; i++) {
4121 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08004122 axis.resetValue();
Jeff Brown6f2fba42011-02-19 01:08:02 -08004123 }
4124
4125 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08004126
4127 InputMapper::reset();
4128}
4129
4130void JoystickInputMapper::process(const RawEvent* rawEvent) {
4131 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004132 case EV_ABS: {
4133 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
4134 if (index >= 0) {
4135 Axis& axis = mAxes.editValueAt(index);
Jeff Brown85297452011-03-04 13:07:49 -08004136 float newValue, highNewValue;
4137 switch (axis.axisInfo.mode) {
4138 case AxisInfo::MODE_INVERT:
4139 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
4140 * axis.scale + axis.offset;
4141 highNewValue = 0.0f;
4142 break;
4143 case AxisInfo::MODE_SPLIT:
4144 if (rawEvent->value < axis.axisInfo.splitValue) {
4145 newValue = (axis.axisInfo.splitValue - rawEvent->value)
4146 * axis.scale + axis.offset;
4147 highNewValue = 0.0f;
4148 } else if (rawEvent->value > axis.axisInfo.splitValue) {
4149 newValue = 0.0f;
4150 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
4151 * axis.highScale + axis.highOffset;
4152 } else {
4153 newValue = 0.0f;
4154 highNewValue = 0.0f;
4155 }
4156 break;
4157 default:
4158 newValue = rawEvent->value * axis.scale + axis.offset;
4159 highNewValue = 0.0f;
4160 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004161 }
Jeff Brown85297452011-03-04 13:07:49 -08004162 axis.newValue = newValue;
4163 axis.highNewValue = highNewValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08004164 }
4165 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004166 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004167
4168 case EV_SYN:
4169 switch (rawEvent->scanCode) {
4170 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08004171 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08004172 break;
4173 }
4174 break;
4175 }
4176}
4177
Jeff Brown6f2fba42011-02-19 01:08:02 -08004178void JoystickInputMapper::sync(nsecs_t when, bool force) {
Jeff Brown85297452011-03-04 13:07:49 -08004179 if (!filterAxes(force)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004180 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08004181 }
4182
4183 int32_t metaState = mContext->getGlobalMetaState();
4184
Jeff Brown6f2fba42011-02-19 01:08:02 -08004185 PointerCoords pointerCoords;
4186 pointerCoords.clear();
4187
4188 size_t numAxes = mAxes.size();
4189 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08004190 const Axis& axis = mAxes.valueAt(i);
4191 pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
4192 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
4193 pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
4194 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004195 }
4196
Jeff Brown56194eb2011-03-02 19:23:13 -08004197 // Moving a joystick axis should not wake the devide because joysticks can
4198 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
4199 // button will likely wake the device.
4200 // TODO: Use the input device configuration to control this behavior more finely.
4201 uint32_t policyFlags = 0;
4202
Jeff Brown6f2fba42011-02-19 01:08:02 -08004203 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08004204 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brown6f2fba42011-02-19 01:08:02 -08004205 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
4206 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08004207}
4208
Jeff Brown85297452011-03-04 13:07:49 -08004209bool JoystickInputMapper::filterAxes(bool force) {
4210 bool atLeastOneSignificantChange = force;
Jeff Brown6f2fba42011-02-19 01:08:02 -08004211 size_t numAxes = mAxes.size();
4212 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08004213 Axis& axis = mAxes.editValueAt(i);
4214 if (force || hasValueChangedSignificantly(axis.filter,
4215 axis.newValue, axis.currentValue, axis.min, axis.max)) {
4216 axis.currentValue = axis.newValue;
4217 atLeastOneSignificantChange = true;
4218 }
4219 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
4220 if (force || hasValueChangedSignificantly(axis.filter,
4221 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
4222 axis.highCurrentValue = axis.highNewValue;
4223 atLeastOneSignificantChange = true;
4224 }
4225 }
4226 }
4227 return atLeastOneSignificantChange;
4228}
4229
4230bool JoystickInputMapper::hasValueChangedSignificantly(
4231 float filter, float newValue, float currentValue, float min, float max) {
4232 if (newValue != currentValue) {
4233 // Filter out small changes in value unless the value is converging on the axis
4234 // bounds or center point. This is intended to reduce the amount of information
4235 // sent to applications by particularly noisy joysticks (such as PS3).
4236 if (fabs(newValue - currentValue) > filter
4237 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
4238 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
4239 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
4240 return true;
4241 }
4242 }
4243 return false;
4244}
4245
4246bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
4247 float filter, float newValue, float currentValue, float thresholdValue) {
4248 float newDistance = fabs(newValue - thresholdValue);
4249 if (newDistance < filter) {
4250 float oldDistance = fabs(currentValue - thresholdValue);
4251 if (newDistance < oldDistance) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08004252 return true;
4253 }
Jeff Browncb1404e2011-01-15 18:14:15 -08004254 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08004255 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08004256}
4257
Jeff Brown46b9ac02010-04-22 18:58:52 -07004258} // namespace android