blob: 1ed5ad729fc24bb1aeadf6a16b601fe6f3ed07db [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 Brown96ad3972011-03-09 17:39:48 -080036// Log debug messages about gesture detection.
37#define DEBUG_GESTURES 0
38
Jeff Brownb4ff35d2011-01-02 16:37:43 -080039#include "InputReader.h"
40
Jeff Brown1a84fd12011-06-02 01:26:32 -070041#include <cutils/atomic.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070042#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080043#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080044#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070045
46#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070047#include <stdlib.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070048#include <unistd.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070049#include <errno.h>
50#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070051#include <math.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070052
Jeff Brown8d608662010-08-30 03:02:23 -070053#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070054#define INDENT2 " "
55#define INDENT3 " "
56#define INDENT4 " "
Jeff Brown8d608662010-08-30 03:02:23 -070057
Jeff Brown46b9ac02010-04-22 18:58:52 -070058namespace android {
59
60// --- Static Functions ---
61
62template<typename T>
63inline static T abs(const T& value) {
64 return value < 0 ? - value : value;
65}
66
67template<typename T>
68inline static T min(const T& a, const T& b) {
69 return a < b ? a : b;
70}
71
Jeff Brown5c225b12010-06-16 01:53:36 -070072template<typename T>
73inline static void swap(T& a, T& b) {
74 T temp = a;
75 a = b;
76 b = temp;
77}
78
Jeff Brown8d608662010-08-30 03:02:23 -070079inline static float avg(float x, float y) {
80 return (x + y) / 2;
81}
82
Jeff Brown86ea1f52011-04-12 22:39:53 -070083inline static float distance(float x1, float y1, float x2, float y2) {
84 return hypotf(x1 - x2, y1 - y2);
Jeff Brown96ad3972011-03-09 17:39:48 -080085}
86
Jeff Brown517bb4c2011-01-14 19:09:23 -080087inline static int32_t signExtendNybble(int32_t value) {
88 return value >= 8 ? value - 16 : value;
89}
90
Jeff Brownef3d7e82010-09-30 14:33:04 -070091static inline const char* toString(bool value) {
92 return value ? "true" : "false";
93}
94
Jeff Brown9626b142011-03-03 02:09:54 -080095static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
96 const int32_t map[][4], size_t mapSize) {
97 if (orientation != DISPLAY_ORIENTATION_0) {
98 for (size_t i = 0; i < mapSize; i++) {
99 if (value == map[i][0]) {
100 return map[i][orientation];
101 }
102 }
103 }
104 return value;
105}
106
Jeff Brown46b9ac02010-04-22 18:58:52 -0700107static const int32_t keyCodeRotationMap[][4] = {
108 // key codes enumerated counter-clockwise with the original (unrotated) key first
109 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd035822010-06-30 16:10:35 -0700110 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
111 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
112 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
113 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac02010-04-22 18:58:52 -0700114};
Jeff Brown9626b142011-03-03 02:09:54 -0800115static const size_t keyCodeRotationMapSize =
Jeff Brown46b9ac02010-04-22 18:58:52 -0700116 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
117
118int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9626b142011-03-03 02:09:54 -0800119 return rotateValueUsingRotationMap(keyCode, orientation,
120 keyCodeRotationMap, keyCodeRotationMapSize);
121}
122
123static const int32_t edgeFlagRotationMap[][4] = {
124 // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
125 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
126 { AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT,
127 AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT },
128 { AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP,
129 AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM },
130 { AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT,
131 AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT },
132 { AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM,
133 AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP },
134};
135static const size_t edgeFlagRotationMapSize =
136 sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
137
138static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
139 return rotateValueUsingRotationMap(edgeFlag, orientation,
140 edgeFlagRotationMap, edgeFlagRotationMapSize);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700141}
142
Jeff Brown6d0fec22010-07-23 21:28:06 -0700143static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
144 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
145}
146
Jeff Brownefd32662011-03-08 15:13:06 -0800147static uint32_t getButtonStateForScanCode(int32_t scanCode) {
148 // Currently all buttons are mapped to the primary button.
149 switch (scanCode) {
150 case BTN_LEFT:
151 case BTN_RIGHT:
152 case BTN_MIDDLE:
153 case BTN_SIDE:
154 case BTN_EXTRA:
155 case BTN_FORWARD:
156 case BTN_BACK:
157 case BTN_TASK:
158 return BUTTON_STATE_PRIMARY;
159 default:
160 return 0;
161 }
162}
163
164// Returns true if the pointer should be reported as being down given the specified
165// button states.
166static bool isPointerDown(uint32_t buttonState) {
167 return buttonState & BUTTON_STATE_PRIMARY;
168}
169
170static int32_t calculateEdgeFlagsUsingPointerBounds(
171 const sp<PointerControllerInterface>& pointerController, float x, float y) {
172 int32_t edgeFlags = 0;
173 float minX, minY, maxX, maxY;
174 if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
175 if (x <= minX) {
176 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
177 } else if (x >= maxX) {
178 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
179 }
180 if (y <= minY) {
181 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
182 } else if (y >= maxY) {
183 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
184 }
185 }
186 return edgeFlags;
187}
188
Jeff Brown86ea1f52011-04-12 22:39:53 -0700189static float calculateCommonVector(float a, float b) {
190 if (a > 0 && b > 0) {
191 return a < b ? a : b;
192 } else if (a < 0 && b < 0) {
193 return a > b ? a : b;
194 } else {
195 return 0;
196 }
197}
198
Jeff Brown46b9ac02010-04-22 18:58:52 -0700199
Jeff Brown46b9ac02010-04-22 18:58:52 -0700200// --- InputReader ---
201
202InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700203 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700204 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700205 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brown1a84fd12011-06-02 01:26:32 -0700206 mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX),
207 mRefreshConfiguration(0) {
208 configure(true /*firstTime*/);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700209 updateGlobalMetaState();
210 updateInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700211}
212
213InputReader::~InputReader() {
214 for (size_t i = 0; i < mDevices.size(); i++) {
215 delete mDevices.valueAt(i);
216 }
217}
218
219void InputReader::loopOnce() {
Jeff Brown1a84fd12011-06-02 01:26:32 -0700220 if (android_atomic_acquire_load(&mRefreshConfiguration)) {
221 android_atomic_release_store(0, &mRefreshConfiguration);
222 configure(false /*firstTime*/);
223 }
224
Jeff Brown68d60752011-03-17 01:34:19 -0700225 int32_t timeoutMillis = -1;
226 if (mNextTimeout != LLONG_MAX) {
227 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
228 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
229 }
230
Jeff Browndbf8d272011-03-18 18:14:26 -0700231 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
232 if (count) {
233 processEvents(mEventBuffer, count);
234 }
235 if (!count || timeoutMillis == 0) {
Jeff Brown68d60752011-03-17 01:34:19 -0700236 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
237#if DEBUG_RAW_EVENTS
238 LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
239#endif
240 mNextTimeout = LLONG_MAX;
241 timeoutExpired(now);
242 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700243}
244
Jeff Browndbf8d272011-03-18 18:14:26 -0700245void InputReader::processEvents(const RawEvent* rawEvents, size_t count) {
246 for (const RawEvent* rawEvent = rawEvents; count;) {
247 int32_t type = rawEvent->type;
248 size_t batchSize = 1;
249 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
250 int32_t deviceId = rawEvent->deviceId;
251 while (batchSize < count) {
252 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
253 || rawEvent[batchSize].deviceId != deviceId) {
254 break;
255 }
256 batchSize += 1;
257 }
258#if DEBUG_RAW_EVENTS
259 LOGD("BatchSize: %d Count: %d", batchSize, count);
260#endif
261 processEventsForDevice(deviceId, rawEvent, batchSize);
262 } else {
263 switch (rawEvent->type) {
264 case EventHubInterface::DEVICE_ADDED:
265 addDevice(rawEvent->deviceId);
266 break;
267 case EventHubInterface::DEVICE_REMOVED:
268 removeDevice(rawEvent->deviceId);
269 break;
270 case EventHubInterface::FINISHED_DEVICE_SCAN:
271 handleConfigurationChanged(rawEvent->when);
272 break;
273 default:
274 assert(false); // can't happen
275 break;
276 }
277 }
278 count -= batchSize;
279 rawEvent += batchSize;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700280 }
281}
282
Jeff Brown7342bb92010-10-01 18:55:43 -0700283void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700284 String8 name = mEventHub->getDeviceName(deviceId);
285 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
286
287 InputDevice* device = createDevice(deviceId, name, classes);
288 device->configure();
289
Jeff Brown8d608662010-08-30 03:02:23 -0700290 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800291 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700292 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800293 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700294 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700295 }
296
Jeff Brown6d0fec22010-07-23 21:28:06 -0700297 bool added = false;
298 { // acquire device registry writer lock
299 RWLock::AutoWLock _wl(mDeviceRegistryLock);
300
301 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
302 if (deviceIndex < 0) {
303 mDevices.add(deviceId, device);
304 added = true;
305 }
306 } // release device registry writer lock
307
308 if (! added) {
309 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
310 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700311 return;
312 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700313}
314
Jeff Brown7342bb92010-10-01 18:55:43 -0700315void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700316 bool removed = false;
317 InputDevice* device = NULL;
318 { // acquire device registry writer lock
319 RWLock::AutoWLock _wl(mDeviceRegistryLock);
320
321 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
322 if (deviceIndex >= 0) {
323 device = mDevices.valueAt(deviceIndex);
324 mDevices.removeItemsAt(deviceIndex, 1);
325 removed = true;
326 }
327 } // release device registry writer lock
328
329 if (! removed) {
330 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700331 return;
332 }
333
Jeff Brown6d0fec22010-07-23 21:28:06 -0700334 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800335 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700336 device->getId(), device->getName().string());
337 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800338 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700339 device->getId(), device->getName().string(), device->getSources());
340 }
341
Jeff Brown8d608662010-08-30 03:02:23 -0700342 device->reset();
343
Jeff Brown6d0fec22010-07-23 21:28:06 -0700344 delete device;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700345}
346
Jeff Brown6d0fec22010-07-23 21:28:06 -0700347InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
348 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700349
Jeff Brown56194eb2011-03-02 19:23:13 -0800350 // External devices.
351 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
352 device->setExternal(true);
353 }
354
Jeff Brown6d0fec22010-07-23 21:28:06 -0700355 // Switch-like devices.
356 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
357 device->addMapper(new SwitchInputMapper(device));
358 }
359
360 // Keyboard-like devices.
Jeff Brownefd32662011-03-08 15:13:06 -0800361 uint32_t keyboardSource = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700362 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
363 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800364 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700365 }
366 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
367 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
368 }
369 if (classes & INPUT_DEVICE_CLASS_DPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800370 keyboardSource |= AINPUT_SOURCE_DPAD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700371 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800372 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800373 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
Jeff Browncb1404e2011-01-15 18:14:15 -0800374 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700375
Jeff Brownefd32662011-03-08 15:13:06 -0800376 if (keyboardSource != 0) {
377 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 }
379
Jeff Brown83c09682010-12-23 17:50:18 -0800380 // Cursor-like devices.
381 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
382 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700383 }
384
Jeff Brown58a2da82011-01-25 16:02:22 -0800385 // Touchscreens and touchpad devices.
386 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800387 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800388 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800389 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700390 }
391
Jeff Browncb1404e2011-01-15 18:14:15 -0800392 // Joystick-like devices.
393 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
394 device->addMapper(new JoystickInputMapper(device));
395 }
396
Jeff Brown6d0fec22010-07-23 21:28:06 -0700397 return device;
398}
399
Jeff Browndbf8d272011-03-18 18:14:26 -0700400void InputReader::processEventsForDevice(int32_t deviceId,
401 const RawEvent* rawEvents, size_t count) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700402 { // acquire device registry reader lock
403 RWLock::AutoRLock _rl(mDeviceRegistryLock);
404
405 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
406 if (deviceIndex < 0) {
407 LOGW("Discarding event for unknown deviceId %d.", deviceId);
408 return;
409 }
410
411 InputDevice* device = mDevices.valueAt(deviceIndex);
412 if (device->isIgnored()) {
413 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
414 return;
415 }
416
Jeff Browndbf8d272011-03-18 18:14:26 -0700417 device->process(rawEvents, count);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700418 } // release device registry reader lock
419}
420
Jeff Brown68d60752011-03-17 01:34:19 -0700421void InputReader::timeoutExpired(nsecs_t when) {
422 { // acquire device registry reader lock
423 RWLock::AutoRLock _rl(mDeviceRegistryLock);
424
425 for (size_t i = 0; i < mDevices.size(); i++) {
426 InputDevice* device = mDevices.valueAt(i);
427 if (!device->isIgnored()) {
428 device->timeoutExpired(when);
429 }
430 }
431 } // release device registry reader lock
432}
433
Jeff Brownc3db8582010-10-20 15:33:38 -0700434void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700435 // Reset global meta state because it depends on the list of all configured devices.
436 updateGlobalMetaState();
437
438 // Update input configuration.
439 updateInputConfiguration();
440
441 // Enqueue configuration changed.
442 mDispatcher->notifyConfigurationChanged(when);
443}
444
Jeff Brown1a84fd12011-06-02 01:26:32 -0700445void InputReader::configure(bool firstTime) {
446 mPolicy->getReaderConfiguration(&mConfig);
447 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
448
449 if (!firstTime) {
450 mEventHub->reopenDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700451 }
452}
453
454void InputReader::updateGlobalMetaState() {
455 { // acquire state lock
456 AutoMutex _l(mStateLock);
457
458 mGlobalMetaState = 0;
459
460 { // acquire device registry reader lock
461 RWLock::AutoRLock _rl(mDeviceRegistryLock);
462
463 for (size_t i = 0; i < mDevices.size(); i++) {
464 InputDevice* device = mDevices.valueAt(i);
465 mGlobalMetaState |= device->getMetaState();
466 }
467 } // release device registry reader lock
468 } // release state lock
469}
470
471int32_t InputReader::getGlobalMetaState() {
472 { // acquire state lock
473 AutoMutex _l(mStateLock);
474
475 return mGlobalMetaState;
476 } // release state lock
477}
478
479void InputReader::updateInputConfiguration() {
480 { // acquire state lock
481 AutoMutex _l(mStateLock);
482
483 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
484 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
485 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
486 { // acquire device registry reader lock
487 RWLock::AutoRLock _rl(mDeviceRegistryLock);
488
489 InputDeviceInfo deviceInfo;
490 for (size_t i = 0; i < mDevices.size(); i++) {
491 InputDevice* device = mDevices.valueAt(i);
492 device->getDeviceInfo(& deviceInfo);
493 uint32_t sources = deviceInfo.getSources();
494
495 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
496 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
497 }
498 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
499 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
500 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
501 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
502 }
503 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
504 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700505 }
506 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700507 } // release device registry reader lock
Jeff Brown46b9ac02010-04-22 18:58:52 -0700508
Jeff Brown6d0fec22010-07-23 21:28:06 -0700509 mInputConfiguration.touchScreen = touchScreenConfig;
510 mInputConfiguration.keyboard = keyboardConfig;
511 mInputConfiguration.navigation = navigationConfig;
512 } // release state lock
513}
514
Jeff Brownfe508922011-01-18 15:10:10 -0800515void InputReader::disableVirtualKeysUntil(nsecs_t time) {
516 mDisableVirtualKeysTimeout = time;
517}
518
519bool InputReader::shouldDropVirtualKey(nsecs_t now,
520 InputDevice* device, int32_t keyCode, int32_t scanCode) {
521 if (now < mDisableVirtualKeysTimeout) {
522 LOGI("Dropping virtual key from device %s because virtual keys are "
523 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
524 device->getName().string(),
525 (mDisableVirtualKeysTimeout - now) * 0.000001,
526 keyCode, scanCode);
527 return true;
528 } else {
529 return false;
530 }
531}
532
Jeff Brown05dc66a2011-03-02 14:41:58 -0800533void InputReader::fadePointer() {
534 { // acquire device registry reader lock
535 RWLock::AutoRLock _rl(mDeviceRegistryLock);
536
537 for (size_t i = 0; i < mDevices.size(); i++) {
538 InputDevice* device = mDevices.valueAt(i);
539 device->fadePointer();
540 }
541 } // release device registry reader lock
542}
543
Jeff Brown68d60752011-03-17 01:34:19 -0700544void InputReader::requestTimeoutAtTime(nsecs_t when) {
545 if (when < mNextTimeout) {
546 mNextTimeout = when;
547 }
548}
549
Jeff Brown6d0fec22010-07-23 21:28:06 -0700550void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
551 { // acquire state lock
552 AutoMutex _l(mStateLock);
553
554 *outConfiguration = mInputConfiguration;
555 } // release state lock
556}
557
558status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
559 { // acquire device registry reader lock
560 RWLock::AutoRLock _rl(mDeviceRegistryLock);
561
562 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
563 if (deviceIndex < 0) {
564 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700565 }
566
Jeff Brown6d0fec22010-07-23 21:28:06 -0700567 InputDevice* device = mDevices.valueAt(deviceIndex);
568 if (device->isIgnored()) {
569 return NAME_NOT_FOUND;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700570 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700571
572 device->getDeviceInfo(outDeviceInfo);
573 return OK;
574 } // release device registy reader lock
575}
576
577void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
578 outDeviceIds.clear();
579
580 { // acquire device registry reader lock
581 RWLock::AutoRLock _rl(mDeviceRegistryLock);
582
583 size_t numDevices = mDevices.size();
584 for (size_t i = 0; i < numDevices; i++) {
585 InputDevice* device = mDevices.valueAt(i);
586 if (! device->isIgnored()) {
587 outDeviceIds.add(device->getId());
588 }
589 }
590 } // release device registy reader lock
591}
592
593int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
594 int32_t keyCode) {
595 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
596}
597
598int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
599 int32_t scanCode) {
600 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
601}
602
603int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
604 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
605}
606
607int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
608 GetStateFunc getStateFunc) {
609 { // acquire device registry reader lock
610 RWLock::AutoRLock _rl(mDeviceRegistryLock);
611
612 int32_t result = AKEY_STATE_UNKNOWN;
613 if (deviceId >= 0) {
614 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
615 if (deviceIndex >= 0) {
616 InputDevice* device = mDevices.valueAt(deviceIndex);
617 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
618 result = (device->*getStateFunc)(sourceMask, code);
619 }
620 }
621 } else {
622 size_t numDevices = mDevices.size();
623 for (size_t i = 0; i < numDevices; i++) {
624 InputDevice* device = mDevices.valueAt(i);
625 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
626 result = (device->*getStateFunc)(sourceMask, code);
627 if (result >= AKEY_STATE_DOWN) {
628 return result;
629 }
630 }
631 }
632 }
633 return result;
634 } // release device registy reader lock
635}
636
637bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
638 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
639 memset(outFlags, 0, numCodes);
640 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
641}
642
643bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
644 const int32_t* keyCodes, uint8_t* outFlags) {
645 { // acquire device registry reader lock
646 RWLock::AutoRLock _rl(mDeviceRegistryLock);
647 bool result = false;
648 if (deviceId >= 0) {
649 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
650 if (deviceIndex >= 0) {
651 InputDevice* device = mDevices.valueAt(deviceIndex);
652 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
653 result = device->markSupportedKeyCodes(sourceMask,
654 numCodes, keyCodes, outFlags);
655 }
656 }
657 } else {
658 size_t numDevices = mDevices.size();
659 for (size_t i = 0; i < numDevices; i++) {
660 InputDevice* device = mDevices.valueAt(i);
661 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
662 result |= device->markSupportedKeyCodes(sourceMask,
663 numCodes, keyCodes, outFlags);
664 }
665 }
666 }
667 return result;
668 } // release device registy reader lock
669}
670
Jeff Brown1a84fd12011-06-02 01:26:32 -0700671void InputReader::refreshConfiguration() {
672 android_atomic_release_store(1, &mRefreshConfiguration);
673}
674
Jeff Brownb88102f2010-09-08 11:49:43 -0700675void InputReader::dump(String8& dump) {
Jeff Brownf2f48712010-10-01 17:46:21 -0700676 mEventHub->dump(dump);
677 dump.append("\n");
678
679 dump.append("Input Reader State:\n");
680
Jeff Brownef3d7e82010-09-30 14:33:04 -0700681 { // acquire device registry reader lock
682 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700683
Jeff Brownef3d7e82010-09-30 14:33:04 -0700684 for (size_t i = 0; i < mDevices.size(); i++) {
685 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700686 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700687 } // release device registy reader lock
Jeff Brown214eaf42011-05-26 19:17:02 -0700688
689 dump.append(INDENT "Configuration:\n");
690 dump.append(INDENT2 "ExcludedDeviceNames: [");
691 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
692 if (i != 0) {
693 dump.append(", ");
694 }
695 dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
696 }
697 dump.append("]\n");
698 dump.appendFormat(INDENT2 "FilterTouchEvents: %s\n",
699 toString(mConfig.filterTouchEvents));
700 dump.appendFormat(INDENT2 "FilterJumpyTouchEvents: %s\n",
701 toString(mConfig.filterJumpyTouchEvents));
702 dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
703 mConfig.virtualKeyQuietTime * 0.000001f);
704
Jeff Brown19c97d462011-06-01 12:33:19 -0700705 dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
706 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
707 mConfig.pointerVelocityControlParameters.scale,
708 mConfig.pointerVelocityControlParameters.lowThreshold,
709 mConfig.pointerVelocityControlParameters.highThreshold,
710 mConfig.pointerVelocityControlParameters.acceleration);
711
712 dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
713 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
714 mConfig.wheelVelocityControlParameters.scale,
715 mConfig.wheelVelocityControlParameters.lowThreshold,
716 mConfig.wheelVelocityControlParameters.highThreshold,
717 mConfig.wheelVelocityControlParameters.acceleration);
718
Jeff Brown214eaf42011-05-26 19:17:02 -0700719 dump.appendFormat(INDENT2 "PointerGesture:\n");
720 dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
721 mConfig.pointerGestureQuietInterval * 0.000001f);
722 dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
723 mConfig.pointerGestureDragMinSwitchSpeed);
724 dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
725 mConfig.pointerGestureTapInterval * 0.000001f);
726 dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
727 mConfig.pointerGestureTapDragInterval * 0.000001f);
728 dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
729 mConfig.pointerGestureTapSlop);
730 dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
731 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -0700732 dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
733 mConfig.pointerGestureMultitouchMinDistance);
Jeff Brown214eaf42011-05-26 19:17:02 -0700734 dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
735 mConfig.pointerGestureSwipeTransitionAngleCosine);
736 dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
737 mConfig.pointerGestureSwipeMaxWidthRatio);
738 dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
739 mConfig.pointerGestureMovementSpeedRatio);
740 dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
741 mConfig.pointerGestureZoomSpeedRatio);
Jeff Brownb88102f2010-09-08 11:49:43 -0700742}
743
Jeff Brown6d0fec22010-07-23 21:28:06 -0700744
745// --- InputReaderThread ---
746
747InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
748 Thread(/*canCallJava*/ true), mReader(reader) {
749}
750
751InputReaderThread::~InputReaderThread() {
752}
753
754bool InputReaderThread::threadLoop() {
755 mReader->loopOnce();
756 return true;
757}
758
759
760// --- InputDevice ---
761
762InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
Jeff Brown56194eb2011-03-02 19:23:13 -0800763 mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700764}
765
766InputDevice::~InputDevice() {
767 size_t numMappers = mMappers.size();
768 for (size_t i = 0; i < numMappers; i++) {
769 delete mMappers[i];
770 }
771 mMappers.clear();
772}
773
Jeff Brownef3d7e82010-09-30 14:33:04 -0700774void InputDevice::dump(String8& dump) {
775 InputDeviceInfo deviceInfo;
776 getDeviceInfo(& deviceInfo);
777
Jeff Brown90655042010-12-02 13:50:46 -0800778 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700779 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800780 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700781 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
782 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800783
Jeff Brownefd32662011-03-08 15:13:06 -0800784 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
Jeff Browncc0c1592011-02-19 05:07:28 -0800785 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700786 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800787 for (size_t i = 0; i < ranges.size(); i++) {
Jeff Brownefd32662011-03-08 15:13:06 -0800788 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
789 const char* label = getAxisLabel(range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800790 char name[32];
791 if (label) {
792 strncpy(name, label, sizeof(name));
793 name[sizeof(name) - 1] = '\0';
794 } else {
Jeff Brownefd32662011-03-08 15:13:06 -0800795 snprintf(name, sizeof(name), "%d", range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800796 }
Jeff Brownefd32662011-03-08 15:13:06 -0800797 dump.appendFormat(INDENT3 "%s: source=0x%08x, "
798 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
799 name, range.source, range.min, range.max, range.flat, range.fuzz);
Jeff Browncc0c1592011-02-19 05:07:28 -0800800 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700801 }
802
803 size_t numMappers = mMappers.size();
804 for (size_t i = 0; i < numMappers; i++) {
805 InputMapper* mapper = mMappers[i];
806 mapper->dump(dump);
807 }
808}
809
Jeff Brown6d0fec22010-07-23 21:28:06 -0700810void InputDevice::addMapper(InputMapper* mapper) {
811 mMappers.add(mapper);
812}
813
814void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700815 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800816 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700817 }
818
Jeff Brown6d0fec22010-07-23 21:28:06 -0700819 mSources = 0;
820
821 size_t numMappers = mMappers.size();
822 for (size_t i = 0; i < numMappers; i++) {
823 InputMapper* mapper = mMappers[i];
824 mapper->configure();
825 mSources |= mapper->getSources();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700826 }
827}
828
Jeff Brown6d0fec22010-07-23 21:28:06 -0700829void InputDevice::reset() {
830 size_t numMappers = mMappers.size();
831 for (size_t i = 0; i < numMappers; i++) {
832 InputMapper* mapper = mMappers[i];
833 mapper->reset();
834 }
835}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700836
Jeff Browndbf8d272011-03-18 18:14:26 -0700837void InputDevice::process(const RawEvent* rawEvents, size_t count) {
838 // Process all of the events in order for each mapper.
839 // We cannot simply ask each mapper to process them in bulk because mappers may
840 // have side-effects that must be interleaved. For example, joystick movement events and
841 // gamepad button presses are handled by different mappers but they should be dispatched
842 // in the order received.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700843 size_t numMappers = mMappers.size();
Jeff Browndbf8d272011-03-18 18:14:26 -0700844 for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
845#if DEBUG_RAW_EVENTS
846 LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
847 "keycode=0x%04x value=0x%04x flags=0x%08x",
848 rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
849 rawEvent->value, rawEvent->flags);
850#endif
851
852 for (size_t i = 0; i < numMappers; i++) {
853 InputMapper* mapper = mMappers[i];
854 mapper->process(rawEvent);
855 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700856 }
857}
Jeff Brown46b9ac02010-04-22 18:58:52 -0700858
Jeff Brown68d60752011-03-17 01:34:19 -0700859void InputDevice::timeoutExpired(nsecs_t when) {
860 size_t numMappers = mMappers.size();
861 for (size_t i = 0; i < numMappers; i++) {
862 InputMapper* mapper = mMappers[i];
863 mapper->timeoutExpired(when);
864 }
865}
866
Jeff Brown6d0fec22010-07-23 21:28:06 -0700867void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
868 outDeviceInfo->initialize(mId, mName);
869
870 size_t numMappers = mMappers.size();
871 for (size_t i = 0; i < numMappers; i++) {
872 InputMapper* mapper = mMappers[i];
873 mapper->populateDeviceInfo(outDeviceInfo);
874 }
875}
876
877int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
878 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
879}
880
881int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
882 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
883}
884
885int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
886 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
887}
888
889int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
890 int32_t result = AKEY_STATE_UNKNOWN;
891 size_t numMappers = mMappers.size();
892 for (size_t i = 0; i < numMappers; i++) {
893 InputMapper* mapper = mMappers[i];
894 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
895 result = (mapper->*getStateFunc)(sourceMask, code);
896 if (result >= AKEY_STATE_DOWN) {
897 return result;
898 }
899 }
900 }
901 return result;
902}
903
904bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
905 const int32_t* keyCodes, uint8_t* outFlags) {
906 bool result = false;
907 size_t numMappers = mMappers.size();
908 for (size_t i = 0; i < numMappers; i++) {
909 InputMapper* mapper = mMappers[i];
910 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
911 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
912 }
913 }
914 return result;
915}
916
917int32_t InputDevice::getMetaState() {
918 int32_t result = 0;
919 size_t numMappers = mMappers.size();
920 for (size_t i = 0; i < numMappers; i++) {
921 InputMapper* mapper = mMappers[i];
922 result |= mapper->getMetaState();
923 }
924 return result;
925}
926
Jeff Brown05dc66a2011-03-02 14:41:58 -0800927void InputDevice::fadePointer() {
928 size_t numMappers = mMappers.size();
929 for (size_t i = 0; i < numMappers; i++) {
930 InputMapper* mapper = mMappers[i];
931 mapper->fadePointer();
932 }
933}
934
Jeff Brown6d0fec22010-07-23 21:28:06 -0700935
936// --- InputMapper ---
937
938InputMapper::InputMapper(InputDevice* device) :
939 mDevice(device), mContext(device->getContext()) {
940}
941
942InputMapper::~InputMapper() {
943}
944
945void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
946 info->addSource(getSources());
947}
948
Jeff Brownef3d7e82010-09-30 14:33:04 -0700949void InputMapper::dump(String8& dump) {
950}
951
Jeff Brown6d0fec22010-07-23 21:28:06 -0700952void InputMapper::configure() {
953}
954
955void InputMapper::reset() {
956}
957
Jeff Brown68d60752011-03-17 01:34:19 -0700958void InputMapper::timeoutExpired(nsecs_t when) {
959}
960
Jeff Brown6d0fec22010-07-23 21:28:06 -0700961int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
962 return AKEY_STATE_UNKNOWN;
963}
964
965int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
966 return AKEY_STATE_UNKNOWN;
967}
968
969int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
970 return AKEY_STATE_UNKNOWN;
971}
972
973bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
974 const int32_t* keyCodes, uint8_t* outFlags) {
975 return false;
976}
977
978int32_t InputMapper::getMetaState() {
979 return 0;
980}
981
Jeff Brown05dc66a2011-03-02 14:41:58 -0800982void InputMapper::fadePointer() {
983}
984
Jeff Browncb1404e2011-01-15 18:14:15 -0800985void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
986 const RawAbsoluteAxisInfo& axis, const char* name) {
987 if (axis.valid) {
988 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
989 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
990 } else {
991 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
992 }
993}
994
Jeff Brown6d0fec22010-07-23 21:28:06 -0700995
996// --- SwitchInputMapper ---
997
998SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
999 InputMapper(device) {
1000}
1001
1002SwitchInputMapper::~SwitchInputMapper() {
1003}
1004
1005uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -08001006 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001007}
1008
1009void SwitchInputMapper::process(const RawEvent* rawEvent) {
1010 switch (rawEvent->type) {
1011 case EV_SW:
1012 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
1013 break;
1014 }
1015}
1016
1017void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -07001018 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001019}
1020
1021int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1022 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1023}
1024
1025
1026// --- KeyboardInputMapper ---
1027
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001028KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brownefd32662011-03-08 15:13:06 -08001029 uint32_t source, int32_t keyboardType) :
1030 InputMapper(device), mSource(source),
Jeff Brown6d0fec22010-07-23 21:28:06 -07001031 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001032 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001033}
1034
1035KeyboardInputMapper::~KeyboardInputMapper() {
1036}
1037
Jeff Brown6328cdc2010-07-29 18:18:33 -07001038void KeyboardInputMapper::initializeLocked() {
1039 mLocked.metaState = AMETA_NONE;
1040 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001041}
1042
1043uint32_t KeyboardInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001044 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001045}
1046
1047void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1048 InputMapper::populateDeviceInfo(info);
1049
1050 info->setKeyboardType(mKeyboardType);
1051}
1052
Jeff Brownef3d7e82010-09-30 14:33:04 -07001053void KeyboardInputMapper::dump(String8& dump) {
1054 { // acquire lock
1055 AutoMutex _l(mLock);
1056 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001057 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001058 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
1059 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
1060 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
1061 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1062 } // release lock
1063}
1064
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001065
1066void KeyboardInputMapper::configure() {
1067 InputMapper::configure();
1068
1069 // Configure basic parameters.
1070 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001071
1072 // Reset LEDs.
1073 {
1074 AutoMutex _l(mLock);
1075 resetLedStateLocked();
1076 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001077}
1078
1079void KeyboardInputMapper::configureParameters() {
1080 mParameters.orientationAware = false;
1081 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
1082 mParameters.orientationAware);
1083
1084 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
1085}
1086
1087void KeyboardInputMapper::dumpParameters(String8& dump) {
1088 dump.append(INDENT3 "Parameters:\n");
1089 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1090 mParameters.associatedDisplayId);
1091 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1092 toString(mParameters.orientationAware));
1093}
1094
Jeff Brown6d0fec22010-07-23 21:28:06 -07001095void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001096 for (;;) {
1097 int32_t keyCode, scanCode;
1098 { // acquire lock
1099 AutoMutex _l(mLock);
1100
1101 // Synthesize key up event on reset if keys are currently down.
1102 if (mLocked.keyDowns.isEmpty()) {
1103 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001104 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001105 break; // done
1106 }
1107
1108 const KeyDown& keyDown = mLocked.keyDowns.top();
1109 keyCode = keyDown.keyCode;
1110 scanCode = keyDown.scanCode;
1111 } // release lock
1112
Jeff Brown6d0fec22010-07-23 21:28:06 -07001113 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001114 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001115 }
1116
1117 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001118 getContext()->updateGlobalMetaState();
1119}
1120
1121void KeyboardInputMapper::process(const RawEvent* rawEvent) {
1122 switch (rawEvent->type) {
1123 case EV_KEY: {
1124 int32_t scanCode = rawEvent->scanCode;
1125 if (isKeyboardOrGamepadKey(scanCode)) {
1126 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
1127 rawEvent->flags);
1128 }
1129 break;
1130 }
1131 }
1132}
1133
1134bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
1135 return scanCode < BTN_MOUSE
1136 || scanCode >= KEY_OK
Jeff Brown9e8e40c2011-03-03 03:39:29 -08001137 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
Jeff Browncb1404e2011-01-15 18:14:15 -08001138 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001139}
1140
Jeff Brown6328cdc2010-07-29 18:18:33 -07001141void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
1142 int32_t scanCode, uint32_t policyFlags) {
1143 int32_t newMetaState;
1144 nsecs_t downTime;
1145 bool metaStateChanged = false;
1146
1147 { // acquire lock
1148 AutoMutex _l(mLock);
1149
1150 if (down) {
1151 // Rotate key codes according to orientation if needed.
1152 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001153 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001154 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001155 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1156 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001157 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001158 }
1159
1160 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001161 }
1162
Jeff Brown6328cdc2010-07-29 18:18:33 -07001163 // Add key down.
1164 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1165 if (keyDownIndex >= 0) {
1166 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001167 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001168 } else {
1169 // key down
Jeff Brownfe508922011-01-18 15:10:10 -08001170 if ((policyFlags & POLICY_FLAG_VIRTUAL)
1171 && mContext->shouldDropVirtualKey(when,
1172 getDevice(), keyCode, scanCode)) {
1173 return;
1174 }
1175
Jeff Brown6328cdc2010-07-29 18:18:33 -07001176 mLocked.keyDowns.push();
1177 KeyDown& keyDown = mLocked.keyDowns.editTop();
1178 keyDown.keyCode = keyCode;
1179 keyDown.scanCode = scanCode;
1180 }
1181
1182 mLocked.downTime = when;
1183 } else {
1184 // Remove key down.
1185 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1186 if (keyDownIndex >= 0) {
1187 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001188 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001189 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1190 } else {
1191 // key was not actually down
1192 LOGI("Dropping key up from device %s because the key was not down. "
1193 "keyCode=%d, scanCode=%d",
1194 getDeviceName().string(), keyCode, scanCode);
1195 return;
1196 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001197 }
1198
Jeff Brown6328cdc2010-07-29 18:18:33 -07001199 int32_t oldMetaState = mLocked.metaState;
1200 newMetaState = updateMetaState(keyCode, down, oldMetaState);
1201 if (oldMetaState != newMetaState) {
1202 mLocked.metaState = newMetaState;
1203 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -07001204 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001205 }
Jeff Brownfd035822010-06-30 16:10:35 -07001206
Jeff Brown6328cdc2010-07-29 18:18:33 -07001207 downTime = mLocked.downTime;
1208 } // release lock
1209
Jeff Brown56194eb2011-03-02 19:23:13 -08001210 // Key down on external an keyboard should wake the device.
1211 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1212 // For internal keyboards, the key layout file should specify the policy flags for
1213 // each wake key individually.
1214 // TODO: Use the input device configuration to control this behavior more finely.
1215 if (down && getDevice()->isExternal()
1216 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1217 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1218 }
1219
Jeff Brown6328cdc2010-07-29 18:18:33 -07001220 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001221 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001222 }
1223
Jeff Brown05dc66a2011-03-02 14:41:58 -08001224 if (down && !isMetaKey(keyCode)) {
1225 getContext()->fadePointer();
1226 }
1227
Jeff Brownefd32662011-03-08 15:13:06 -08001228 getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001229 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1230 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001231}
1232
Jeff Brown6328cdc2010-07-29 18:18:33 -07001233ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1234 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001235 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001236 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001237 return i;
1238 }
1239 }
1240 return -1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001241}
1242
Jeff Brown6d0fec22010-07-23 21:28:06 -07001243int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1244 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1245}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001246
Jeff Brown6d0fec22010-07-23 21:28:06 -07001247int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1248 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1249}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001250
Jeff Brown6d0fec22010-07-23 21:28:06 -07001251bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1252 const int32_t* keyCodes, uint8_t* outFlags) {
1253 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1254}
1255
1256int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001257 { // acquire lock
1258 AutoMutex _l(mLock);
1259 return mLocked.metaState;
1260 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001261}
1262
Jeff Brown49ed71d2010-12-06 17:13:33 -08001263void KeyboardInputMapper::resetLedStateLocked() {
1264 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1265 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1266 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1267
1268 updateLedStateLocked(true);
1269}
1270
1271void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1272 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1273 ledState.on = false;
1274}
1275
Jeff Brown497a92c2010-09-12 17:55:08 -07001276void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1277 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001278 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001279 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001280 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001281 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe72010-10-29 22:19:53 -07001282 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001283}
1284
1285void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1286 int32_t led, int32_t modifier, bool reset) {
1287 if (ledState.avail) {
1288 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001289 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001290 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1291 ledState.on = desiredState;
1292 }
1293 }
1294}
1295
Jeff Brown6d0fec22010-07-23 21:28:06 -07001296
Jeff Brown83c09682010-12-23 17:50:18 -08001297// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001298
Jeff Brown83c09682010-12-23 17:50:18 -08001299CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001300 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001301 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001302}
1303
Jeff Brown83c09682010-12-23 17:50:18 -08001304CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001305}
1306
Jeff Brown83c09682010-12-23 17:50:18 -08001307uint32_t CursorInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001308 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001309}
1310
Jeff Brown83c09682010-12-23 17:50:18 -08001311void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001312 InputMapper::populateDeviceInfo(info);
1313
Jeff Brown83c09682010-12-23 17:50:18 -08001314 if (mParameters.mode == Parameters::MODE_POINTER) {
1315 float minX, minY, maxX, maxY;
1316 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brownefd32662011-03-08 15:13:06 -08001317 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
1318 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001319 }
1320 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001321 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
1322 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001323 }
Jeff Brownefd32662011-03-08 15:13:06 -08001324 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001325
1326 if (mHaveVWheel) {
Jeff Brownefd32662011-03-08 15:13:06 -08001327 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001328 }
1329 if (mHaveHWheel) {
Jeff Brownefd32662011-03-08 15:13:06 -08001330 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001331 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001332}
1333
Jeff Brown83c09682010-12-23 17:50:18 -08001334void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001335 { // acquire lock
1336 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001337 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001338 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001339 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1340 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001341 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1342 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001343 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1344 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1345 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1346 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001347 dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
1348 dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState)));
Jeff Brownef3d7e82010-09-30 14:33:04 -07001349 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1350 } // release lock
1351}
1352
Jeff Brown83c09682010-12-23 17:50:18 -08001353void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001354 InputMapper::configure();
1355
1356 // Configure basic parameters.
1357 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001358
1359 // Configure device mode.
1360 switch (mParameters.mode) {
1361 case Parameters::MODE_POINTER:
Jeff Brownefd32662011-03-08 15:13:06 -08001362 mSource = AINPUT_SOURCE_MOUSE;
Jeff Brown83c09682010-12-23 17:50:18 -08001363 mXPrecision = 1.0f;
1364 mYPrecision = 1.0f;
1365 mXScale = 1.0f;
1366 mYScale = 1.0f;
1367 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1368 break;
1369 case Parameters::MODE_NAVIGATION:
Jeff Brownefd32662011-03-08 15:13:06 -08001370 mSource = AINPUT_SOURCE_TRACKBALL;
Jeff Brown83c09682010-12-23 17:50:18 -08001371 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1372 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1373 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1374 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1375 break;
1376 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001377
1378 mVWheelScale = 1.0f;
1379 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001380
1381 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1382 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown19c97d462011-06-01 12:33:19 -07001383
1384 mPointerVelocityControl.setParameters(getConfig()->pointerVelocityControlParameters);
1385 mWheelXVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters);
1386 mWheelYVelocityControl.setParameters(getConfig()->wheelVelocityControlParameters);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001387}
1388
Jeff Brown83c09682010-12-23 17:50:18 -08001389void CursorInputMapper::configureParameters() {
1390 mParameters.mode = Parameters::MODE_POINTER;
1391 String8 cursorModeString;
1392 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1393 if (cursorModeString == "navigation") {
1394 mParameters.mode = Parameters::MODE_NAVIGATION;
1395 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1396 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1397 }
1398 }
1399
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001400 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001401 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001402 mParameters.orientationAware);
1403
Jeff Brown83c09682010-12-23 17:50:18 -08001404 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1405 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001406}
1407
Jeff Brown83c09682010-12-23 17:50:18 -08001408void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001409 dump.append(INDENT3 "Parameters:\n");
1410 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1411 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001412
1413 switch (mParameters.mode) {
1414 case Parameters::MODE_POINTER:
1415 dump.append(INDENT4 "Mode: pointer\n");
1416 break;
1417 case Parameters::MODE_NAVIGATION:
1418 dump.append(INDENT4 "Mode: navigation\n");
1419 break;
1420 default:
1421 assert(false);
1422 }
1423
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001424 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1425 toString(mParameters.orientationAware));
1426}
1427
Jeff Brown83c09682010-12-23 17:50:18 -08001428void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001429 mAccumulator.clear();
1430
Jeff Brownefd32662011-03-08 15:13:06 -08001431 mLocked.buttonState = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001432 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001433}
1434
Jeff Brown83c09682010-12-23 17:50:18 -08001435void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001436 for (;;) {
Jeff Brownefd32662011-03-08 15:13:06 -08001437 uint32_t buttonState;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001438 { // acquire lock
1439 AutoMutex _l(mLock);
1440
Jeff Brownefd32662011-03-08 15:13:06 -08001441 buttonState = mLocked.buttonState;
1442 if (!buttonState) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001443 initializeLocked();
1444 break; // done
1445 }
1446 } // release lock
1447
Jeff Brown19c97d462011-06-01 12:33:19 -07001448 // Reset velocity.
1449 mPointerVelocityControl.reset();
1450 mWheelXVelocityControl.reset();
1451 mWheelYVelocityControl.reset();
1452
Jeff Brown83c09682010-12-23 17:50:18 -08001453 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001454 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownefd32662011-03-08 15:13:06 -08001455 mAccumulator.clear();
1456 mAccumulator.buttonDown = 0;
1457 mAccumulator.buttonUp = buttonState;
1458 mAccumulator.fields = Accumulator::FIELD_BUTTONS;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001459 sync(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001460 }
1461
Jeff Brown6d0fec22010-07-23 21:28:06 -07001462 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001463}
Jeff Brown46b9ac02010-04-22 18:58:52 -07001464
Jeff Brown83c09682010-12-23 17:50:18 -08001465void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001466 switch (rawEvent->type) {
Jeff Brownefd32662011-03-08 15:13:06 -08001467 case EV_KEY: {
1468 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
1469 if (buttonState) {
1470 if (rawEvent->value) {
1471 mAccumulator.buttonDown = buttonState;
1472 mAccumulator.buttonUp = 0;
1473 } else {
1474 mAccumulator.buttonDown = 0;
1475 mAccumulator.buttonUp = buttonState;
1476 }
1477 mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
1478
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001479 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1480 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001481 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001482 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001483 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001484 break;
Jeff Brownefd32662011-03-08 15:13:06 -08001485 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001486
Jeff Brown6d0fec22010-07-23 21:28:06 -07001487 case EV_REL:
1488 switch (rawEvent->scanCode) {
1489 case REL_X:
1490 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1491 mAccumulator.relX = rawEvent->value;
1492 break;
1493 case REL_Y:
1494 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1495 mAccumulator.relY = rawEvent->value;
1496 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001497 case REL_WHEEL:
1498 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1499 mAccumulator.relWheel = rawEvent->value;
1500 break;
1501 case REL_HWHEEL:
1502 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1503 mAccumulator.relHWheel = rawEvent->value;
1504 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001505 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001506 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001507
Jeff Brown6d0fec22010-07-23 21:28:06 -07001508 case EV_SYN:
1509 switch (rawEvent->scanCode) {
1510 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001511 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001512 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001513 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001514 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001515 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001516}
1517
Jeff Brown83c09682010-12-23 17:50:18 -08001518void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001519 uint32_t fields = mAccumulator.fields;
1520 if (fields == 0) {
1521 return; // no new state changes, so nothing to do
1522 }
1523
Jeff Brown9626b142011-03-03 02:09:54 -08001524 int32_t motionEventAction;
1525 int32_t motionEventEdgeFlags;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001526 PointerCoords pointerCoords;
1527 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001528 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001529 { // acquire lock
1530 AutoMutex _l(mLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001531
Jeff Brownefd32662011-03-08 15:13:06 -08001532 bool down, downChanged;
1533 bool wasDown = isPointerDown(mLocked.buttonState);
1534 bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
1535 if (buttonsChanged) {
1536 mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
1537 & ~mAccumulator.buttonUp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001538
Jeff Brownefd32662011-03-08 15:13:06 -08001539 down = isPointerDown(mLocked.buttonState);
1540
1541 if (!wasDown && down) {
1542 mLocked.downTime = when;
1543 downChanged = true;
1544 } else if (wasDown && !down) {
1545 downChanged = true;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001546 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001547 downChanged = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001548 }
Jeff Brownefd32662011-03-08 15:13:06 -08001549 } else {
1550 down = wasDown;
1551 downChanged = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001552 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001553
Jeff Brown6328cdc2010-07-29 18:18:33 -07001554 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001555 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1556 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001557
Jeff Brown6328cdc2010-07-29 18:18:33 -07001558 if (downChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08001559 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1560 } else if (down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001561 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001562 } else {
1563 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001564 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001565
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001566 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001567 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001568 // Rotate motion based on display orientation if needed.
1569 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1570 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001571 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1572 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001573 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001574 }
1575
1576 float temp;
1577 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001578 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001579 temp = deltaX;
1580 deltaX = deltaY;
1581 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001582 break;
1583
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001584 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001585 deltaX = -deltaX;
1586 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001587 break;
1588
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001589 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001590 temp = deltaX;
1591 deltaX = -deltaY;
1592 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001593 break;
1594 }
1595 }
Jeff Brown83c09682010-12-23 17:50:18 -08001596
Jeff Brown91c69ab2011-02-14 17:03:18 -08001597 pointerCoords.clear();
1598
Jeff Brown9626b142011-03-03 02:09:54 -08001599 motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
1600
Jeff Brown86ea1f52011-04-12 22:39:53 -07001601 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1602 vscroll = mAccumulator.relWheel;
1603 } else {
1604 vscroll = 0;
1605 }
Jeff Brown19c97d462011-06-01 12:33:19 -07001606 mWheelYVelocityControl.move(when, NULL, &vscroll);
1607
Jeff Brown86ea1f52011-04-12 22:39:53 -07001608 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1609 hscroll = mAccumulator.relHWheel;
1610 } else {
1611 hscroll = 0;
1612 }
Jeff Brown19c97d462011-06-01 12:33:19 -07001613 mWheelXVelocityControl.move(when, &hscroll, NULL);
1614
1615 mPointerVelocityControl.move(when, &deltaX, &deltaY);
Jeff Brown86ea1f52011-04-12 22:39:53 -07001616
Jeff Brown83c09682010-12-23 17:50:18 -08001617 if (mPointerController != NULL) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07001618 if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
1619 || buttonsChanged) {
1620 mPointerController->setPresentation(
1621 PointerControllerInterface::PRESENTATION_POINTER);
1622
1623 if (deltaX != 0 || deltaY != 0) {
1624 mPointerController->move(deltaX, deltaY);
1625 }
1626
1627 if (buttonsChanged) {
1628 mPointerController->setButtonState(mLocked.buttonState);
1629 }
1630
Jeff Brown538881e2011-05-25 18:23:38 -07001631 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
Jeff Brown83c09682010-12-23 17:50:18 -08001632 }
Jeff Brownefd32662011-03-08 15:13:06 -08001633
Jeff Brown91c69ab2011-02-14 17:03:18 -08001634 float x, y;
1635 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001636 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1637 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown9626b142011-03-03 02:09:54 -08001638
1639 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownefd32662011-03-08 15:13:06 -08001640 motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds(
1641 mPointerController, x, y);
Jeff Brown9626b142011-03-03 02:09:54 -08001642 }
Jeff Brown83c09682010-12-23 17:50:18 -08001643 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001644 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1645 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001646 }
1647
Jeff Brownefd32662011-03-08 15:13:06 -08001648 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001649 } // release lock
1650
Jeff Brown56194eb2011-03-02 19:23:13 -08001651 // Moving an external trackball or mouse should wake the device.
1652 // We don't do this for internal cursor devices to prevent them from waking up
1653 // the device in your pocket.
1654 // TODO: Use the input device configuration to control this behavior more finely.
1655 uint32_t policyFlags = 0;
1656 if (getDevice()->isExternal()) {
1657 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1658 }
1659
Jeff Brown6d0fec22010-07-23 21:28:06 -07001660 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001661 int32_t pointerId = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08001662 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brown9626b142011-03-03 02:09:54 -08001663 motionEventAction, 0, metaState, motionEventEdgeFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001664 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1665
1666 mAccumulator.clear();
Jeff Brown33bbfd22011-02-24 20:55:35 -08001667
1668 if (vscroll != 0 || hscroll != 0) {
1669 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1670 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1671
Jeff Brownefd32662011-03-08 15:13:06 -08001672 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brown33bbfd22011-02-24 20:55:35 -08001673 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1674 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1675 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001676}
1677
Jeff Brown83c09682010-12-23 17:50:18 -08001678int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001679 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1680 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1681 } else {
1682 return AKEY_STATE_UNKNOWN;
1683 }
1684}
1685
Jeff Brown05dc66a2011-03-02 14:41:58 -08001686void CursorInputMapper::fadePointer() {
1687 { // acquire lock
1688 AutoMutex _l(mLock);
Jeff Brownefd32662011-03-08 15:13:06 -08001689 if (mPointerController != NULL) {
Jeff Brown538881e2011-05-25 18:23:38 -07001690 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Jeff Brownefd32662011-03-08 15:13:06 -08001691 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001692 } // release lock
1693}
1694
Jeff Brown6d0fec22010-07-23 21:28:06 -07001695
1696// --- TouchInputMapper ---
1697
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001698TouchInputMapper::TouchInputMapper(InputDevice* device) :
1699 InputMapper(device) {
Jeff Brown214eaf42011-05-26 19:17:02 -07001700 mConfig = getConfig();
1701
Jeff Brown6328cdc2010-07-29 18:18:33 -07001702 mLocked.surfaceOrientation = -1;
1703 mLocked.surfaceWidth = -1;
1704 mLocked.surfaceHeight = -1;
1705
1706 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001707}
1708
1709TouchInputMapper::~TouchInputMapper() {
1710}
1711
1712uint32_t TouchInputMapper::getSources() {
Jeff Brown96ad3972011-03-09 17:39:48 -08001713 return mTouchSource | mPointerSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001714}
1715
1716void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1717 InputMapper::populateDeviceInfo(info);
1718
Jeff Brown6328cdc2010-07-29 18:18:33 -07001719 { // acquire lock
1720 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001721
Jeff Brown6328cdc2010-07-29 18:18:33 -07001722 // Ensure surface information is up to date so that orientation changes are
1723 // noticed immediately.
Jeff Brownefd32662011-03-08 15:13:06 -08001724 if (!configureSurfaceLocked()) {
1725 return;
1726 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001727
Jeff Brownefd32662011-03-08 15:13:06 -08001728 info->addMotionRange(mLocked.orientedRanges.x);
1729 info->addMotionRange(mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001730
1731 if (mLocked.orientedRanges.havePressure) {
Jeff Brownefd32662011-03-08 15:13:06 -08001732 info->addMotionRange(mLocked.orientedRanges.pressure);
Jeff Brown8d608662010-08-30 03:02:23 -07001733 }
1734
1735 if (mLocked.orientedRanges.haveSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001736 info->addMotionRange(mLocked.orientedRanges.size);
Jeff Brown8d608662010-08-30 03:02:23 -07001737 }
1738
Jeff Brownc6d282b2010-10-14 21:42:15 -07001739 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001740 info->addMotionRange(mLocked.orientedRanges.touchMajor);
1741 info->addMotionRange(mLocked.orientedRanges.touchMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07001742 }
1743
Jeff Brownc6d282b2010-10-14 21:42:15 -07001744 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001745 info->addMotionRange(mLocked.orientedRanges.toolMajor);
1746 info->addMotionRange(mLocked.orientedRanges.toolMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07001747 }
1748
1749 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brownefd32662011-03-08 15:13:06 -08001750 info->addMotionRange(mLocked.orientedRanges.orientation);
Jeff Brown8d608662010-08-30 03:02:23 -07001751 }
Jeff Brown96ad3972011-03-09 17:39:48 -08001752
1753 if (mPointerController != NULL) {
1754 float minX, minY, maxX, maxY;
1755 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1756 info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource,
1757 minX, maxX, 0.0f, 0.0f);
1758 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource,
1759 minY, maxY, 0.0f, 0.0f);
1760 }
1761 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource,
1762 0.0f, 1.0f, 0.0f, 0.0f);
1763 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001764 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001765}
1766
Jeff Brownef3d7e82010-09-30 14:33:04 -07001767void TouchInputMapper::dump(String8& dump) {
1768 { // acquire lock
1769 AutoMutex _l(mLock);
1770 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001771 dumpParameters(dump);
1772 dumpVirtualKeysLocked(dump);
1773 dumpRawAxes(dump);
1774 dumpCalibration(dump);
1775 dumpSurfaceLocked(dump);
Jeff Brownefd32662011-03-08 15:13:06 -08001776
Jeff Brown511ee5f2010-10-18 13:32:20 -07001777 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001778 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1779 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1780 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1781 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1782 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1783 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1784 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1785 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1786 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1787 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1788 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001789 dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale);
1790
1791 dump.appendFormat(INDENT3 "Last Touch:\n");
1792 dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
Jeff Brown96ad3972011-03-09 17:39:48 -08001793 dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
1794
1795 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
1796 dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
1797 dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
1798 mLocked.pointerGestureXMovementScale);
1799 dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
1800 mLocked.pointerGestureYMovementScale);
1801 dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
1802 mLocked.pointerGestureXZoomScale);
1803 dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
1804 mLocked.pointerGestureYZoomScale);
Jeff Brown86ea1f52011-04-12 22:39:53 -07001805 dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
1806 mLocked.pointerGestureMaxSwipeWidth);
Jeff Brown96ad3972011-03-09 17:39:48 -08001807 }
Jeff Brownef3d7e82010-09-30 14:33:04 -07001808 } // release lock
1809}
1810
Jeff Brown6328cdc2010-07-29 18:18:33 -07001811void TouchInputMapper::initializeLocked() {
1812 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001813 mLastTouch.clear();
1814 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001815
1816 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1817 mAveragingTouchFilter.historyStart[i] = 0;
1818 mAveragingTouchFilter.historyEnd[i] = 0;
1819 }
1820
1821 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001822
1823 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001824
1825 mLocked.orientedRanges.havePressure = false;
1826 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001827 mLocked.orientedRanges.haveTouchSize = false;
1828 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001829 mLocked.orientedRanges.haveOrientation = false;
Jeff Brown96ad3972011-03-09 17:39:48 -08001830
1831 mPointerGesture.reset();
Jeff Brown19c97d462011-06-01 12:33:19 -07001832 mPointerGesture.pointerVelocityControl.setParameters(mConfig->pointerVelocityControlParameters);
Jeff Brown8d608662010-08-30 03:02:23 -07001833}
1834
Jeff Brown6d0fec22010-07-23 21:28:06 -07001835void TouchInputMapper::configure() {
1836 InputMapper::configure();
1837
1838 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001839 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001840
Jeff Brown83c09682010-12-23 17:50:18 -08001841 // Configure sources.
1842 switch (mParameters.deviceType) {
1843 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
Jeff Brownefd32662011-03-08 15:13:06 -08001844 mTouchSource = AINPUT_SOURCE_TOUCHSCREEN;
Jeff Brown96ad3972011-03-09 17:39:48 -08001845 mPointerSource = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001846 break;
1847 case Parameters::DEVICE_TYPE_TOUCH_PAD:
Jeff Brownefd32662011-03-08 15:13:06 -08001848 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
Jeff Brown96ad3972011-03-09 17:39:48 -08001849 mPointerSource = 0;
1850 break;
1851 case Parameters::DEVICE_TYPE_POINTER:
1852 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
1853 mPointerSource = AINPUT_SOURCE_MOUSE;
Jeff Brown83c09682010-12-23 17:50:18 -08001854 break;
1855 default:
1856 assert(false);
1857 }
1858
Jeff Brown6d0fec22010-07-23 21:28:06 -07001859 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001860 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001861
1862 // Prepare input device calibration.
1863 parseCalibration();
1864 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001865
Jeff Brown6328cdc2010-07-29 18:18:33 -07001866 { // acquire lock
1867 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001868
Jeff Brown8d608662010-08-30 03:02:23 -07001869 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001870 configureSurfaceLocked();
1871 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001872}
1873
Jeff Brown8d608662010-08-30 03:02:23 -07001874void TouchInputMapper::configureParameters() {
Jeff Brown214eaf42011-05-26 19:17:02 -07001875 mParameters.useBadTouchFilter = mConfig->filterTouchEvents;
1876 mParameters.useAveragingTouchFilter = mConfig->filterTouchEvents;
1877 mParameters.useJumpyTouchFilter = mConfig->filterJumpyTouchEvents;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001878
Jeff Brown538881e2011-05-25 18:23:38 -07001879 // TODO: select the default gesture mode based on whether the device supports
1880 // distinct multitouch
Jeff Brown86ea1f52011-04-12 22:39:53 -07001881 mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
1882
Jeff Brown538881e2011-05-25 18:23:38 -07001883 String8 gestureModeString;
1884 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
1885 gestureModeString)) {
1886 if (gestureModeString == "pointer") {
1887 mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
1888 } else if (gestureModeString == "spots") {
1889 mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
1890 } else if (gestureModeString != "default") {
1891 LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
1892 }
1893 }
1894
Jeff Brown96ad3972011-03-09 17:39:48 -08001895 if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
1896 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
1897 // The device is a cursor device with a touch pad attached.
1898 // By default don't use the touch pad to move the pointer.
1899 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1900 } else {
1901 // The device is just a touch pad.
1902 // By default use the touch pad to move the pointer and to perform related gestures.
1903 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
1904 }
1905
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001906 String8 deviceTypeString;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001907 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1908 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001909 if (deviceTypeString == "touchScreen") {
1910 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brownefd32662011-03-08 15:13:06 -08001911 } else if (deviceTypeString == "touchPad") {
1912 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown96ad3972011-03-09 17:39:48 -08001913 } else if (deviceTypeString == "pointer") {
1914 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
Jeff Brown538881e2011-05-25 18:23:38 -07001915 } else if (deviceTypeString != "default") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001916 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1917 }
1918 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001919
Jeff Brownefd32662011-03-08 15:13:06 -08001920 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001921 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1922 mParameters.orientationAware);
1923
Jeff Brownefd32662011-03-08 15:13:06 -08001924 mParameters.associatedDisplayId = mParameters.orientationAware
1925 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
Jeff Brown96ad3972011-03-09 17:39:48 -08001926 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
Jeff Brownefd32662011-03-08 15:13:06 -08001927 ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001928}
1929
Jeff Brownef3d7e82010-09-30 14:33:04 -07001930void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001931 dump.append(INDENT3 "Parameters:\n");
1932
Jeff Brown538881e2011-05-25 18:23:38 -07001933 switch (mParameters.gestureMode) {
1934 case Parameters::GESTURE_MODE_POINTER:
1935 dump.append(INDENT4 "GestureMode: pointer\n");
1936 break;
1937 case Parameters::GESTURE_MODE_SPOTS:
1938 dump.append(INDENT4 "GestureMode: spots\n");
1939 break;
1940 default:
1941 assert(false);
1942 }
1943
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001944 switch (mParameters.deviceType) {
1945 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1946 dump.append(INDENT4 "DeviceType: touchScreen\n");
1947 break;
1948 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1949 dump.append(INDENT4 "DeviceType: touchPad\n");
1950 break;
Jeff Brown96ad3972011-03-09 17:39:48 -08001951 case Parameters::DEVICE_TYPE_POINTER:
1952 dump.append(INDENT4 "DeviceType: pointer\n");
1953 break;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001954 default:
1955 assert(false);
1956 }
1957
1958 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1959 mParameters.associatedDisplayId);
1960 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1961 toString(mParameters.orientationAware));
1962
1963 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001964 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001965 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001966 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001967 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001968 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001969}
1970
Jeff Brown8d608662010-08-30 03:02:23 -07001971void TouchInputMapper::configureRawAxes() {
1972 mRawAxes.x.clear();
1973 mRawAxes.y.clear();
1974 mRawAxes.pressure.clear();
1975 mRawAxes.touchMajor.clear();
1976 mRawAxes.touchMinor.clear();
1977 mRawAxes.toolMajor.clear();
1978 mRawAxes.toolMinor.clear();
1979 mRawAxes.orientation.clear();
1980}
1981
Jeff Brownef3d7e82010-09-30 14:33:04 -07001982void TouchInputMapper::dumpRawAxes(String8& dump) {
1983 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001984 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1985 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1986 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1987 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1988 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1989 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1990 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1991 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001992}
1993
Jeff Brown6328cdc2010-07-29 18:18:33 -07001994bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown9626b142011-03-03 02:09:54 -08001995 // Ensure we have valid X and Y axes.
1996 if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
1997 LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
1998 "The device will be inoperable.", getDeviceName().string());
1999 return false;
2000 }
2001
Jeff Brown6d0fec22010-07-23 21:28:06 -07002002 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002003 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown9626b142011-03-03 02:09:54 -08002004 int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2005 int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002006
2007 if (mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002008 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002009 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
Jeff Brownefd32662011-03-08 15:13:06 -08002010 &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
2011 &mLocked.associatedDisplayOrientation)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002012 return false;
2013 }
Jeff Brownefd32662011-03-08 15:13:06 -08002014
2015 // A touch screen inherits the dimensions of the display.
2016 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2017 width = mLocked.associatedDisplayWidth;
2018 height = mLocked.associatedDisplayHeight;
2019 }
2020
2021 // The device inherits the orientation of the display if it is orientation aware.
2022 if (mParameters.orientationAware) {
2023 orientation = mLocked.associatedDisplayOrientation;
2024 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002025 }
2026
Jeff Brown96ad3972011-03-09 17:39:48 -08002027 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2028 && mPointerController == NULL) {
2029 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2030 }
2031
Jeff Brown6328cdc2010-07-29 18:18:33 -07002032 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002033 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002034 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002035 }
2036
Jeff Brown6328cdc2010-07-29 18:18:33 -07002037 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002038 if (sizeChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08002039 LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07002040 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07002041
Jeff Brown6328cdc2010-07-29 18:18:33 -07002042 mLocked.surfaceWidth = width;
2043 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002044
Jeff Brown8d608662010-08-30 03:02:23 -07002045 // Configure X and Y factors.
Jeff Brown9626b142011-03-03 02:09:54 -08002046 mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
2047 mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
2048 mLocked.xPrecision = 1.0f / mLocked.xScale;
2049 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002050
Jeff Brownefd32662011-03-08 15:13:06 -08002051 mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
2052 mLocked.orientedRanges.x.source = mTouchSource;
2053 mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
2054 mLocked.orientedRanges.y.source = mTouchSource;
2055
Jeff Brown9626b142011-03-03 02:09:54 -08002056 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002057
Jeff Brown8d608662010-08-30 03:02:23 -07002058 // Scale factor for terms that are not oriented in a particular axis.
2059 // If the pixels are square then xScale == yScale otherwise we fake it
2060 // by choosing an average.
2061 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002062
Jeff Brown8d608662010-08-30 03:02:23 -07002063 // Size of diagonal axis.
Jeff Brown86ea1f52011-04-12 22:39:53 -07002064 float diagonalSize = hypotf(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002065
Jeff Brown8d608662010-08-30 03:02:23 -07002066 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002067 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
2068 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002069
2070 mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
2071 mLocked.orientedRanges.touchMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002072 mLocked.orientedRanges.touchMajor.min = 0;
2073 mLocked.orientedRanges.touchMajor.max = diagonalSize;
2074 mLocked.orientedRanges.touchMajor.flat = 0;
2075 mLocked.orientedRanges.touchMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002076
Jeff Brown8d608662010-08-30 03:02:23 -07002077 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08002078 mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002079 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002080
Jeff Brown8d608662010-08-30 03:02:23 -07002081 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002082 mLocked.toolSizeLinearScale = 0;
2083 mLocked.toolSizeLinearBias = 0;
2084 mLocked.toolSizeAreaScale = 0;
2085 mLocked.toolSizeAreaBias = 0;
2086 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2087 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
2088 if (mCalibration.haveToolSizeLinearScale) {
2089 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07002090 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002091 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07002092 / mRawAxes.toolMajor.maxValue;
2093 }
2094
Jeff Brownc6d282b2010-10-14 21:42:15 -07002095 if (mCalibration.haveToolSizeLinearBias) {
2096 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2097 }
2098 } else if (mCalibration.toolSizeCalibration ==
2099 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
2100 if (mCalibration.haveToolSizeLinearScale) {
2101 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2102 } else {
2103 mLocked.toolSizeLinearScale = min(width, height);
2104 }
2105
2106 if (mCalibration.haveToolSizeLinearBias) {
2107 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2108 }
2109
2110 if (mCalibration.haveToolSizeAreaScale) {
2111 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
2112 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2113 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
2114 }
2115
2116 if (mCalibration.haveToolSizeAreaBias) {
2117 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07002118 }
2119 }
2120
Jeff Brownc6d282b2010-10-14 21:42:15 -07002121 mLocked.orientedRanges.haveToolSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002122
2123 mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
2124 mLocked.orientedRanges.toolMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002125 mLocked.orientedRanges.toolMajor.min = 0;
2126 mLocked.orientedRanges.toolMajor.max = diagonalSize;
2127 mLocked.orientedRanges.toolMajor.flat = 0;
2128 mLocked.orientedRanges.toolMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002129
Jeff Brown8d608662010-08-30 03:02:23 -07002130 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08002131 mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002132 }
2133
2134 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002135 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002136 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
2137 RawAbsoluteAxisInfo rawPressureAxis;
2138 switch (mCalibration.pressureSource) {
2139 case Calibration::PRESSURE_SOURCE_PRESSURE:
2140 rawPressureAxis = mRawAxes.pressure;
2141 break;
2142 case Calibration::PRESSURE_SOURCE_TOUCH:
2143 rawPressureAxis = mRawAxes.touchMajor;
2144 break;
2145 default:
2146 rawPressureAxis.clear();
2147 }
2148
Jeff Brown8d608662010-08-30 03:02:23 -07002149 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2150 || mCalibration.pressureCalibration
2151 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2152 if (mCalibration.havePressureScale) {
2153 mLocked.pressureScale = mCalibration.pressureScale;
2154 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
2155 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
2156 }
2157 }
2158
2159 mLocked.orientedRanges.havePressure = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002160
2161 mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2162 mLocked.orientedRanges.pressure.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002163 mLocked.orientedRanges.pressure.min = 0;
2164 mLocked.orientedRanges.pressure.max = 1.0;
2165 mLocked.orientedRanges.pressure.flat = 0;
2166 mLocked.orientedRanges.pressure.fuzz = 0;
2167 }
2168
2169 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002170 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002171 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002172 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
2173 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2174 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
2175 }
2176 }
2177
2178 mLocked.orientedRanges.haveSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002179
2180 mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
2181 mLocked.orientedRanges.size.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002182 mLocked.orientedRanges.size.min = 0;
2183 mLocked.orientedRanges.size.max = 1.0;
2184 mLocked.orientedRanges.size.flat = 0;
2185 mLocked.orientedRanges.size.fuzz = 0;
2186 }
2187
2188 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07002189 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002190 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002191 if (mCalibration.orientationCalibration
2192 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
2193 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
2194 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
2195 }
2196 }
2197
Jeff Brownb416e242011-05-24 15:17:57 -07002198 mLocked.orientedRanges.haveOrientation = true;
2199
Jeff Brownefd32662011-03-08 15:13:06 -08002200 mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2201 mLocked.orientedRanges.orientation.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002202 mLocked.orientedRanges.orientation.min = - M_PI_2;
2203 mLocked.orientedRanges.orientation.max = M_PI_2;
2204 mLocked.orientedRanges.orientation.flat = 0;
2205 mLocked.orientedRanges.orientation.fuzz = 0;
2206 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002207 }
2208
2209 if (orientationChanged || sizeChanged) {
Jeff Brown9626b142011-03-03 02:09:54 -08002210 // Compute oriented surface dimensions, precision, scales and ranges.
2211 // Note that the maximum value reported is an inclusive maximum value so it is one
2212 // unit less than the total width or height of surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002213 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002214 case DISPLAY_ORIENTATION_90:
2215 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07002216 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
2217 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
Jeff Brown9626b142011-03-03 02:09:54 -08002218
Jeff Brown6328cdc2010-07-29 18:18:33 -07002219 mLocked.orientedXPrecision = mLocked.yPrecision;
2220 mLocked.orientedYPrecision = mLocked.xPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002221
2222 mLocked.orientedRanges.x.min = 0;
2223 mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2224 * mLocked.yScale;
2225 mLocked.orientedRanges.x.flat = 0;
2226 mLocked.orientedRanges.x.fuzz = mLocked.yScale;
2227
2228 mLocked.orientedRanges.y.min = 0;
2229 mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2230 * mLocked.xScale;
2231 mLocked.orientedRanges.y.flat = 0;
2232 mLocked.orientedRanges.y.fuzz = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002233 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002234
Jeff Brown6d0fec22010-07-23 21:28:06 -07002235 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07002236 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
2237 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
Jeff Brown9626b142011-03-03 02:09:54 -08002238
Jeff Brown6328cdc2010-07-29 18:18:33 -07002239 mLocked.orientedXPrecision = mLocked.xPrecision;
2240 mLocked.orientedYPrecision = mLocked.yPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002241
2242 mLocked.orientedRanges.x.min = 0;
2243 mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2244 * mLocked.xScale;
2245 mLocked.orientedRanges.x.flat = 0;
2246 mLocked.orientedRanges.x.fuzz = mLocked.xScale;
2247
2248 mLocked.orientedRanges.y.min = 0;
2249 mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2250 * mLocked.yScale;
2251 mLocked.orientedRanges.y.flat = 0;
2252 mLocked.orientedRanges.y.fuzz = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002253 break;
2254 }
Jeff Brown96ad3972011-03-09 17:39:48 -08002255
2256 // Compute pointer gesture detection parameters.
2257 // TODO: These factors should not be hardcoded.
2258 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2259 int32_t rawWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2260 int32_t rawHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown86ea1f52011-04-12 22:39:53 -07002261 float rawDiagonal = hypotf(rawWidth, rawHeight);
2262 float displayDiagonal = hypotf(mLocked.associatedDisplayWidth,
2263 mLocked.associatedDisplayHeight);
Jeff Brown96ad3972011-03-09 17:39:48 -08002264
Jeff Brown86ea1f52011-04-12 22:39:53 -07002265 // Scale movements such that one whole swipe of the touch pad covers a
Jeff Brown19c97d462011-06-01 12:33:19 -07002266 // given area relative to the diagonal size of the display when no acceleration
2267 // is applied.
Jeff Brown96ad3972011-03-09 17:39:48 -08002268 // Assume that the touch pad has a square aspect ratio such that movements in
2269 // X and Y of the same number of raw units cover the same physical distance.
Jeff Brown214eaf42011-05-26 19:17:02 -07002270 mLocked.pointerGestureXMovementScale = mConfig->pointerGestureMovementSpeedRatio
Jeff Brown86ea1f52011-04-12 22:39:53 -07002271 * displayDiagonal / rawDiagonal;
Jeff Brown96ad3972011-03-09 17:39:48 -08002272 mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
2273
2274 // Scale zooms to cover a smaller range of the display than movements do.
2275 // This value determines the area around the pointer that is affected by freeform
2276 // pointer gestures.
Jeff Brown214eaf42011-05-26 19:17:02 -07002277 mLocked.pointerGestureXZoomScale = mConfig->pointerGestureZoomSpeedRatio
Jeff Brown86ea1f52011-04-12 22:39:53 -07002278 * displayDiagonal / rawDiagonal;
2279 mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
Jeff Brown96ad3972011-03-09 17:39:48 -08002280
Jeff Brown86ea1f52011-04-12 22:39:53 -07002281 // Max width between pointers to detect a swipe gesture is more than some fraction
2282 // of the diagonal axis of the touch pad. Touches that are wider than this are
2283 // translated into freeform gestures.
Jeff Brown214eaf42011-05-26 19:17:02 -07002284 mLocked.pointerGestureMaxSwipeWidth =
2285 mConfig->pointerGestureSwipeMaxWidthRatio * rawDiagonal;
Jeff Brown86ea1f52011-04-12 22:39:53 -07002286
2287 // Reset the current pointer gesture.
2288 mPointerGesture.reset();
2289
2290 // Remove any current spots.
2291 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2292 mPointerController->clearSpots();
2293 }
Jeff Brown96ad3972011-03-09 17:39:48 -08002294 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002295 }
2296
2297 return true;
2298}
2299
Jeff Brownef3d7e82010-09-30 14:33:04 -07002300void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
2301 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
2302 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
2303 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07002304}
2305
Jeff Brown6328cdc2010-07-29 18:18:33 -07002306void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07002307 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08002308 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002309
Jeff Brown6328cdc2010-07-29 18:18:33 -07002310 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002311
Jeff Brown6328cdc2010-07-29 18:18:33 -07002312 if (virtualKeyDefinitions.size() == 0) {
2313 return;
2314 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002315
Jeff Brown6328cdc2010-07-29 18:18:33 -07002316 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
2317
Jeff Brown8d608662010-08-30 03:02:23 -07002318 int32_t touchScreenLeft = mRawAxes.x.minValue;
2319 int32_t touchScreenTop = mRawAxes.y.minValue;
Jeff Brown9626b142011-03-03 02:09:54 -08002320 int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2321 int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002322
2323 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07002324 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07002325 virtualKeyDefinitions[i];
2326
2327 mLocked.virtualKeys.add();
2328 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
2329
2330 virtualKey.scanCode = virtualKeyDefinition.scanCode;
2331 int32_t keyCode;
2332 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08002333 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002334 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002335 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
2336 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002337 mLocked.virtualKeys.pop(); // drop the key
2338 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002339 }
2340
Jeff Brown6328cdc2010-07-29 18:18:33 -07002341 virtualKey.keyCode = keyCode;
2342 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002343
Jeff Brown6328cdc2010-07-29 18:18:33 -07002344 // convert the key definition's display coordinates into touch coordinates for a hit box
2345 int32_t halfWidth = virtualKeyDefinition.width / 2;
2346 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002347
Jeff Brown6328cdc2010-07-29 18:18:33 -07002348 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
2349 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2350 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
2351 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2352 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
2353 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2354 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
2355 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brownef3d7e82010-09-30 14:33:04 -07002356 }
2357}
2358
2359void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
2360 if (!mLocked.virtualKeys.isEmpty()) {
2361 dump.append(INDENT3 "Virtual Keys:\n");
2362
2363 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
2364 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
2365 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
2366 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
2367 i, virtualKey.scanCode, virtualKey.keyCode,
2368 virtualKey.hitLeft, virtualKey.hitRight,
2369 virtualKey.hitTop, virtualKey.hitBottom);
2370 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002371 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002372}
2373
Jeff Brown8d608662010-08-30 03:02:23 -07002374void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002375 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07002376 Calibration& out = mCalibration;
2377
Jeff Brownc6d282b2010-10-14 21:42:15 -07002378 // Touch Size
2379 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2380 String8 touchSizeCalibrationString;
2381 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2382 if (touchSizeCalibrationString == "none") {
2383 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2384 } else if (touchSizeCalibrationString == "geometric") {
2385 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2386 } else if (touchSizeCalibrationString == "pressure") {
2387 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2388 } else if (touchSizeCalibrationString != "default") {
2389 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2390 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002391 }
2392 }
2393
Jeff Brownc6d282b2010-10-14 21:42:15 -07002394 // Tool Size
2395 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2396 String8 toolSizeCalibrationString;
2397 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2398 if (toolSizeCalibrationString == "none") {
2399 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2400 } else if (toolSizeCalibrationString == "geometric") {
2401 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2402 } else if (toolSizeCalibrationString == "linear") {
2403 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2404 } else if (toolSizeCalibrationString == "area") {
2405 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2406 } else if (toolSizeCalibrationString != "default") {
2407 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2408 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002409 }
2410 }
2411
Jeff Brownc6d282b2010-10-14 21:42:15 -07002412 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2413 out.toolSizeLinearScale);
2414 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2415 out.toolSizeLinearBias);
2416 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2417 out.toolSizeAreaScale);
2418 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2419 out.toolSizeAreaBias);
2420 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2421 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07002422
2423 // Pressure
2424 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2425 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002426 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002427 if (pressureCalibrationString == "none") {
2428 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2429 } else if (pressureCalibrationString == "physical") {
2430 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2431 } else if (pressureCalibrationString == "amplitude") {
2432 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2433 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002434 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002435 pressureCalibrationString.string());
2436 }
2437 }
2438
2439 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2440 String8 pressureSourceString;
2441 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2442 if (pressureSourceString == "pressure") {
2443 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2444 } else if (pressureSourceString == "touch") {
2445 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2446 } else if (pressureSourceString != "default") {
2447 LOGW("Invalid value for touch.pressure.source: '%s'",
2448 pressureSourceString.string());
2449 }
2450 }
2451
2452 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2453 out.pressureScale);
2454
2455 // Size
2456 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2457 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002458 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002459 if (sizeCalibrationString == "none") {
2460 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2461 } else if (sizeCalibrationString == "normalized") {
2462 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2463 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002464 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002465 sizeCalibrationString.string());
2466 }
2467 }
2468
2469 // Orientation
2470 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2471 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002472 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002473 if (orientationCalibrationString == "none") {
2474 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2475 } else if (orientationCalibrationString == "interpolated") {
2476 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002477 } else if (orientationCalibrationString == "vector") {
2478 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002479 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002480 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002481 orientationCalibrationString.string());
2482 }
2483 }
2484}
2485
2486void TouchInputMapper::resolveCalibration() {
2487 // Pressure
2488 switch (mCalibration.pressureSource) {
2489 case Calibration::PRESSURE_SOURCE_DEFAULT:
2490 if (mRawAxes.pressure.valid) {
2491 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2492 } else if (mRawAxes.touchMajor.valid) {
2493 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2494 }
2495 break;
2496
2497 case Calibration::PRESSURE_SOURCE_PRESSURE:
2498 if (! mRawAxes.pressure.valid) {
2499 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2500 "the pressure axis is not available.");
2501 }
2502 break;
2503
2504 case Calibration::PRESSURE_SOURCE_TOUCH:
2505 if (! mRawAxes.touchMajor.valid) {
2506 LOGW("Calibration property touch.pressure.source is 'touch' but "
2507 "the touchMajor axis is not available.");
2508 }
2509 break;
2510
2511 default:
2512 break;
2513 }
2514
2515 switch (mCalibration.pressureCalibration) {
2516 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2517 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2518 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2519 } else {
2520 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2521 }
2522 break;
2523
2524 default:
2525 break;
2526 }
2527
Jeff Brownc6d282b2010-10-14 21:42:15 -07002528 // Tool Size
2529 switch (mCalibration.toolSizeCalibration) {
2530 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002531 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002532 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002533 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002534 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002535 }
2536 break;
2537
2538 default:
2539 break;
2540 }
2541
Jeff Brownc6d282b2010-10-14 21:42:15 -07002542 // Touch Size
2543 switch (mCalibration.touchSizeCalibration) {
2544 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002545 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002546 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2547 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002548 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002549 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002550 }
2551 break;
2552
2553 default:
2554 break;
2555 }
2556
2557 // Size
2558 switch (mCalibration.sizeCalibration) {
2559 case Calibration::SIZE_CALIBRATION_DEFAULT:
2560 if (mRawAxes.toolMajor.valid) {
2561 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2562 } else {
2563 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2564 }
2565 break;
2566
2567 default:
2568 break;
2569 }
2570
2571 // Orientation
2572 switch (mCalibration.orientationCalibration) {
2573 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2574 if (mRawAxes.orientation.valid) {
2575 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2576 } else {
2577 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2578 }
2579 break;
2580
2581 default:
2582 break;
2583 }
2584}
2585
Jeff Brownef3d7e82010-09-30 14:33:04 -07002586void TouchInputMapper::dumpCalibration(String8& dump) {
2587 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002588
Jeff Brownc6d282b2010-10-14 21:42:15 -07002589 // Touch Size
2590 switch (mCalibration.touchSizeCalibration) {
2591 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2592 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002593 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002594 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2595 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002596 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002597 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2598 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002599 break;
2600 default:
2601 assert(false);
2602 }
2603
Jeff Brownc6d282b2010-10-14 21:42:15 -07002604 // Tool Size
2605 switch (mCalibration.toolSizeCalibration) {
2606 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2607 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002608 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002609 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2610 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002611 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002612 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2613 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2614 break;
2615 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2616 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002617 break;
2618 default:
2619 assert(false);
2620 }
2621
Jeff Brownc6d282b2010-10-14 21:42:15 -07002622 if (mCalibration.haveToolSizeLinearScale) {
2623 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2624 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002625 }
2626
Jeff Brownc6d282b2010-10-14 21:42:15 -07002627 if (mCalibration.haveToolSizeLinearBias) {
2628 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2629 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002630 }
2631
Jeff Brownc6d282b2010-10-14 21:42:15 -07002632 if (mCalibration.haveToolSizeAreaScale) {
2633 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2634 mCalibration.toolSizeAreaScale);
2635 }
2636
2637 if (mCalibration.haveToolSizeAreaBias) {
2638 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2639 mCalibration.toolSizeAreaBias);
2640 }
2641
2642 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002643 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002644 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002645 }
2646
2647 // Pressure
2648 switch (mCalibration.pressureCalibration) {
2649 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002650 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002651 break;
2652 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002653 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002654 break;
2655 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002656 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002657 break;
2658 default:
2659 assert(false);
2660 }
2661
2662 switch (mCalibration.pressureSource) {
2663 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002664 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002665 break;
2666 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002667 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002668 break;
2669 case Calibration::PRESSURE_SOURCE_DEFAULT:
2670 break;
2671 default:
2672 assert(false);
2673 }
2674
2675 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002676 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2677 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002678 }
2679
2680 // Size
2681 switch (mCalibration.sizeCalibration) {
2682 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002683 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002684 break;
2685 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002686 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002687 break;
2688 default:
2689 assert(false);
2690 }
2691
2692 // Orientation
2693 switch (mCalibration.orientationCalibration) {
2694 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002695 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002696 break;
2697 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002698 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002699 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002700 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2701 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2702 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002703 default:
2704 assert(false);
2705 }
2706}
2707
Jeff Brown6d0fec22010-07-23 21:28:06 -07002708void TouchInputMapper::reset() {
2709 // Synthesize touch up event if touch is currently down.
2710 // This will also take care of finishing virtual key processing if needed.
2711 if (mLastTouch.pointerCount != 0) {
2712 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2713 mCurrentTouch.clear();
2714 syncTouch(when, true);
2715 }
2716
Jeff Brown6328cdc2010-07-29 18:18:33 -07002717 { // acquire lock
2718 AutoMutex _l(mLock);
2719 initializeLocked();
Jeff Brown86ea1f52011-04-12 22:39:53 -07002720
2721 if (mPointerController != NULL
2722 && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2723 mPointerController->clearSpots();
2724 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002725 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002726
Jeff Brown6328cdc2010-07-29 18:18:33 -07002727 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002728}
2729
2730void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown68d60752011-03-17 01:34:19 -07002731#if DEBUG_RAW_EVENTS
2732 if (!havePointerIds) {
2733 LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount);
2734 } else {
2735 LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, "
2736 "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount,
2737 mLastTouch.idBits.value & ~mCurrentTouch.idBits.value,
2738 mCurrentTouch.idBits.value & ~mLastTouch.idBits.value,
2739 mLastTouch.idBits.value & mCurrentTouch.idBits.value,
2740 mLastTouch.idBits.value, mCurrentTouch.idBits.value);
2741 }
2742#endif
2743
Jeff Brown6328cdc2010-07-29 18:18:33 -07002744 // Preprocess pointer data.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002745 if (mParameters.useBadTouchFilter) {
2746 if (applyBadTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002747 havePointerIds = false;
2748 }
2749 }
2750
Jeff Brown6d0fec22010-07-23 21:28:06 -07002751 if (mParameters.useJumpyTouchFilter) {
2752 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002753 havePointerIds = false;
2754 }
2755 }
2756
Jeff Brown68d60752011-03-17 01:34:19 -07002757 if (!havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002758 calculatePointerIds();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002759 }
2760
Jeff Brown6d0fec22010-07-23 21:28:06 -07002761 TouchData temp;
2762 TouchData* savedTouch;
2763 if (mParameters.useAveragingTouchFilter) {
2764 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002765 savedTouch = & temp;
2766
Jeff Brown6d0fec22010-07-23 21:28:06 -07002767 applyAveragingTouchFilter();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002768 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002769 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002770 }
2771
Jeff Brown56194eb2011-03-02 19:23:13 -08002772 uint32_t policyFlags = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -08002773 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brownefd32662011-03-08 15:13:06 -08002774 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2775 // If this is a touch screen, hide the pointer on an initial down.
2776 getContext()->fadePointer();
2777 }
Jeff Brown56194eb2011-03-02 19:23:13 -08002778
2779 // Initial downs on external touch devices should wake the device.
2780 // We don't do this for internal touch screens to prevent them from waking
2781 // up in your pocket.
2782 // TODO: Use the input device configuration to control this behavior more finely.
2783 if (getDevice()->isExternal()) {
2784 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2785 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002786 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002787
Jeff Brown325bd072011-04-19 21:20:10 -07002788 TouchResult touchResult;
2789 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
2790 && mLastTouch.buttonState == mCurrentTouch.buttonState) {
2791 // Drop spurious syncs.
2792 touchResult = DROP_STROKE;
2793 } else {
2794 // Process touches and virtual keys.
2795 touchResult = consumeOffScreenTouches(when, policyFlags);
2796 if (touchResult == DISPATCH_TOUCH) {
2797 suppressSwipeOntoVirtualKeys(when);
2798 if (mPointerController != NULL) {
2799 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
2800 }
2801 dispatchTouches(when, policyFlags);
Jeff Brown96ad3972011-03-09 17:39:48 -08002802 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002803 }
2804
Jeff Brown6328cdc2010-07-29 18:18:33 -07002805 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown96ad3972011-03-09 17:39:48 -08002806 // Keep the button state so we can track edge-triggered button state changes.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002807 if (touchResult == DROP_STROKE) {
2808 mLastTouch.clear();
Jeff Brown96ad3972011-03-09 17:39:48 -08002809 mLastTouch.buttonState = savedTouch->buttonState;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002810 } else {
2811 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002812 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07002813}
2814
Jeff Brown325bd072011-04-19 21:20:10 -07002815void TouchInputMapper::timeoutExpired(nsecs_t when) {
2816 if (mPointerController != NULL) {
2817 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
2818 }
2819}
2820
Jeff Brown6d0fec22010-07-23 21:28:06 -07002821TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2822 nsecs_t when, uint32_t policyFlags) {
2823 int32_t keyEventAction, keyEventFlags;
2824 int32_t keyCode, scanCode, downTime;
2825 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002826
Jeff Brown6328cdc2010-07-29 18:18:33 -07002827 { // acquire lock
2828 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002829
Jeff Brown6328cdc2010-07-29 18:18:33 -07002830 // Update surface size and orientation, including virtual key positions.
2831 if (! configureSurfaceLocked()) {
2832 return DROP_STROKE;
2833 }
2834
2835 // Check for virtual key press.
2836 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002837 if (mCurrentTouch.pointerCount == 0) {
2838 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002839 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002840#if DEBUG_VIRTUAL_KEYS
2841 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002842 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002843#endif
2844 keyEventAction = AKEY_EVENT_ACTION_UP;
2845 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2846 touchResult = SKIP_TOUCH;
2847 goto DispatchVirtualKey;
2848 }
2849
2850 if (mCurrentTouch.pointerCount == 1) {
2851 int32_t x = mCurrentTouch.pointers[0].x;
2852 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002853 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2854 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002855 // Pointer is still within the space of the virtual key.
2856 return SKIP_TOUCH;
2857 }
2858 }
2859
2860 // Pointer left virtual key area or another pointer also went down.
2861 // Send key cancellation and drop the stroke so subsequent motions will be
2862 // considered fresh downs. This is useful when the user swipes away from the
2863 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002864 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002865#if DEBUG_VIRTUAL_KEYS
2866 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002867 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002868#endif
2869 keyEventAction = AKEY_EVENT_ACTION_UP;
2870 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2871 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002872
2873 // Check whether the pointer moved inside the display area where we should
2874 // start a new stroke.
2875 int32_t x = mCurrentTouch.pointers[0].x;
2876 int32_t y = mCurrentTouch.pointers[0].y;
2877 if (isPointInsideSurfaceLocked(x, y)) {
2878 mLastTouch.clear();
2879 touchResult = DISPATCH_TOUCH;
2880 } else {
2881 touchResult = DROP_STROKE;
2882 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002883 } else {
2884 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2885 // Pointer just went down. Handle off-screen touches, if needed.
2886 int32_t x = mCurrentTouch.pointers[0].x;
2887 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002888 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002889 // If exactly one pointer went down, check for virtual key hit.
2890 // Otherwise we will drop the entire stroke.
2891 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002892 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002893 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002894 if (mContext->shouldDropVirtualKey(when, getDevice(),
2895 virtualKey->keyCode, virtualKey->scanCode)) {
2896 return DROP_STROKE;
2897 }
2898
Jeff Brown6328cdc2010-07-29 18:18:33 -07002899 mLocked.currentVirtualKey.down = true;
2900 mLocked.currentVirtualKey.downTime = when;
2901 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2902 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002903#if DEBUG_VIRTUAL_KEYS
2904 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002905 mLocked.currentVirtualKey.keyCode,
2906 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002907#endif
2908 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2909 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2910 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2911 touchResult = SKIP_TOUCH;
2912 goto DispatchVirtualKey;
2913 }
2914 }
2915 return DROP_STROKE;
2916 }
2917 }
2918 return DISPATCH_TOUCH;
2919 }
2920
2921 DispatchVirtualKey:
2922 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002923 keyCode = mLocked.currentVirtualKey.keyCode;
2924 scanCode = mLocked.currentVirtualKey.scanCode;
2925 downTime = mLocked.currentVirtualKey.downTime;
2926 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002927
2928 // Dispatch virtual key.
2929 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002930 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002931 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2932 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2933 return touchResult;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002934}
2935
Jeff Brownefd32662011-03-08 15:13:06 -08002936void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
Jeff Brownfe508922011-01-18 15:10:10 -08002937 // Disable all virtual key touches that happen within a short time interval of the
2938 // most recent touch. The idea is to filter out stray virtual key presses when
2939 // interacting with the touch screen.
2940 //
2941 // Problems we're trying to solve:
2942 //
2943 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2944 // virtual key area that is implemented by a separate touch panel and accidentally
2945 // triggers a virtual key.
2946 //
2947 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2948 // area and accidentally triggers a virtual key. This often happens when virtual keys
2949 // are layed out below the screen near to where the on screen keyboard's space bar
2950 // is displayed.
Jeff Brown214eaf42011-05-26 19:17:02 -07002951 if (mConfig->virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2952 mContext->disableVirtualKeysUntil(when + mConfig->virtualKeyQuietTime);
Jeff Brownfe508922011-01-18 15:10:10 -08002953 }
2954}
2955
Jeff Brown6d0fec22010-07-23 21:28:06 -07002956void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2957 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2958 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07002959 if (currentPointerCount == 0 && lastPointerCount == 0) {
2960 return; // nothing to do!
2961 }
2962
Jeff Brown96ad3972011-03-09 17:39:48 -08002963 // Update current touch coordinates.
2964 int32_t edgeFlags;
2965 float xPrecision, yPrecision;
2966 prepareTouches(&edgeFlags, &xPrecision, &yPrecision);
2967
2968 // Dispatch motions.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002969 BitSet32 currentIdBits = mCurrentTouch.idBits;
2970 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown96ad3972011-03-09 17:39:48 -08002971 uint32_t metaState = getContext()->getGlobalMetaState();
Jeff Brown46b9ac02010-04-22 18:58:52 -07002972
2973 if (currentIdBits == lastIdBits) {
2974 // No pointer id changes so this is a move event.
2975 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown96ad3972011-03-09 17:39:48 -08002976 dispatchMotion(when, policyFlags, mTouchSource,
2977 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
2978 mCurrentTouchCoords, mCurrentTouch.idToIndex, currentIdBits, -1,
2979 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002980 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002981 // There may be pointers going up and pointers going down and pointers moving
2982 // all at the same time.
Jeff Brown96ad3972011-03-09 17:39:48 -08002983 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
2984 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07002985 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
Jeff Brown96ad3972011-03-09 17:39:48 -08002986 BitSet32 dispatchedIdBits(lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07002987
Jeff Brown96ad3972011-03-09 17:39:48 -08002988 // Update last coordinates of pointers that have moved so that we observe the new
2989 // pointer positions at the same time as other pointers that have just gone up.
2990 bool moveNeeded = updateMovedPointerCoords(
2991 mCurrentTouchCoords, mCurrentTouch.idToIndex,
2992 mLastTouchCoords, mLastTouch.idToIndex,
2993 moveIdBits);
Jeff Brownc3db8582010-10-20 15:33:38 -07002994
Jeff Brown96ad3972011-03-09 17:39:48 -08002995 // Dispatch pointer up events.
Jeff Brownc3db8582010-10-20 15:33:38 -07002996 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07002997 uint32_t upId = upIdBits.firstMarkedBit();
2998 upIdBits.clearBit(upId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002999
Jeff Brown96ad3972011-03-09 17:39:48 -08003000 dispatchMotion(when, policyFlags, mTouchSource,
3001 AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, 0,
3002 mLastTouchCoords, mLastTouch.idToIndex, dispatchedIdBits, upId,
3003 xPrecision, yPrecision, mDownTime);
3004 dispatchedIdBits.clearBit(upId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003005 }
3006
Jeff Brownc3db8582010-10-20 15:33:38 -07003007 // Dispatch move events if any of the remaining pointers moved from their old locations.
3008 // Although applications receive new locations as part of individual pointer up
3009 // events, they do not generally handle them except when presented in a move event.
3010 if (moveNeeded) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003011 assert(moveIdBits.value == dispatchedIdBits.value);
3012 dispatchMotion(when, policyFlags, mTouchSource,
3013 AMOTION_EVENT_ACTION_MOVE, 0, metaState, 0,
3014 mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, -1,
3015 xPrecision, yPrecision, mDownTime);
Jeff Brownc3db8582010-10-20 15:33:38 -07003016 }
3017
3018 // Dispatch pointer down events using the new pointer locations.
3019 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07003020 uint32_t downId = downIdBits.firstMarkedBit();
3021 downIdBits.clearBit(downId);
Jeff Brown96ad3972011-03-09 17:39:48 -08003022 dispatchedIdBits.markBit(downId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07003023
Jeff Brown96ad3972011-03-09 17:39:48 -08003024 if (dispatchedIdBits.count() == 1) {
3025 // First pointer is going down. Set down time.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003026 mDownTime = when;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003027 } else {
Jeff Brown96ad3972011-03-09 17:39:48 -08003028 // Only send edge flags with first pointer down.
3029 edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003030 }
3031
Jeff Brown96ad3972011-03-09 17:39:48 -08003032 dispatchMotion(when, policyFlags, mTouchSource,
3033 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
3034 mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, downId,
3035 xPrecision, yPrecision, mDownTime);
3036 }
3037 }
3038
3039 // Update state for next time.
3040 for (uint32_t i = 0; i < currentPointerCount; i++) {
3041 mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]);
3042 }
3043}
3044
3045void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
3046 float* outXPrecision, float* outYPrecision) {
3047 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3048 uint32_t lastPointerCount = mLastTouch.pointerCount;
3049
3050 AutoMutex _l(mLock);
3051
3052 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
3053 // display or surface coordinates (PointerCoords) and adjust for display orientation.
3054 for (uint32_t i = 0; i < currentPointerCount; i++) {
3055 const PointerData& in = mCurrentTouch.pointers[i];
3056
3057 // ToolMajor and ToolMinor
3058 float toolMajor, toolMinor;
3059 switch (mCalibration.toolSizeCalibration) {
3060 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
3061 toolMajor = in.toolMajor * mLocked.geometricScale;
3062 if (mRawAxes.toolMinor.valid) {
3063 toolMinor = in.toolMinor * mLocked.geometricScale;
3064 } else {
3065 toolMinor = toolMajor;
3066 }
3067 break;
3068 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
3069 toolMajor = in.toolMajor != 0
3070 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
3071 : 0;
3072 if (mRawAxes.toolMinor.valid) {
3073 toolMinor = in.toolMinor != 0
3074 ? in.toolMinor * mLocked.toolSizeLinearScale
3075 + mLocked.toolSizeLinearBias
3076 : 0;
3077 } else {
3078 toolMinor = toolMajor;
3079 }
3080 break;
3081 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
3082 if (in.toolMajor != 0) {
3083 float diameter = sqrtf(in.toolMajor
3084 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
3085 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
3086 } else {
3087 toolMajor = 0;
3088 }
3089 toolMinor = toolMajor;
3090 break;
3091 default:
3092 toolMajor = 0;
3093 toolMinor = 0;
3094 break;
3095 }
3096
3097 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
3098 toolMajor /= currentPointerCount;
3099 toolMinor /= currentPointerCount;
3100 }
3101
3102 // Pressure
3103 float rawPressure;
3104 switch (mCalibration.pressureSource) {
3105 case Calibration::PRESSURE_SOURCE_PRESSURE:
3106 rawPressure = in.pressure;
3107 break;
3108 case Calibration::PRESSURE_SOURCE_TOUCH:
3109 rawPressure = in.touchMajor;
3110 break;
3111 default:
3112 rawPressure = 0;
3113 }
3114
3115 float pressure;
3116 switch (mCalibration.pressureCalibration) {
3117 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3118 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3119 pressure = rawPressure * mLocked.pressureScale;
3120 break;
3121 default:
3122 pressure = 1;
3123 break;
3124 }
3125
3126 // TouchMajor and TouchMinor
3127 float touchMajor, touchMinor;
3128 switch (mCalibration.touchSizeCalibration) {
3129 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
3130 touchMajor = in.touchMajor * mLocked.geometricScale;
3131 if (mRawAxes.touchMinor.valid) {
3132 touchMinor = in.touchMinor * mLocked.geometricScale;
3133 } else {
3134 touchMinor = touchMajor;
3135 }
3136 break;
3137 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
3138 touchMajor = toolMajor * pressure;
3139 touchMinor = toolMinor * pressure;
3140 break;
3141 default:
3142 touchMajor = 0;
3143 touchMinor = 0;
3144 break;
3145 }
3146
3147 if (touchMajor > toolMajor) {
3148 touchMajor = toolMajor;
3149 }
3150 if (touchMinor > toolMinor) {
3151 touchMinor = toolMinor;
3152 }
3153
3154 // Size
3155 float size;
3156 switch (mCalibration.sizeCalibration) {
3157 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
3158 float rawSize = mRawAxes.toolMinor.valid
3159 ? avg(in.toolMajor, in.toolMinor)
3160 : in.toolMajor;
3161 size = rawSize * mLocked.sizeScale;
3162 break;
3163 }
3164 default:
3165 size = 0;
3166 break;
3167 }
3168
3169 // Orientation
3170 float orientation;
3171 switch (mCalibration.orientationCalibration) {
3172 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3173 orientation = in.orientation * mLocked.orientationScale;
3174 break;
3175 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3176 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3177 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3178 if (c1 != 0 || c2 != 0) {
3179 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003180 float scale = 1.0f + hypotf(c1, c2) / 16.0f;
Jeff Brown96ad3972011-03-09 17:39:48 -08003181 touchMajor *= scale;
3182 touchMinor /= scale;
3183 toolMajor *= scale;
3184 toolMinor /= scale;
3185 } else {
3186 orientation = 0;
3187 }
3188 break;
3189 }
3190 default:
3191 orientation = 0;
3192 }
3193
3194 // X and Y
3195 // Adjust coords for surface orientation.
3196 float x, y;
3197 switch (mLocked.surfaceOrientation) {
3198 case DISPLAY_ORIENTATION_90:
3199 x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3200 y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3201 orientation -= M_PI_2;
3202 if (orientation < - M_PI_2) {
3203 orientation += M_PI;
3204 }
3205 break;
3206 case DISPLAY_ORIENTATION_180:
3207 x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3208 y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3209 break;
3210 case DISPLAY_ORIENTATION_270:
3211 x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3212 y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3213 orientation += M_PI_2;
3214 if (orientation > M_PI_2) {
3215 orientation -= M_PI;
3216 }
3217 break;
3218 default:
3219 x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3220 y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3221 break;
3222 }
3223
3224 // Write output coords.
3225 PointerCoords& out = mCurrentTouchCoords[i];
3226 out.clear();
3227 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3228 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3229 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3230 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3231 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3232 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3233 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3234 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3235 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
3236 }
3237
3238 // Check edge flags by looking only at the first pointer since the flags are
3239 // global to the event.
3240 *outEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3241 if (lastPointerCount == 0 && currentPointerCount > 0) {
3242 const PointerData& in = mCurrentTouch.pointers[0];
3243
3244 if (in.x <= mRawAxes.x.minValue) {
3245 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
3246 mLocked.surfaceOrientation);
3247 } else if (in.x >= mRawAxes.x.maxValue) {
3248 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
3249 mLocked.surfaceOrientation);
3250 }
3251 if (in.y <= mRawAxes.y.minValue) {
3252 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
3253 mLocked.surfaceOrientation);
3254 } else if (in.y >= mRawAxes.y.maxValue) {
3255 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
3256 mLocked.surfaceOrientation);
3257 }
3258 }
3259
3260 *outXPrecision = mLocked.orientedXPrecision;
3261 *outYPrecision = mLocked.orientedYPrecision;
3262}
3263
Jeff Brown325bd072011-04-19 21:20:10 -07003264void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3265 bool isTimeout) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003266 // Update current gesture coordinates.
3267 bool cancelPreviousGesture, finishPreviousGesture;
Jeff Brown325bd072011-04-19 21:20:10 -07003268 bool sendEvents = preparePointerGestures(when,
3269 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3270 if (!sendEvents) {
3271 return;
3272 }
Jeff Brown19c97d462011-06-01 12:33:19 -07003273 if (finishPreviousGesture) {
3274 cancelPreviousGesture = false;
3275 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003276
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003277 // Update the pointer presentation and spots.
3278 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3279 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3280 if (finishPreviousGesture || cancelPreviousGesture) {
3281 mPointerController->clearSpots();
3282 }
Jeff Browncb5ffcf2011-06-06 20:03:18 -07003283 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
3284 mPointerGesture.currentGestureIdToIndex,
3285 mPointerGesture.currentGestureIdBits);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003286 } else {
3287 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
3288 }
Jeff Brown214eaf42011-05-26 19:17:02 -07003289
Jeff Brown538881e2011-05-25 18:23:38 -07003290 // Show or hide the pointer if needed.
3291 switch (mPointerGesture.currentGestureMode) {
3292 case PointerGesture::NEUTRAL:
3293 case PointerGesture::QUIET:
3294 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3295 && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3296 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
3297 // Remind the user of where the pointer is after finishing a gesture with spots.
3298 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
3299 }
3300 break;
3301 case PointerGesture::TAP:
3302 case PointerGesture::TAP_DRAG:
3303 case PointerGesture::BUTTON_CLICK_OR_DRAG:
3304 case PointerGesture::HOVER:
3305 case PointerGesture::PRESS:
3306 // Unfade the pointer when the current gesture manipulates the
3307 // area directly under the pointer.
3308 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3309 break;
3310 case PointerGesture::SWIPE:
3311 case PointerGesture::FREEFORM:
3312 // Fade the pointer when the current gesture manipulates a different
3313 // area and there are spots to guide the user experience.
3314 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3315 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3316 } else {
3317 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3318 }
3319 break;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003320 }
3321
Jeff Brown96ad3972011-03-09 17:39:48 -08003322 // Send events!
3323 uint32_t metaState = getContext()->getGlobalMetaState();
3324
3325 // Update last coordinates of pointers that have moved so that we observe the new
3326 // pointer positions at the same time as other pointers that have just gone up.
Jeff Brown325bd072011-04-19 21:20:10 -07003327 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
3328 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
3329 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown86ea1f52011-04-12 22:39:53 -07003330 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
Jeff Brown96ad3972011-03-09 17:39:48 -08003331 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
3332 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
3333 bool moveNeeded = false;
3334 if (down && !cancelPreviousGesture && !finishPreviousGesture
Jeff Brown86ea1f52011-04-12 22:39:53 -07003335 && !mPointerGesture.lastGestureIdBits.isEmpty()
3336 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003337 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
3338 & mPointerGesture.lastGestureIdBits.value);
3339 moveNeeded = updateMovedPointerCoords(
3340 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3341 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3342 movedGestureIdBits);
3343 }
3344
3345 // Send motion events for all pointers that went up or were canceled.
3346 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
3347 if (!dispatchedGestureIdBits.isEmpty()) {
3348 if (cancelPreviousGesture) {
3349 dispatchMotion(when, policyFlags, mPointerSource,
3350 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3351 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3352 dispatchedGestureIdBits, -1,
3353 0, 0, mPointerGesture.downTime);
3354
3355 dispatchedGestureIdBits.clear();
3356 } else {
3357 BitSet32 upGestureIdBits;
3358 if (finishPreviousGesture) {
3359 upGestureIdBits = dispatchedGestureIdBits;
3360 } else {
3361 upGestureIdBits.value = dispatchedGestureIdBits.value
3362 & ~mPointerGesture.currentGestureIdBits.value;
3363 }
3364 while (!upGestureIdBits.isEmpty()) {
3365 uint32_t id = upGestureIdBits.firstMarkedBit();
3366 upGestureIdBits.clearBit(id);
3367
3368 dispatchMotion(when, policyFlags, mPointerSource,
3369 AMOTION_EVENT_ACTION_POINTER_UP, 0,
3370 metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3371 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3372 dispatchedGestureIdBits, id,
3373 0, 0, mPointerGesture.downTime);
3374
3375 dispatchedGestureIdBits.clearBit(id);
3376 }
3377 }
3378 }
3379
3380 // Send motion events for all pointers that moved.
3381 if (moveNeeded) {
3382 dispatchMotion(when, policyFlags, mPointerSource,
3383 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3384 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3385 dispatchedGestureIdBits, -1,
3386 0, 0, mPointerGesture.downTime);
3387 }
3388
3389 // Send motion events for all pointers that went down.
3390 if (down) {
3391 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
3392 & ~dispatchedGestureIdBits.value);
3393 while (!downGestureIdBits.isEmpty()) {
3394 uint32_t id = downGestureIdBits.firstMarkedBit();
3395 downGestureIdBits.clearBit(id);
3396 dispatchedGestureIdBits.markBit(id);
3397
3398 int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3399 if (dispatchedGestureIdBits.count() == 1) {
3400 // First pointer is going down. Calculate edge flags and set down time.
3401 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3402 const PointerCoords& downCoords = mPointerGesture.currentGestureCoords[index];
3403 edgeFlags = calculateEdgeFlagsUsingPointerBounds(mPointerController,
3404 downCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
3405 downCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
3406 mPointerGesture.downTime = when;
3407 }
3408
3409 dispatchMotion(when, policyFlags, mPointerSource,
3410 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
3411 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3412 dispatchedGestureIdBits, id,
3413 0, 0, mPointerGesture.downTime);
3414 }
3415 }
3416
Jeff Brown96ad3972011-03-09 17:39:48 -08003417 // Send motion events for hover.
3418 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
3419 dispatchMotion(when, policyFlags, mPointerSource,
3420 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3421 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3422 mPointerGesture.currentGestureIdBits, -1,
3423 0, 0, mPointerGesture.downTime);
3424 }
3425
3426 // Update state.
3427 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
3428 if (!down) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003429 mPointerGesture.lastGestureIdBits.clear();
3430 } else {
Jeff Brown96ad3972011-03-09 17:39:48 -08003431 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
3432 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
3433 uint32_t id = idBits.firstMarkedBit();
3434 idBits.clearBit(id);
3435 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3436 mPointerGesture.lastGestureCoords[index].copyFrom(
3437 mPointerGesture.currentGestureCoords[index]);
3438 mPointerGesture.lastGestureIdToIndex[id] = index;
Jeff Brown46b9ac02010-04-22 18:58:52 -07003439 }
3440 }
3441}
3442
Jeff Brown325bd072011-04-19 21:20:10 -07003443bool TouchInputMapper::preparePointerGestures(nsecs_t when,
3444 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003445 *outCancelPreviousGesture = false;
3446 *outFinishPreviousGesture = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003447
Jeff Brown96ad3972011-03-09 17:39:48 -08003448 AutoMutex _l(mLock);
Jeff Brown6328cdc2010-07-29 18:18:33 -07003449
Jeff Brown325bd072011-04-19 21:20:10 -07003450 // Handle TAP timeout.
3451 if (isTimeout) {
3452#if DEBUG_GESTURES
3453 LOGD("Gestures: Processing timeout");
3454#endif
3455
3456 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
Jeff Brown214eaf42011-05-26 19:17:02 -07003457 if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) {
Jeff Brown325bd072011-04-19 21:20:10 -07003458 // The tap/drag timeout has not yet expired.
Jeff Brown214eaf42011-05-26 19:17:02 -07003459 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
3460 + mConfig->pointerGestureTapDragInterval);
Jeff Brown325bd072011-04-19 21:20:10 -07003461 } else {
3462 // The tap is finished.
3463#if DEBUG_GESTURES
3464 LOGD("Gestures: TAP finished");
3465#endif
3466 *outFinishPreviousGesture = true;
3467
3468 mPointerGesture.activeGestureId = -1;
3469 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
3470 mPointerGesture.currentGestureIdBits.clear();
3471
Jeff Brown19c97d462011-06-01 12:33:19 -07003472 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown325bd072011-04-19 21:20:10 -07003473 return true;
3474 }
3475 }
3476
3477 // We did not handle this timeout.
3478 return false;
3479 }
3480
Jeff Brown96ad3972011-03-09 17:39:48 -08003481 // Update the velocity tracker.
3482 {
3483 VelocityTracker::Position positions[MAX_POINTERS];
3484 uint32_t count = 0;
3485 for (BitSet32 idBits(mCurrentTouch.idBits); !idBits.isEmpty(); count++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003486 uint32_t id = idBits.firstMarkedBit();
3487 idBits.clearBit(id);
Jeff Brown96ad3972011-03-09 17:39:48 -08003488 uint32_t index = mCurrentTouch.idToIndex[id];
3489 positions[count].x = mCurrentTouch.pointers[index].x
3490 * mLocked.pointerGestureXMovementScale;
3491 positions[count].y = mCurrentTouch.pointers[index].y
3492 * mLocked.pointerGestureYMovementScale;
3493 }
3494 mPointerGesture.velocityTracker.addMovement(when, mCurrentTouch.idBits, positions);
3495 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003496
Jeff Brown96ad3972011-03-09 17:39:48 -08003497 // Pick a new active touch id if needed.
3498 // Choose an arbitrary pointer that just went down, if there is one.
3499 // Otherwise choose an arbitrary remaining pointer.
3500 // This guarantees we always have an active touch id when there is at least one pointer.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003501 // We keep the same active touch id for as long as possible.
3502 bool activeTouchChanged = false;
3503 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
3504 int32_t activeTouchId = lastActiveTouchId;
3505 if (activeTouchId < 0) {
3506 if (!mCurrentTouch.idBits.isEmpty()) {
3507 activeTouchChanged = true;
3508 activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3509 mPointerGesture.firstTouchTime = when;
Jeff Brown96ad3972011-03-09 17:39:48 -08003510 }
Jeff Brown86ea1f52011-04-12 22:39:53 -07003511 } else if (!mCurrentTouch.idBits.hasBit(activeTouchId)) {
3512 activeTouchChanged = true;
3513 if (!mCurrentTouch.idBits.isEmpty()) {
3514 activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3515 } else {
3516 activeTouchId = mPointerGesture.activeTouchId = -1;
Jeff Brown96ad3972011-03-09 17:39:48 -08003517 }
3518 }
3519
3520 // Determine whether we are in quiet time.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003521 bool isQuietTime = false;
3522 if (activeTouchId < 0) {
3523 mPointerGesture.resetQuietTime();
3524 } else {
Jeff Brown214eaf42011-05-26 19:17:02 -07003525 isQuietTime = when < mPointerGesture.quietTime + mConfig->pointerGestureQuietInterval;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003526 if (!isQuietTime) {
3527 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
3528 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3529 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
3530 && mCurrentTouch.pointerCount < 2) {
3531 // Enter quiet time when exiting swipe or freeform state.
3532 // This is to prevent accidentally entering the hover state and flinging the
3533 // pointer when finishing a swipe and there is still one pointer left onscreen.
3534 isQuietTime = true;
Jeff Brown325bd072011-04-19 21:20:10 -07003535 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown86ea1f52011-04-12 22:39:53 -07003536 && mCurrentTouch.pointerCount >= 2
3537 && !isPointerDown(mCurrentTouch.buttonState)) {
3538 // Enter quiet time when releasing the button and there are still two or more
3539 // fingers down. This may indicate that one finger was used to press the button
3540 // but it has not gone up yet.
3541 isQuietTime = true;
3542 }
3543 if (isQuietTime) {
3544 mPointerGesture.quietTime = when;
3545 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003546 }
3547 }
3548
3549 // Switch states based on button and pointer state.
3550 if (isQuietTime) {
3551 // Case 1: Quiet time. (QUIET)
3552#if DEBUG_GESTURES
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003553 LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
3554 + mConfig->pointerGestureQuietInterval - when) * 0.000001f);
Jeff Brown96ad3972011-03-09 17:39:48 -08003555#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003556 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
3557 *outFinishPreviousGesture = true;
3558 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003559
3560 mPointerGesture.activeGestureId = -1;
3561 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
Jeff Brown96ad3972011-03-09 17:39:48 -08003562 mPointerGesture.currentGestureIdBits.clear();
Jeff Brown86ea1f52011-04-12 22:39:53 -07003563
Jeff Brown19c97d462011-06-01 12:33:19 -07003564 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown96ad3972011-03-09 17:39:48 -08003565 } else if (isPointerDown(mCurrentTouch.buttonState)) {
Jeff Brown325bd072011-04-19 21:20:10 -07003566 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
Jeff Brown96ad3972011-03-09 17:39:48 -08003567 // The pointer follows the active touch point.
3568 // Emit DOWN, MOVE, UP events at the pointer location.
3569 //
3570 // Only the active touch matters; other fingers are ignored. This policy helps
3571 // to handle the case where the user places a second finger on the touch pad
3572 // to apply the necessary force to depress an integrated button below the surface.
3573 // We don't want the second finger to be delivered to applications.
3574 //
3575 // For this to work well, we need to make sure to track the pointer that is really
3576 // active. If the user first puts one finger down to click then adds another
3577 // finger to drag then the active pointer should switch to the finger that is
3578 // being dragged.
3579#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003580 LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
Jeff Brown96ad3972011-03-09 17:39:48 -08003581 "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount);
3582#endif
3583 // Reset state when just starting.
Jeff Brown325bd072011-04-19 21:20:10 -07003584 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003585 *outFinishPreviousGesture = true;
3586 mPointerGesture.activeGestureId = 0;
3587 }
3588
3589 // Switch pointers if needed.
3590 // Find the fastest pointer and follow it.
Jeff Brown19c97d462011-06-01 12:33:19 -07003591 if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) {
3592 int32_t bestId = -1;
3593 float bestSpeed = mConfig->pointerGestureDragMinSwitchSpeed;
3594 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
3595 uint32_t id = mCurrentTouch.pointers[i].id;
3596 float vx, vy;
3597 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
3598 float speed = hypotf(vx, vy);
3599 if (speed > bestSpeed) {
3600 bestId = id;
3601 bestSpeed = speed;
Jeff Brown96ad3972011-03-09 17:39:48 -08003602 }
Jeff Brown8d608662010-08-30 03:02:23 -07003603 }
Jeff Brown19c97d462011-06-01 12:33:19 -07003604 }
3605 if (bestId >= 0 && bestId != activeTouchId) {
3606 mPointerGesture.activeTouchId = activeTouchId = bestId;
3607 activeTouchChanged = true;
Jeff Brown96ad3972011-03-09 17:39:48 -08003608#if DEBUG_GESTURES
Jeff Brown19c97d462011-06-01 12:33:19 -07003609 LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
3610 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
Jeff Brown96ad3972011-03-09 17:39:48 -08003611#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07003612 }
Jeff Brown19c97d462011-06-01 12:33:19 -07003613 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003614
Jeff Brown19c97d462011-06-01 12:33:19 -07003615 if (activeTouchId >= 0 && mLastTouch.idBits.hasBit(activeTouchId)) {
3616 const PointerData& currentPointer =
3617 mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3618 const PointerData& lastPointer =
3619 mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3620 float deltaX = (currentPointer.x - lastPointer.x)
3621 * mLocked.pointerGestureXMovementScale;
3622 float deltaY = (currentPointer.y - lastPointer.y)
3623 * mLocked.pointerGestureYMovementScale;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003624
Jeff Brown19c97d462011-06-01 12:33:19 -07003625 mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
3626
3627 // Move the pointer using a relative motion.
3628 // When using spots, the click will occur at the position of the anchor
3629 // spot and all other spots will move there.
3630 mPointerController->move(deltaX, deltaY);
3631 } else {
3632 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown46b9ac02010-04-22 18:58:52 -07003633 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003634
Jeff Brown96ad3972011-03-09 17:39:48 -08003635 float x, y;
3636 mPointerController->getPosition(&x, &y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08003637
Jeff Brown325bd072011-04-19 21:20:10 -07003638 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
Jeff Brown96ad3972011-03-09 17:39:48 -08003639 mPointerGesture.currentGestureIdBits.clear();
3640 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3641 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3642 mPointerGesture.currentGestureCoords[0].clear();
3643 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3644 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3645 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
3646 } else if (mCurrentTouch.pointerCount == 0) {
3647 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003648 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
3649 *outFinishPreviousGesture = true;
3650 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003651
Jeff Brown325bd072011-04-19 21:20:10 -07003652 // Watch for taps coming out of HOVER or TAP_DRAG mode.
Jeff Brown214eaf42011-05-26 19:17:02 -07003653 // Checking for taps after TAP_DRAG allows us to detect double-taps.
Jeff Brown96ad3972011-03-09 17:39:48 -08003654 bool tapped = false;
Jeff Brown325bd072011-04-19 21:20:10 -07003655 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
3656 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
Jeff Brown86ea1f52011-04-12 22:39:53 -07003657 && mLastTouch.pointerCount == 1) {
Jeff Brown214eaf42011-05-26 19:17:02 -07003658 if (when <= mPointerGesture.tapDownTime + mConfig->pointerGestureTapInterval) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003659 float x, y;
3660 mPointerController->getPosition(&x, &y);
Jeff Brown214eaf42011-05-26 19:17:02 -07003661 if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop
3662 && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003663#if DEBUG_GESTURES
3664 LOGD("Gestures: TAP");
3665#endif
Jeff Brown325bd072011-04-19 21:20:10 -07003666
3667 mPointerGesture.tapUpTime = when;
Jeff Brown214eaf42011-05-26 19:17:02 -07003668 getContext()->requestTimeoutAtTime(when
3669 + mConfig->pointerGestureTapDragInterval);
Jeff Brown325bd072011-04-19 21:20:10 -07003670
Jeff Brown96ad3972011-03-09 17:39:48 -08003671 mPointerGesture.activeGestureId = 0;
3672 mPointerGesture.currentGestureMode = PointerGesture::TAP;
Jeff Brown96ad3972011-03-09 17:39:48 -08003673 mPointerGesture.currentGestureIdBits.clear();
3674 mPointerGesture.currentGestureIdBits.markBit(
3675 mPointerGesture.activeGestureId);
3676 mPointerGesture.currentGestureIdToIndex[
3677 mPointerGesture.activeGestureId] = 0;
3678 mPointerGesture.currentGestureCoords[0].clear();
3679 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown86ea1f52011-04-12 22:39:53 -07003680 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
Jeff Brown96ad3972011-03-09 17:39:48 -08003681 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown86ea1f52011-04-12 22:39:53 -07003682 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003683 mPointerGesture.currentGestureCoords[0].setAxisValue(
3684 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003685
Jeff Brown96ad3972011-03-09 17:39:48 -08003686 tapped = true;
3687 } else {
3688#if DEBUG_GESTURES
3689 LOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
Jeff Brown86ea1f52011-04-12 22:39:53 -07003690 x - mPointerGesture.tapX,
3691 y - mPointerGesture.tapY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003692#endif
3693 }
3694 } else {
3695#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003696 LOGD("Gestures: Not a TAP, %0.3fms since down",
3697 (when - mPointerGesture.tapDownTime) * 0.000001f);
Jeff Brown96ad3972011-03-09 17:39:48 -08003698#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07003699 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003700 }
Jeff Brown86ea1f52011-04-12 22:39:53 -07003701
Jeff Brown19c97d462011-06-01 12:33:19 -07003702 mPointerGesture.pointerVelocityControl.reset();
3703
Jeff Brown96ad3972011-03-09 17:39:48 -08003704 if (!tapped) {
3705#if DEBUG_GESTURES
3706 LOGD("Gestures: NEUTRAL");
3707#endif
3708 mPointerGesture.activeGestureId = -1;
3709 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
Jeff Brown96ad3972011-03-09 17:39:48 -08003710 mPointerGesture.currentGestureIdBits.clear();
3711 }
3712 } else if (mCurrentTouch.pointerCount == 1) {
Jeff Brown325bd072011-04-19 21:20:10 -07003713 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
Jeff Brown96ad3972011-03-09 17:39:48 -08003714 // The pointer follows the active touch point.
Jeff Brown325bd072011-04-19 21:20:10 -07003715 // When in HOVER, emit HOVER_MOVE events at the pointer location.
3716 // When in TAP_DRAG, emit MOVE events at the pointer location.
3717 LOG_ASSERT(activeTouchId >= 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08003718
Jeff Brown325bd072011-04-19 21:20:10 -07003719 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
3720 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
Jeff Brown214eaf42011-05-26 19:17:02 -07003721 if (when <= mPointerGesture.tapUpTime + mConfig->pointerGestureTapDragInterval) {
Jeff Brown325bd072011-04-19 21:20:10 -07003722 float x, y;
3723 mPointerController->getPosition(&x, &y);
Jeff Brown214eaf42011-05-26 19:17:02 -07003724 if (fabs(x - mPointerGesture.tapX) <= mConfig->pointerGestureTapSlop
3725 && fabs(y - mPointerGesture.tapY) <= mConfig->pointerGestureTapSlop) {
Jeff Brown325bd072011-04-19 21:20:10 -07003726 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
3727 } else {
Jeff Brown96ad3972011-03-09 17:39:48 -08003728#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003729 LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
3730 x - mPointerGesture.tapX,
3731 y - mPointerGesture.tapY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003732#endif
Jeff Brown325bd072011-04-19 21:20:10 -07003733 }
3734 } else {
3735#if DEBUG_GESTURES
3736 LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
3737 (when - mPointerGesture.tapUpTime) * 0.000001f);
3738#endif
3739 }
3740 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
3741 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
3742 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003743
3744 if (mLastTouch.idBits.hasBit(activeTouchId)) {
3745 const PointerData& currentPointer =
3746 mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3747 const PointerData& lastPointer =
3748 mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3749 float deltaX = (currentPointer.x - lastPointer.x)
3750 * mLocked.pointerGestureXMovementScale;
3751 float deltaY = (currentPointer.y - lastPointer.y)
3752 * mLocked.pointerGestureYMovementScale;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003753
Jeff Brown19c97d462011-06-01 12:33:19 -07003754 mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
3755
Jeff Brown86ea1f52011-04-12 22:39:53 -07003756 // Move the pointer using a relative motion.
Jeff Brown325bd072011-04-19 21:20:10 -07003757 // When using spots, the hover or drag will occur at the position of the anchor spot.
Jeff Brown96ad3972011-03-09 17:39:48 -08003758 mPointerController->move(deltaX, deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07003759 } else {
3760 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown96ad3972011-03-09 17:39:48 -08003761 }
3762
Jeff Brown325bd072011-04-19 21:20:10 -07003763 bool down;
3764 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
3765#if DEBUG_GESTURES
3766 LOGD("Gestures: TAP_DRAG");
3767#endif
3768 down = true;
3769 } else {
3770#if DEBUG_GESTURES
3771 LOGD("Gestures: HOVER");
3772#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003773 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
3774 *outFinishPreviousGesture = true;
3775 }
Jeff Brown325bd072011-04-19 21:20:10 -07003776 mPointerGesture.activeGestureId = 0;
3777 down = false;
3778 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003779
3780 float x, y;
3781 mPointerController->getPosition(&x, &y);
3782
Jeff Brown96ad3972011-03-09 17:39:48 -08003783 mPointerGesture.currentGestureIdBits.clear();
3784 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3785 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3786 mPointerGesture.currentGestureCoords[0].clear();
3787 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3788 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown325bd072011-04-19 21:20:10 -07003789 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
3790 down ? 1.0f : 0.0f);
3791
Jeff Brown96ad3972011-03-09 17:39:48 -08003792 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brown325bd072011-04-19 21:20:10 -07003793 mPointerGesture.resetTap();
3794 mPointerGesture.tapDownTime = when;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003795 mPointerGesture.tapX = x;
3796 mPointerGesture.tapY = y;
3797 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003798 } else {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003799 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
3800 // We need to provide feedback for each finger that goes down so we cannot wait
3801 // for the fingers to move before deciding what to do.
Jeff Brown96ad3972011-03-09 17:39:48 -08003802 //
Jeff Brown86ea1f52011-04-12 22:39:53 -07003803 // The ambiguous case is deciding what to do when there are two fingers down but they
3804 // have not moved enough to determine whether they are part of a drag or part of a
3805 // freeform gesture, or just a press or long-press at the pointer location.
3806 //
3807 // When there are two fingers we start with the PRESS hypothesis and we generate a
3808 // down at the pointer location.
3809 //
3810 // When the two fingers move enough or when additional fingers are added, we make
3811 // a decision to transition into SWIPE or FREEFORM mode accordingly.
3812 LOG_ASSERT(activeTouchId >= 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08003813
Jeff Brown214eaf42011-05-26 19:17:02 -07003814 bool settled = when >= mPointerGesture.firstTouchTime
3815 + mConfig->pointerGestureMultitouchSettleInterval;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003816 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
Jeff Brown96ad3972011-03-09 17:39:48 -08003817 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
3818 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003819 *outFinishPreviousGesture = true;
Jeff Brown19c97d462011-06-01 12:33:19 -07003820 } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
3821 // Additional pointers have gone down but not yet settled.
3822 // Reset the gesture.
3823#if DEBUG_GESTURES
3824 LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003825 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
3826 + mConfig->pointerGestureMultitouchSettleInterval - when)
Jeff Brown19c97d462011-06-01 12:33:19 -07003827 * 0.000001f);
3828#endif
3829 *outCancelPreviousGesture = true;
3830 } else {
3831 // Continue previous gesture.
3832 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
3833 }
3834
3835 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003836 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
3837 mPointerGesture.activeGestureId = 0;
Jeff Brown538881e2011-05-25 18:23:38 -07003838 mPointerGesture.referenceIdBits.clear();
Jeff Brown19c97d462011-06-01 12:33:19 -07003839 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown96ad3972011-03-09 17:39:48 -08003840
Jeff Browncb5ffcf2011-06-06 20:03:18 -07003841 // Use the centroid and pointer location as the reference points for the gesture.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003842#if DEBUG_GESTURES
Jeff Browncb5ffcf2011-06-06 20:03:18 -07003843 LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
3844 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
3845 + mConfig->pointerGestureMultitouchSettleInterval - when)
3846 * 0.000001f);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003847#endif
Jeff Browncb5ffcf2011-06-06 20:03:18 -07003848 mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
3849 &mPointerGesture.referenceTouchY);
3850 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
3851 &mPointerGesture.referenceGestureY);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003852 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003853
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003854 // Clear the reference deltas for fingers not yet included in the reference calculation.
3855 for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
3856 !idBits.isEmpty(); ) {
3857 uint32_t id = idBits.firstMarkedBit();
3858 idBits.clearBit(id);
3859
3860 mPointerGesture.referenceDeltas[id].dx = 0;
3861 mPointerGesture.referenceDeltas[id].dy = 0;
3862 }
3863 mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
3864
3865 // Add delta for all fingers and calculate a common movement delta.
3866 float commonDeltaX = 0, commonDeltaY = 0;
3867 BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
3868 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
3869 bool first = (idBits == commonIdBits);
3870 uint32_t id = idBits.firstMarkedBit();
3871 idBits.clearBit(id);
3872
3873 const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
3874 const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
3875 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
3876 delta.dx += cpd.x - lpd.x;
3877 delta.dy += cpd.y - lpd.y;
3878
3879 if (first) {
3880 commonDeltaX = delta.dx;
3881 commonDeltaY = delta.dy;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003882 } else {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003883 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
3884 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
3885 }
3886 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003887
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003888 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
3889 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
3890 float dist[MAX_POINTER_ID + 1];
3891 int32_t distOverThreshold = 0;
3892 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
3893 uint32_t id = idBits.firstMarkedBit();
3894 idBits.clearBit(id);
Jeff Brown96ad3972011-03-09 17:39:48 -08003895
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003896 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
3897 dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale,
3898 delta.dy * mLocked.pointerGestureYZoomScale);
3899 if (dist[id] > mConfig->pointerGestureMultitouchMinDistance) {
3900 distOverThreshold += 1;
3901 }
3902 }
3903
3904 // Only transition when at least two pointers have moved further than
3905 // the minimum distance threshold.
3906 if (distOverThreshold >= 2) {
3907 float d;
3908 if (mCurrentTouch.pointerCount > 2) {
3909 // There are more than two pointers, switch to FREEFORM.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003910#if DEBUG_GESTURES
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003911 LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
3912 mCurrentTouch.pointerCount);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003913#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003914 *outCancelPreviousGesture = true;
3915 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3916 } else if (((d = distance(
3917 mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
3918 mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
3919 > mLocked.pointerGestureMaxSwipeWidth)) {
3920 // There are two pointers but they are too far apart for a SWIPE,
3921 // switch to FREEFORM.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003922#if DEBUG_GESTURES
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003923 LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
3924 d, mLocked.pointerGestureMaxSwipeWidth);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003925#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003926 *outCancelPreviousGesture = true;
3927 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3928 } else {
3929 // There are two pointers. Wait for both pointers to start moving
3930 // before deciding whether this is a SWIPE or FREEFORM gesture.
3931 uint32_t id1 = mCurrentTouch.pointers[0].id;
3932 uint32_t id2 = mCurrentTouch.pointers[1].id;
3933 float dist1 = dist[id1];
3934 float dist2 = dist[id2];
3935 if (dist1 >= mConfig->pointerGestureMultitouchMinDistance
3936 && dist2 >= mConfig->pointerGestureMultitouchMinDistance) {
3937 // Calculate the dot product of the displacement vectors.
3938 // When the vectors are oriented in approximately the same direction,
3939 // the angle betweeen them is near zero and the cosine of the angle
3940 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
3941 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
3942 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
Jeff Brown6674d9b2011-06-07 16:50:14 -07003943 float dx1 = delta1.dx * mLocked.pointerGestureXZoomScale;
3944 float dy1 = delta1.dy * mLocked.pointerGestureYZoomScale;
3945 float dx2 = delta2.dx * mLocked.pointerGestureXZoomScale;
3946 float dy2 = delta2.dy * mLocked.pointerGestureYZoomScale;
3947 float dot = dx1 * dx2 + dy1 * dy2;
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003948 float cosine = dot / (dist1 * dist2); // denominator always > 0
3949 if (cosine >= mConfig->pointerGestureSwipeTransitionAngleCosine) {
3950 // Pointers are moving in the same direction. Switch to SWIPE.
3951#if DEBUG_GESTURES
3952 LOGD("Gestures: PRESS transitioned to SWIPE, "
3953 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
3954 "cosine %0.3f >= %0.3f",
3955 dist1, mConfig->pointerGestureMultitouchMinDistance,
3956 dist2, mConfig->pointerGestureMultitouchMinDistance,
3957 cosine, mConfig->pointerGestureSwipeTransitionAngleCosine);
3958#endif
3959 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
3960 } else {
3961 // Pointers are moving in different directions. Switch to FREEFORM.
3962#if DEBUG_GESTURES
3963 LOGD("Gestures: PRESS transitioned to FREEFORM, "
3964 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
3965 "cosine %0.3f < %0.3f",
3966 dist1, mConfig->pointerGestureMultitouchMinDistance,
3967 dist2, mConfig->pointerGestureMultitouchMinDistance,
3968 cosine, mConfig->pointerGestureSwipeTransitionAngleCosine);
3969#endif
3970 *outCancelPreviousGesture = true;
3971 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3972 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003973 }
3974 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003975 }
3976 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003977 // Switch from SWIPE to FREEFORM if additional pointers go down.
3978 // Cancel previous gesture.
3979 if (mCurrentTouch.pointerCount > 2) {
3980#if DEBUG_GESTURES
3981 LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
3982 mCurrentTouch.pointerCount);
3983#endif
Jeff Brown96ad3972011-03-09 17:39:48 -08003984 *outCancelPreviousGesture = true;
3985 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003986 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07003987 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003988
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003989 // Move the reference points based on the overall group motion of the fingers
3990 // except in PRESS mode while waiting for a transition to occur.
3991 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
3992 && (commonDeltaX || commonDeltaY)) {
3993 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003994 uint32_t id = idBits.firstMarkedBit();
3995 idBits.clearBit(id);
3996
Jeff Brown538881e2011-05-25 18:23:38 -07003997 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003998 delta.dx = 0;
3999 delta.dy = 0;
Jeff Brown86ea1f52011-04-12 22:39:53 -07004000 }
4001
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004002 mPointerGesture.referenceTouchX += commonDeltaX;
4003 mPointerGesture.referenceTouchY += commonDeltaY;
Jeff Brown538881e2011-05-25 18:23:38 -07004004
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004005 commonDeltaX *= mLocked.pointerGestureXMovementScale;
4006 commonDeltaY *= mLocked.pointerGestureYMovementScale;
4007 mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
Jeff Brown538881e2011-05-25 18:23:38 -07004008
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004009 mPointerGesture.referenceGestureX += commonDeltaX;
4010 mPointerGesture.referenceGestureY += commonDeltaY;
Jeff Brown86ea1f52011-04-12 22:39:53 -07004011 }
4012
4013 // Report gestures.
4014 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4015 // PRESS mode.
Jeff Brown96ad3972011-03-09 17:39:48 -08004016#if DEBUG_GESTURES
Jeff Brown86ea1f52011-04-12 22:39:53 -07004017 LOGD("Gestures: PRESS activeTouchId=%d,"
Jeff Brown96ad3972011-03-09 17:39:48 -08004018 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown86ea1f52011-04-12 22:39:53 -07004019 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
Jeff Brown96ad3972011-03-09 17:39:48 -08004020#endif
Jeff Brown86ea1f52011-04-12 22:39:53 -07004021 LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08004022
Jeff Brown96ad3972011-03-09 17:39:48 -08004023 mPointerGesture.currentGestureIdBits.clear();
4024 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4025 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4026 mPointerGesture.currentGestureCoords[0].clear();
Jeff Brown86ea1f52011-04-12 22:39:53 -07004027 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4028 mPointerGesture.referenceGestureX);
4029 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4030 mPointerGesture.referenceGestureY);
Jeff Brown96ad3972011-03-09 17:39:48 -08004031 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown86ea1f52011-04-12 22:39:53 -07004032 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4033 // SWIPE mode.
4034#if DEBUG_GESTURES
4035 LOGD("Gestures: SWIPE activeTouchId=%d,"
4036 "activeGestureId=%d, currentTouchPointerCount=%d",
4037 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4038#endif
4039 assert(mPointerGesture.activeGestureId >= 0);
4040
4041 mPointerGesture.currentGestureIdBits.clear();
4042 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4043 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4044 mPointerGesture.currentGestureCoords[0].clear();
4045 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4046 mPointerGesture.referenceGestureX);
4047 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4048 mPointerGesture.referenceGestureY);
4049 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown96ad3972011-03-09 17:39:48 -08004050 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4051 // FREEFORM mode.
4052#if DEBUG_GESTURES
4053 LOGD("Gestures: FREEFORM activeTouchId=%d,"
4054 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown86ea1f52011-04-12 22:39:53 -07004055 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
Jeff Brown96ad3972011-03-09 17:39:48 -08004056#endif
4057 assert(mPointerGesture.activeGestureId >= 0);
4058
Jeff Brown96ad3972011-03-09 17:39:48 -08004059 mPointerGesture.currentGestureIdBits.clear();
4060
4061 BitSet32 mappedTouchIdBits;
4062 BitSet32 usedGestureIdBits;
4063 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4064 // Initially, assign the active gesture id to the active touch point
4065 // if there is one. No other touch id bits are mapped yet.
4066 if (!*outCancelPreviousGesture) {
4067 mappedTouchIdBits.markBit(activeTouchId);
4068 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4069 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4070 mPointerGesture.activeGestureId;
4071 } else {
4072 mPointerGesture.activeGestureId = -1;
4073 }
4074 } else {
4075 // Otherwise, assume we mapped all touches from the previous frame.
4076 // Reuse all mappings that are still applicable.
4077 mappedTouchIdBits.value = mLastTouch.idBits.value & mCurrentTouch.idBits.value;
4078 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4079
4080 // Check whether we need to choose a new active gesture id because the
4081 // current went went up.
4082 for (BitSet32 upTouchIdBits(mLastTouch.idBits.value & ~mCurrentTouch.idBits.value);
4083 !upTouchIdBits.isEmpty(); ) {
4084 uint32_t upTouchId = upTouchIdBits.firstMarkedBit();
4085 upTouchIdBits.clearBit(upTouchId);
4086 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4087 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4088 mPointerGesture.activeGestureId = -1;
4089 break;
4090 }
4091 }
4092 }
4093
4094#if DEBUG_GESTURES
4095 LOGD("Gestures: FREEFORM follow up "
4096 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4097 "activeGestureId=%d",
4098 mappedTouchIdBits.value, usedGestureIdBits.value,
4099 mPointerGesture.activeGestureId);
4100#endif
4101
Jeff Brown86ea1f52011-04-12 22:39:53 -07004102 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
Jeff Brown96ad3972011-03-09 17:39:48 -08004103 uint32_t touchId = mCurrentTouch.pointers[i].id;
4104 uint32_t gestureId;
4105 if (!mappedTouchIdBits.hasBit(touchId)) {
4106 gestureId = usedGestureIdBits.firstUnmarkedBit();
4107 usedGestureIdBits.markBit(gestureId);
4108 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4109#if DEBUG_GESTURES
4110 LOGD("Gestures: FREEFORM "
4111 "new mapping for touch id %d -> gesture id %d",
4112 touchId, gestureId);
4113#endif
4114 } else {
4115 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4116#if DEBUG_GESTURES
4117 LOGD("Gestures: FREEFORM "
4118 "existing mapping for touch id %d -> gesture id %d",
4119 touchId, gestureId);
4120#endif
4121 }
4122 mPointerGesture.currentGestureIdBits.markBit(gestureId);
4123 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4124
Jeff Brown86ea1f52011-04-12 22:39:53 -07004125 float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4126 * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
4127 float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4128 * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
Jeff Brown96ad3972011-03-09 17:39:48 -08004129
4130 mPointerGesture.currentGestureCoords[i].clear();
4131 mPointerGesture.currentGestureCoords[i].setAxisValue(
4132 AMOTION_EVENT_AXIS_X, x);
4133 mPointerGesture.currentGestureCoords[i].setAxisValue(
4134 AMOTION_EVENT_AXIS_Y, y);
4135 mPointerGesture.currentGestureCoords[i].setAxisValue(
4136 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4137 }
4138
4139 if (mPointerGesture.activeGestureId < 0) {
4140 mPointerGesture.activeGestureId =
4141 mPointerGesture.currentGestureIdBits.firstMarkedBit();
4142#if DEBUG_GESTURES
4143 LOGD("Gestures: FREEFORM new "
4144 "activeGestureId=%d", mPointerGesture.activeGestureId);
4145#endif
4146 }
Jeff Brown86ea1f52011-04-12 22:39:53 -07004147 }
Jeff Brown96ad3972011-03-09 17:39:48 -08004148 }
4149
Jeff Brown4e3f7202011-05-31 15:00:18 -07004150 mPointerController->setButtonState(mCurrentTouch.buttonState);
4151
Jeff Brown96ad3972011-03-09 17:39:48 -08004152#if DEBUG_GESTURES
4153 LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
Jeff Brown86ea1f52011-04-12 22:39:53 -07004154 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4155 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
Jeff Brown96ad3972011-03-09 17:39:48 -08004156 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
Jeff Brown86ea1f52011-04-12 22:39:53 -07004157 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4158 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
Jeff Brown96ad3972011-03-09 17:39:48 -08004159 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
4160 uint32_t id = idBits.firstMarkedBit();
4161 idBits.clearBit(id);
4162 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4163 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
4164 LOGD(" currentGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
4165 id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4166 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4167 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4168 }
4169 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
4170 uint32_t id = idBits.firstMarkedBit();
4171 idBits.clearBit(id);
4172 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
4173 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
4174 LOGD(" lastGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
4175 id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4176 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4177 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4178 }
4179#endif
Jeff Brown325bd072011-04-19 21:20:10 -07004180 return true;
Jeff Brown96ad3972011-03-09 17:39:48 -08004181}
4182
4183void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
4184 int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
4185 const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
4186 int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
4187 PointerCoords pointerCoords[MAX_POINTERS];
4188 int32_t pointerIds[MAX_POINTERS];
4189 uint32_t pointerCount = 0;
4190 while (!idBits.isEmpty()) {
4191 uint32_t id = idBits.firstMarkedBit();
4192 idBits.clearBit(id);
4193 uint32_t index = idToIndex[id];
4194 pointerIds[pointerCount] = id;
4195 pointerCoords[pointerCount].copyFrom(coords[index]);
4196
4197 if (changedId >= 0 && id == uint32_t(changedId)) {
4198 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
4199 }
4200
4201 pointerCount += 1;
4202 }
4203
4204 assert(pointerCount != 0);
4205
4206 if (changedId >= 0 && pointerCount == 1) {
4207 // Replace initial down and final up action.
4208 // We can compare the action without masking off the changed pointer index
4209 // because we know the index is 0.
4210 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
4211 action = AMOTION_EVENT_ACTION_DOWN;
4212 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
4213 action = AMOTION_EVENT_ACTION_UP;
4214 } else {
4215 // Can't happen.
4216 assert(false);
4217 }
4218 }
4219
4220 getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags,
4221 action, flags, metaState, edgeFlags,
4222 pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, downTime);
4223}
4224
4225bool TouchInputMapper::updateMovedPointerCoords(
4226 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
4227 PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const {
4228 bool changed = false;
4229 while (!idBits.isEmpty()) {
4230 uint32_t id = idBits.firstMarkedBit();
4231 idBits.clearBit(id);
4232
4233 uint32_t inIndex = inIdToIndex[id];
4234 uint32_t outIndex = outIdToIndex[id];
4235 const PointerCoords& curInCoords = inCoords[inIndex];
4236 PointerCoords& curOutCoords = outCoords[outIndex];
4237
4238 if (curInCoords != curOutCoords) {
4239 curOutCoords.copyFrom(curInCoords);
4240 changed = true;
4241 }
4242 }
4243 return changed;
4244}
4245
4246void TouchInputMapper::fadePointer() {
4247 { // acquire lock
4248 AutoMutex _l(mLock);
4249 if (mPointerController != NULL) {
Jeff Brown538881e2011-05-25 18:23:38 -07004250 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Jeff Brown96ad3972011-03-09 17:39:48 -08004251 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004252 } // release lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07004253}
4254
Jeff Brown6328cdc2010-07-29 18:18:33 -07004255bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown9626b142011-03-03 02:09:54 -08004256 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
4257 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004258}
4259
Jeff Brown6328cdc2010-07-29 18:18:33 -07004260const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
4261 int32_t x, int32_t y) {
4262 size_t numVirtualKeys = mLocked.virtualKeys.size();
4263 for (size_t i = 0; i < numVirtualKeys; i++) {
4264 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004265
4266#if DEBUG_VIRTUAL_KEYS
4267 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
4268 "left=%d, top=%d, right=%d, bottom=%d",
4269 x, y,
4270 virtualKey.keyCode, virtualKey.scanCode,
4271 virtualKey.hitLeft, virtualKey.hitTop,
4272 virtualKey.hitRight, virtualKey.hitBottom);
4273#endif
4274
4275 if (virtualKey.isHit(x, y)) {
4276 return & virtualKey;
4277 }
4278 }
4279
4280 return NULL;
4281}
4282
4283void TouchInputMapper::calculatePointerIds() {
4284 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
4285 uint32_t lastPointerCount = mLastTouch.pointerCount;
4286
4287 if (currentPointerCount == 0) {
4288 // No pointers to assign.
4289 mCurrentTouch.idBits.clear();
4290 } else if (lastPointerCount == 0) {
4291 // All pointers are new.
4292 mCurrentTouch.idBits.clear();
4293 for (uint32_t i = 0; i < currentPointerCount; i++) {
4294 mCurrentTouch.pointers[i].id = i;
4295 mCurrentTouch.idToIndex[i] = i;
4296 mCurrentTouch.idBits.markBit(i);
4297 }
4298 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
4299 // Only one pointer and no change in count so it must have the same id as before.
4300 uint32_t id = mLastTouch.pointers[0].id;
4301 mCurrentTouch.pointers[0].id = id;
4302 mCurrentTouch.idToIndex[id] = 0;
4303 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
4304 } else {
4305 // General case.
4306 // We build a heap of squared euclidean distances between current and last pointers
4307 // associated with the current and last pointer indices. Then, we find the best
4308 // match (by distance) for each current pointer.
4309 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
4310
4311 uint32_t heapSize = 0;
4312 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
4313 currentPointerIndex++) {
4314 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
4315 lastPointerIndex++) {
4316 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
4317 - mLastTouch.pointers[lastPointerIndex].x;
4318 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
4319 - mLastTouch.pointers[lastPointerIndex].y;
4320
4321 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4322
4323 // Insert new element into the heap (sift up).
4324 heap[heapSize].currentPointerIndex = currentPointerIndex;
4325 heap[heapSize].lastPointerIndex = lastPointerIndex;
4326 heap[heapSize].distance = distance;
4327 heapSize += 1;
4328 }
4329 }
4330
4331 // Heapify
4332 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
4333 startIndex -= 1;
4334 for (uint32_t parentIndex = startIndex; ;) {
4335 uint32_t childIndex = parentIndex * 2 + 1;
4336 if (childIndex >= heapSize) {
4337 break;
4338 }
4339
4340 if (childIndex + 1 < heapSize
4341 && heap[childIndex + 1].distance < heap[childIndex].distance) {
4342 childIndex += 1;
4343 }
4344
4345 if (heap[parentIndex].distance <= heap[childIndex].distance) {
4346 break;
4347 }
4348
4349 swap(heap[parentIndex], heap[childIndex]);
4350 parentIndex = childIndex;
4351 }
4352 }
4353
4354#if DEBUG_POINTER_ASSIGNMENT
4355 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
4356 for (size_t i = 0; i < heapSize; i++) {
4357 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
4358 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4359 heap[i].distance);
4360 }
4361#endif
4362
4363 // Pull matches out by increasing order of distance.
4364 // To avoid reassigning pointers that have already been matched, the loop keeps track
4365 // of which last and current pointers have been matched using the matchedXXXBits variables.
4366 // It also tracks the used pointer id bits.
4367 BitSet32 matchedLastBits(0);
4368 BitSet32 matchedCurrentBits(0);
4369 BitSet32 usedIdBits(0);
4370 bool first = true;
4371 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
4372 for (;;) {
4373 if (first) {
4374 // The first time through the loop, we just consume the root element of
4375 // the heap (the one with smallest distance).
4376 first = false;
4377 } else {
4378 // Previous iterations consumed the root element of the heap.
4379 // Pop root element off of the heap (sift down).
4380 heapSize -= 1;
4381 assert(heapSize > 0);
4382
4383 // Sift down.
4384 heap[0] = heap[heapSize];
4385 for (uint32_t parentIndex = 0; ;) {
4386 uint32_t childIndex = parentIndex * 2 + 1;
4387 if (childIndex >= heapSize) {
4388 break;
4389 }
4390
4391 if (childIndex + 1 < heapSize
4392 && heap[childIndex + 1].distance < heap[childIndex].distance) {
4393 childIndex += 1;
4394 }
4395
4396 if (heap[parentIndex].distance <= heap[childIndex].distance) {
4397 break;
4398 }
4399
4400 swap(heap[parentIndex], heap[childIndex]);
4401 parentIndex = childIndex;
4402 }
4403
4404#if DEBUG_POINTER_ASSIGNMENT
4405 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
4406 for (size_t i = 0; i < heapSize; i++) {
4407 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
4408 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4409 heap[i].distance);
4410 }
4411#endif
4412 }
4413
4414 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
4415 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
4416
4417 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
4418 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
4419
4420 matchedCurrentBits.markBit(currentPointerIndex);
4421 matchedLastBits.markBit(lastPointerIndex);
4422
4423 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
4424 mCurrentTouch.pointers[currentPointerIndex].id = id;
4425 mCurrentTouch.idToIndex[id] = currentPointerIndex;
4426 usedIdBits.markBit(id);
4427
4428#if DEBUG_POINTER_ASSIGNMENT
4429 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
4430 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
4431#endif
4432 break;
4433 }
4434 }
4435
4436 // Assign fresh ids to new pointers.
4437 if (currentPointerCount > lastPointerCount) {
4438 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
4439 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
4440 uint32_t id = usedIdBits.firstUnmarkedBit();
4441
4442 mCurrentTouch.pointers[currentPointerIndex].id = id;
4443 mCurrentTouch.idToIndex[id] = currentPointerIndex;
4444 usedIdBits.markBit(id);
4445
4446#if DEBUG_POINTER_ASSIGNMENT
4447 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
4448 currentPointerIndex, id);
4449#endif
4450
4451 if (--i == 0) break; // done
4452 matchedCurrentBits.markBit(currentPointerIndex);
4453 }
4454 }
4455
4456 // Fix id bits.
4457 mCurrentTouch.idBits = usedIdBits;
4458 }
4459}
4460
4461/* Special hack for devices that have bad screen data: if one of the
4462 * points has moved more than a screen height from the last position,
4463 * then drop it. */
4464bool TouchInputMapper::applyBadTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004465 uint32_t pointerCount = mCurrentTouch.pointerCount;
4466
4467 // Nothing to do if there are no points.
4468 if (pointerCount == 0) {
4469 return false;
4470 }
4471
4472 // Don't do anything if a finger is going down or up. We run
4473 // here before assigning pointer IDs, so there isn't a good
4474 // way to do per-finger matching.
4475 if (pointerCount != mLastTouch.pointerCount) {
4476 return false;
4477 }
4478
4479 // We consider a single movement across more than a 7/16 of
4480 // the long size of the screen to be bad. This was a magic value
4481 // determined by looking at the maximum distance it is feasible
4482 // to actually move in one sample.
Jeff Brown9626b142011-03-03 02:09:54 -08004483 int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004484
4485 // XXX The original code in InputDevice.java included commented out
4486 // code for testing the X axis. Note that when we drop a point
4487 // we don't actually restore the old X either. Strange.
4488 // The old code also tries to track when bad points were previously
4489 // detected but it turns out that due to the placement of a "break"
4490 // at the end of the loop, we never set mDroppedBadPoint to true
4491 // so it is effectively dead code.
4492 // Need to figure out if the old code is busted or just overcomplicated
4493 // but working as intended.
4494
4495 // Look through all new points and see if any are farther than
4496 // acceptable from all previous points.
4497 for (uint32_t i = pointerCount; i-- > 0; ) {
4498 int32_t y = mCurrentTouch.pointers[i].y;
4499 int32_t closestY = INT_MAX;
4500 int32_t closestDeltaY = 0;
4501
4502#if DEBUG_HACKS
4503 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
4504#endif
4505
4506 for (uint32_t j = pointerCount; j-- > 0; ) {
4507 int32_t lastY = mLastTouch.pointers[j].y;
4508 int32_t deltaY = abs(y - lastY);
4509
4510#if DEBUG_HACKS
4511 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
4512 j, lastY, deltaY);
4513#endif
4514
4515 if (deltaY < maxDeltaY) {
4516 goto SkipSufficientlyClosePoint;
4517 }
4518 if (deltaY < closestDeltaY) {
4519 closestDeltaY = deltaY;
4520 closestY = lastY;
4521 }
4522 }
4523
4524 // Must not have found a close enough match.
4525#if DEBUG_HACKS
4526 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
4527 i, y, closestY, closestDeltaY, maxDeltaY);
4528#endif
4529
4530 mCurrentTouch.pointers[i].y = closestY;
4531 return true; // XXX original code only corrects one point
4532
4533 SkipSufficientlyClosePoint: ;
4534 }
4535
4536 // No change.
4537 return false;
4538}
4539
4540/* Special hack for devices that have bad screen data: drop points where
4541 * the coordinate value for one axis has jumped to the other pointer's location.
4542 */
4543bool TouchInputMapper::applyJumpyTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004544 uint32_t pointerCount = mCurrentTouch.pointerCount;
4545 if (mLastTouch.pointerCount != pointerCount) {
4546#if DEBUG_HACKS
4547 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
4548 mLastTouch.pointerCount, pointerCount);
4549 for (uint32_t i = 0; i < pointerCount; i++) {
4550 LOGD(" Pointer %d (%d, %d)", i,
4551 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4552 }
4553#endif
4554
4555 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
4556 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
4557 // Just drop the first few events going from 1 to 2 pointers.
4558 // They're bad often enough that they're not worth considering.
4559 mCurrentTouch.pointerCount = 1;
4560 mJumpyTouchFilter.jumpyPointsDropped += 1;
4561
4562#if DEBUG_HACKS
4563 LOGD("JumpyTouchFilter: Pointer 2 dropped");
4564#endif
4565 return true;
4566 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
4567 // The event when we go from 2 -> 1 tends to be messed up too
4568 mCurrentTouch.pointerCount = 2;
4569 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
4570 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
4571 mJumpyTouchFilter.jumpyPointsDropped += 1;
4572
4573#if DEBUG_HACKS
4574 for (int32_t i = 0; i < 2; i++) {
4575 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
4576 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4577 }
4578#endif
4579 return true;
4580 }
4581 }
4582 // Reset jumpy points dropped on other transitions or if limit exceeded.
4583 mJumpyTouchFilter.jumpyPointsDropped = 0;
4584
4585#if DEBUG_HACKS
4586 LOGD("JumpyTouchFilter: Transition - drop limit reset");
4587#endif
4588 return false;
4589 }
4590
4591 // We have the same number of pointers as last time.
4592 // A 'jumpy' point is one where the coordinate value for one axis
4593 // has jumped to the other pointer's location. No need to do anything
4594 // else if we only have one pointer.
4595 if (pointerCount < 2) {
4596 return false;
4597 }
4598
4599 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown9626b142011-03-03 02:09:54 -08004600 int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004601
4602 // We only replace the single worst jumpy point as characterized by pointer distance
4603 // in a single axis.
4604 int32_t badPointerIndex = -1;
4605 int32_t badPointerReplacementIndex = -1;
4606 int32_t badPointerDistance = INT_MIN; // distance to be corrected
4607
4608 for (uint32_t i = pointerCount; i-- > 0; ) {
4609 int32_t x = mCurrentTouch.pointers[i].x;
4610 int32_t y = mCurrentTouch.pointers[i].y;
4611
4612#if DEBUG_HACKS
4613 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
4614#endif
4615
4616 // Check if a touch point is too close to another's coordinates
4617 bool dropX = false, dropY = false;
4618 for (uint32_t j = 0; j < pointerCount; j++) {
4619 if (i == j) {
4620 continue;
4621 }
4622
4623 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
4624 dropX = true;
4625 break;
4626 }
4627
4628 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
4629 dropY = true;
4630 break;
4631 }
4632 }
4633 if (! dropX && ! dropY) {
4634 continue; // not jumpy
4635 }
4636
4637 // Find a replacement candidate by comparing with older points on the
4638 // complementary (non-jumpy) axis.
4639 int32_t distance = INT_MIN; // distance to be corrected
4640 int32_t replacementIndex = -1;
4641
4642 if (dropX) {
4643 // X looks too close. Find an older replacement point with a close Y.
4644 int32_t smallestDeltaY = INT_MAX;
4645 for (uint32_t j = 0; j < pointerCount; j++) {
4646 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
4647 if (deltaY < smallestDeltaY) {
4648 smallestDeltaY = deltaY;
4649 replacementIndex = j;
4650 }
4651 }
4652 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
4653 } else {
4654 // Y looks too close. Find an older replacement point with a close X.
4655 int32_t smallestDeltaX = INT_MAX;
4656 for (uint32_t j = 0; j < pointerCount; j++) {
4657 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
4658 if (deltaX < smallestDeltaX) {
4659 smallestDeltaX = deltaX;
4660 replacementIndex = j;
4661 }
4662 }
4663 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
4664 }
4665
4666 // If replacing this pointer would correct a worse error than the previous ones
4667 // considered, then use this replacement instead.
4668 if (distance > badPointerDistance) {
4669 badPointerIndex = i;
4670 badPointerReplacementIndex = replacementIndex;
4671 badPointerDistance = distance;
4672 }
4673 }
4674
4675 // Correct the jumpy pointer if one was found.
4676 if (badPointerIndex >= 0) {
4677#if DEBUG_HACKS
4678 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
4679 badPointerIndex,
4680 mLastTouch.pointers[badPointerReplacementIndex].x,
4681 mLastTouch.pointers[badPointerReplacementIndex].y);
4682#endif
4683
4684 mCurrentTouch.pointers[badPointerIndex].x =
4685 mLastTouch.pointers[badPointerReplacementIndex].x;
4686 mCurrentTouch.pointers[badPointerIndex].y =
4687 mLastTouch.pointers[badPointerReplacementIndex].y;
4688 mJumpyTouchFilter.jumpyPointsDropped += 1;
4689 return true;
4690 }
4691 }
4692
4693 mJumpyTouchFilter.jumpyPointsDropped = 0;
4694 return false;
4695}
4696
4697/* Special hack for devices that have bad screen data: aggregate and
4698 * compute averages of the coordinate data, to reduce the amount of
4699 * jitter seen by applications. */
4700void TouchInputMapper::applyAveragingTouchFilter() {
4701 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
4702 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
4703 int32_t x = mCurrentTouch.pointers[currentIndex].x;
4704 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07004705 int32_t pressure;
4706 switch (mCalibration.pressureSource) {
4707 case Calibration::PRESSURE_SOURCE_PRESSURE:
4708 pressure = mCurrentTouch.pointers[currentIndex].pressure;
4709 break;
4710 case Calibration::PRESSURE_SOURCE_TOUCH:
4711 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
4712 break;
4713 default:
4714 pressure = 1;
4715 break;
4716 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07004717
4718 if (mLastTouch.idBits.hasBit(id)) {
4719 // Pointer was down before and is still down now.
4720 // Compute average over history trace.
4721 uint32_t start = mAveragingTouchFilter.historyStart[id];
4722 uint32_t end = mAveragingTouchFilter.historyEnd[id];
4723
4724 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
4725 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
4726 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4727
4728#if DEBUG_HACKS
4729 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
4730 id, distance);
4731#endif
4732
4733 if (distance < AVERAGING_DISTANCE_LIMIT) {
4734 // Increment end index in preparation for recording new historical data.
4735 end += 1;
4736 if (end > AVERAGING_HISTORY_SIZE) {
4737 end = 0;
4738 }
4739
4740 // If the end index has looped back to the start index then we have filled
4741 // the historical trace up to the desired size so we drop the historical
4742 // data at the start of the trace.
4743 if (end == start) {
4744 start += 1;
4745 if (start > AVERAGING_HISTORY_SIZE) {
4746 start = 0;
4747 }
4748 }
4749
4750 // Add the raw data to the historical trace.
4751 mAveragingTouchFilter.historyStart[id] = start;
4752 mAveragingTouchFilter.historyEnd[id] = end;
4753 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
4754 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
4755 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
4756
4757 // Average over all historical positions in the trace by total pressure.
4758 int32_t averagedX = 0;
4759 int32_t averagedY = 0;
4760 int32_t totalPressure = 0;
4761 for (;;) {
4762 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
4763 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
4764 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
4765 .pointers[id].pressure;
4766
4767 averagedX += historicalX * historicalPressure;
4768 averagedY += historicalY * historicalPressure;
4769 totalPressure += historicalPressure;
4770
4771 if (start == end) {
4772 break;
4773 }
4774
4775 start += 1;
4776 if (start > AVERAGING_HISTORY_SIZE) {
4777 start = 0;
4778 }
4779 }
4780
Jeff Brown8d608662010-08-30 03:02:23 -07004781 if (totalPressure != 0) {
4782 averagedX /= totalPressure;
4783 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004784
4785#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07004786 LOGD("AveragingTouchFilter: Pointer id %d - "
4787 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
4788 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004789#endif
4790
Jeff Brown8d608662010-08-30 03:02:23 -07004791 mCurrentTouch.pointers[currentIndex].x = averagedX;
4792 mCurrentTouch.pointers[currentIndex].y = averagedY;
4793 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07004794 } else {
4795#if DEBUG_HACKS
4796 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
4797#endif
4798 }
4799 } else {
4800#if DEBUG_HACKS
4801 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
4802#endif
4803 }
4804
4805 // Reset pointer history.
4806 mAveragingTouchFilter.historyStart[id] = 0;
4807 mAveragingTouchFilter.historyEnd[id] = 0;
4808 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
4809 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
4810 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
4811 }
4812}
4813
4814int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004815 { // acquire lock
4816 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004817
Jeff Brown6328cdc2010-07-29 18:18:33 -07004818 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004819 return AKEY_STATE_VIRTUAL;
4820 }
4821
Jeff Brown6328cdc2010-07-29 18:18:33 -07004822 size_t numVirtualKeys = mLocked.virtualKeys.size();
4823 for (size_t i = 0; i < numVirtualKeys; i++) {
4824 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004825 if (virtualKey.keyCode == keyCode) {
4826 return AKEY_STATE_UP;
4827 }
4828 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004829 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004830
4831 return AKEY_STATE_UNKNOWN;
4832}
4833
4834int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004835 { // acquire lock
4836 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004837
Jeff Brown6328cdc2010-07-29 18:18:33 -07004838 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004839 return AKEY_STATE_VIRTUAL;
4840 }
4841
Jeff Brown6328cdc2010-07-29 18:18:33 -07004842 size_t numVirtualKeys = mLocked.virtualKeys.size();
4843 for (size_t i = 0; i < numVirtualKeys; i++) {
4844 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004845 if (virtualKey.scanCode == scanCode) {
4846 return AKEY_STATE_UP;
4847 }
4848 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004849 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004850
4851 return AKEY_STATE_UNKNOWN;
4852}
4853
4854bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
4855 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004856 { // acquire lock
4857 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004858
Jeff Brown6328cdc2010-07-29 18:18:33 -07004859 size_t numVirtualKeys = mLocked.virtualKeys.size();
4860 for (size_t i = 0; i < numVirtualKeys; i++) {
4861 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004862
4863 for (size_t i = 0; i < numCodes; i++) {
4864 if (virtualKey.keyCode == keyCodes[i]) {
4865 outFlags[i] = 1;
4866 }
4867 }
4868 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004869 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004870
4871 return true;
4872}
4873
4874
4875// --- SingleTouchInputMapper ---
4876
Jeff Brown47e6b1b2010-11-29 17:37:49 -08004877SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
4878 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004879 initialize();
4880}
4881
4882SingleTouchInputMapper::~SingleTouchInputMapper() {
4883}
4884
4885void SingleTouchInputMapper::initialize() {
4886 mAccumulator.clear();
4887
4888 mDown = false;
4889 mX = 0;
4890 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07004891 mPressure = 0; // default to 0 for devices that don't report pressure
4892 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown96ad3972011-03-09 17:39:48 -08004893 mButtonState = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004894}
4895
4896void SingleTouchInputMapper::reset() {
4897 TouchInputMapper::reset();
4898
Jeff Brown6d0fec22010-07-23 21:28:06 -07004899 initialize();
4900 }
4901
4902void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
4903 switch (rawEvent->type) {
4904 case EV_KEY:
4905 switch (rawEvent->scanCode) {
4906 case BTN_TOUCH:
4907 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
4908 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07004909 // Don't sync immediately. Wait until the next SYN_REPORT since we might
4910 // not have received valid position information yet. This logic assumes that
4911 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07004912 break;
Jeff Brown96ad3972011-03-09 17:39:48 -08004913 default:
4914 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
4915 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
4916 if (buttonState) {
4917 if (rawEvent->value) {
4918 mAccumulator.buttonDown |= buttonState;
4919 } else {
4920 mAccumulator.buttonUp |= buttonState;
4921 }
4922 mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
4923 }
4924 }
4925 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004926 }
4927 break;
4928
4929 case EV_ABS:
4930 switch (rawEvent->scanCode) {
4931 case ABS_X:
4932 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
4933 mAccumulator.absX = rawEvent->value;
4934 break;
4935 case ABS_Y:
4936 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
4937 mAccumulator.absY = rawEvent->value;
4938 break;
4939 case ABS_PRESSURE:
4940 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
4941 mAccumulator.absPressure = rawEvent->value;
4942 break;
4943 case ABS_TOOL_WIDTH:
4944 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
4945 mAccumulator.absToolWidth = rawEvent->value;
4946 break;
4947 }
4948 break;
4949
4950 case EV_SYN:
4951 switch (rawEvent->scanCode) {
4952 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07004953 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004954 break;
4955 }
4956 break;
4957 }
4958}
4959
4960void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004961 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07004962 if (fields == 0) {
4963 return; // no new state changes, so nothing to do
4964 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07004965
4966 if (fields & Accumulator::FIELD_BTN_TOUCH) {
4967 mDown = mAccumulator.btnTouch;
4968 }
4969
4970 if (fields & Accumulator::FIELD_ABS_X) {
4971 mX = mAccumulator.absX;
4972 }
4973
4974 if (fields & Accumulator::FIELD_ABS_Y) {
4975 mY = mAccumulator.absY;
4976 }
4977
4978 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
4979 mPressure = mAccumulator.absPressure;
4980 }
4981
4982 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07004983 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004984 }
4985
Jeff Brown96ad3972011-03-09 17:39:48 -08004986 if (fields & Accumulator::FIELD_BUTTONS) {
4987 mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
4988 }
4989
Jeff Brown6d0fec22010-07-23 21:28:06 -07004990 mCurrentTouch.clear();
4991
4992 if (mDown) {
4993 mCurrentTouch.pointerCount = 1;
4994 mCurrentTouch.pointers[0].id = 0;
4995 mCurrentTouch.pointers[0].x = mX;
4996 mCurrentTouch.pointers[0].y = mY;
4997 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07004998 mCurrentTouch.pointers[0].touchMajor = 0;
4999 mCurrentTouch.pointers[0].touchMinor = 0;
5000 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
5001 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005002 mCurrentTouch.pointers[0].orientation = 0;
5003 mCurrentTouch.idToIndex[0] = 0;
5004 mCurrentTouch.idBits.markBit(0);
Jeff Brown96ad3972011-03-09 17:39:48 -08005005 mCurrentTouch.buttonState = mButtonState;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005006 }
5007
5008 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005009
5010 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005011}
5012
Jeff Brown8d608662010-08-30 03:02:23 -07005013void SingleTouchInputMapper::configureRawAxes() {
5014 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005015
Jeff Brown8d608662010-08-30 03:02:23 -07005016 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
5017 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
5018 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
5019 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005020}
5021
5022
5023// --- MultiTouchInputMapper ---
5024
Jeff Brown47e6b1b2010-11-29 17:37:49 -08005025MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
5026 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005027 initialize();
5028}
5029
5030MultiTouchInputMapper::~MultiTouchInputMapper() {
5031}
5032
5033void MultiTouchInputMapper::initialize() {
5034 mAccumulator.clear();
Jeff Brown96ad3972011-03-09 17:39:48 -08005035 mButtonState = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005036}
5037
5038void MultiTouchInputMapper::reset() {
5039 TouchInputMapper::reset();
5040
Jeff Brown6d0fec22010-07-23 21:28:06 -07005041 initialize();
5042}
5043
5044void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
5045 switch (rawEvent->type) {
Jeff Brown96ad3972011-03-09 17:39:48 -08005046 case EV_KEY: {
5047 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
5048 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
5049 if (buttonState) {
5050 if (rawEvent->value) {
5051 mAccumulator.buttonDown |= buttonState;
5052 } else {
5053 mAccumulator.buttonUp |= buttonState;
5054 }
5055 }
5056 }
5057 break;
5058 }
5059
Jeff Brown6d0fec22010-07-23 21:28:06 -07005060 case EV_ABS: {
5061 uint32_t pointerIndex = mAccumulator.pointerCount;
5062 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
5063
5064 switch (rawEvent->scanCode) {
5065 case ABS_MT_POSITION_X:
5066 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
5067 pointer->absMTPositionX = rawEvent->value;
5068 break;
5069 case ABS_MT_POSITION_Y:
5070 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
5071 pointer->absMTPositionY = rawEvent->value;
5072 break;
5073 case ABS_MT_TOUCH_MAJOR:
5074 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
5075 pointer->absMTTouchMajor = rawEvent->value;
5076 break;
5077 case ABS_MT_TOUCH_MINOR:
5078 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
5079 pointer->absMTTouchMinor = rawEvent->value;
5080 break;
5081 case ABS_MT_WIDTH_MAJOR:
5082 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
5083 pointer->absMTWidthMajor = rawEvent->value;
5084 break;
5085 case ABS_MT_WIDTH_MINOR:
5086 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
5087 pointer->absMTWidthMinor = rawEvent->value;
5088 break;
5089 case ABS_MT_ORIENTATION:
5090 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
5091 pointer->absMTOrientation = rawEvent->value;
5092 break;
5093 case ABS_MT_TRACKING_ID:
5094 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
5095 pointer->absMTTrackingId = rawEvent->value;
5096 break;
Jeff Brown8d608662010-08-30 03:02:23 -07005097 case ABS_MT_PRESSURE:
5098 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
5099 pointer->absMTPressure = rawEvent->value;
5100 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005101 }
5102 break;
5103 }
5104
5105 case EV_SYN:
5106 switch (rawEvent->scanCode) {
5107 case SYN_MT_REPORT: {
5108 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
5109 uint32_t pointerIndex = mAccumulator.pointerCount;
5110
5111 if (mAccumulator.pointers[pointerIndex].fields) {
5112 if (pointerIndex == MAX_POINTERS) {
5113 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
5114 MAX_POINTERS);
5115 } else {
5116 pointerIndex += 1;
5117 mAccumulator.pointerCount = pointerIndex;
5118 }
5119 }
5120
5121 mAccumulator.pointers[pointerIndex].clear();
5122 break;
5123 }
5124
5125 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005126 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005127 break;
5128 }
5129 break;
5130 }
5131}
5132
5133void MultiTouchInputMapper::sync(nsecs_t when) {
5134 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07005135 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005136
Jeff Brown6d0fec22010-07-23 21:28:06 -07005137 uint32_t inCount = mAccumulator.pointerCount;
5138 uint32_t outCount = 0;
5139 bool havePointerIds = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005140
Jeff Brown6d0fec22010-07-23 21:28:06 -07005141 mCurrentTouch.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07005142
Jeff Brown6d0fec22010-07-23 21:28:06 -07005143 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005144 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
5145 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005146
Jeff Brown6d0fec22010-07-23 21:28:06 -07005147 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005148 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
5149 // Drop this finger.
Jeff Brown46b9ac02010-04-22 18:58:52 -07005150 continue;
5151 }
5152
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005153 PointerData& outPointer = mCurrentTouch.pointers[outCount];
5154 outPointer.x = inPointer.absMTPositionX;
5155 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005156
Jeff Brown8d608662010-08-30 03:02:23 -07005157 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
5158 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07005159 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
5160 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005161 continue;
5162 }
Jeff Brown8d608662010-08-30 03:02:23 -07005163 outPointer.pressure = inPointer.absMTPressure;
5164 } else {
5165 // Default pressure to 0 if absent.
5166 outPointer.pressure = 0;
5167 }
5168
5169 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
5170 if (inPointer.absMTTouchMajor <= 0) {
5171 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
5172 // a pointer going up. Drop this finger.
5173 continue;
5174 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005175 outPointer.touchMajor = inPointer.absMTTouchMajor;
5176 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005177 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005178 outPointer.touchMajor = 0;
5179 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07005180
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005181 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
5182 outPointer.touchMinor = inPointer.absMTTouchMinor;
5183 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005184 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005185 outPointer.touchMinor = outPointer.touchMajor;
5186 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07005187
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005188 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
5189 outPointer.toolMajor = inPointer.absMTWidthMajor;
5190 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005191 // Default tool area to 0 if absent.
5192 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005193 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07005194
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005195 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
5196 outPointer.toolMinor = inPointer.absMTWidthMinor;
5197 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005198 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005199 outPointer.toolMinor = outPointer.toolMajor;
5200 }
5201
5202 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
5203 outPointer.orientation = inPointer.absMTOrientation;
5204 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005205 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005206 outPointer.orientation = 0;
5207 }
5208
Jeff Brown8d608662010-08-30 03:02:23 -07005209 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07005210 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005211 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
5212 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac02010-04-22 18:58:52 -07005213
Jeff Brown6d0fec22010-07-23 21:28:06 -07005214 if (id > MAX_POINTER_ID) {
5215#if DEBUG_POINTERS
5216 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07005217 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07005218 id, MAX_POINTER_ID);
5219#endif
5220 havePointerIds = false;
5221 }
5222 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005223 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005224 mCurrentTouch.idToIndex[id] = outCount;
5225 mCurrentTouch.idBits.markBit(id);
5226 }
5227 } else {
5228 havePointerIds = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005229 }
5230 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07005231
Jeff Brown6d0fec22010-07-23 21:28:06 -07005232 outCount += 1;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005233 }
5234
Jeff Brown6d0fec22010-07-23 21:28:06 -07005235 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac02010-04-22 18:58:52 -07005236
Jeff Brown96ad3972011-03-09 17:39:48 -08005237 mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
5238 mCurrentTouch.buttonState = mButtonState;
5239
Jeff Brown6d0fec22010-07-23 21:28:06 -07005240 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005241
5242 mAccumulator.clear();
Jeff Brown46b9ac02010-04-22 18:58:52 -07005243}
5244
Jeff Brown8d608662010-08-30 03:02:23 -07005245void MultiTouchInputMapper::configureRawAxes() {
5246 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac02010-04-22 18:58:52 -07005247
Jeff Brown8d608662010-08-30 03:02:23 -07005248 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, & mRawAxes.x);
5249 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, & mRawAxes.y);
5250 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, & mRawAxes.touchMajor);
5251 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, & mRawAxes.touchMinor);
5252 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, & mRawAxes.toolMajor);
5253 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, & mRawAxes.toolMinor);
5254 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, & mRawAxes.orientation);
5255 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, & mRawAxes.pressure);
Jeff Brown9c3cda02010-06-15 01:31:58 -07005256}
5257
Jeff Brown46b9ac02010-04-22 18:58:52 -07005258
Jeff Browncb1404e2011-01-15 18:14:15 -08005259// --- JoystickInputMapper ---
5260
5261JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5262 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08005263}
5264
5265JoystickInputMapper::~JoystickInputMapper() {
5266}
5267
5268uint32_t JoystickInputMapper::getSources() {
5269 return AINPUT_SOURCE_JOYSTICK;
5270}
5271
5272void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5273 InputMapper::populateDeviceInfo(info);
5274
Jeff Brown6f2fba42011-02-19 01:08:02 -08005275 for (size_t i = 0; i < mAxes.size(); i++) {
5276 const Axis& axis = mAxes.valueAt(i);
Jeff Brownefd32662011-03-08 15:13:06 -08005277 info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5278 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005279 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
Jeff Brownefd32662011-03-08 15:13:06 -08005280 info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5281 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005282 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005283 }
5284}
5285
5286void JoystickInputMapper::dump(String8& dump) {
5287 dump.append(INDENT2 "Joystick Input Mapper:\n");
5288
Jeff Brown6f2fba42011-02-19 01:08:02 -08005289 dump.append(INDENT3 "Axes:\n");
5290 size_t numAxes = mAxes.size();
5291 for (size_t i = 0; i < numAxes; i++) {
5292 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005293 const char* label = getAxisLabel(axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005294 if (label) {
Jeff Brown85297452011-03-04 13:07:49 -08005295 dump.appendFormat(INDENT4 "%s", label);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005296 } else {
Jeff Brown85297452011-03-04 13:07:49 -08005297 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005298 }
Jeff Brown85297452011-03-04 13:07:49 -08005299 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5300 label = getAxisLabel(axis.axisInfo.highAxis);
5301 if (label) {
5302 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5303 } else {
5304 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5305 axis.axisInfo.splitValue);
5306 }
5307 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5308 dump.append(" (invert)");
5309 }
5310
5311 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5312 axis.min, axis.max, axis.flat, axis.fuzz);
5313 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
5314 "highScale=%0.5f, highOffset=%0.5f\n",
5315 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005316 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
5317 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
5318 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08005319 }
5320}
5321
5322void JoystickInputMapper::configure() {
5323 InputMapper::configure();
5324
Jeff Brown6f2fba42011-02-19 01:08:02 -08005325 // Collect all axes.
5326 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
5327 RawAbsoluteAxisInfo rawAxisInfo;
5328 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
5329 if (rawAxisInfo.valid) {
Jeff Brown85297452011-03-04 13:07:49 -08005330 // Map axis.
5331 AxisInfo axisInfo;
5332 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005333 if (!explicitlyMapped) {
5334 // Axis is not explicitly mapped, will choose a generic axis later.
Jeff Brown85297452011-03-04 13:07:49 -08005335 axisInfo.mode = AxisInfo::MODE_NORMAL;
5336 axisInfo.axis = -1;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005337 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005338
Jeff Brown85297452011-03-04 13:07:49 -08005339 // Apply flat override.
5340 int32_t rawFlat = axisInfo.flatOverride < 0
5341 ? rawAxisInfo.flat : axisInfo.flatOverride;
5342
5343 // Calculate scaling factors and limits.
Jeff Brown6f2fba42011-02-19 01:08:02 -08005344 Axis axis;
Jeff Brown85297452011-03-04 13:07:49 -08005345 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5346 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5347 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5348 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5349 scale, 0.0f, highScale, 0.0f,
5350 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5351 } else if (isCenteredAxis(axisInfo.axis)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005352 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5353 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
Jeff Brown85297452011-03-04 13:07:49 -08005354 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5355 scale, offset, scale, offset,
5356 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005357 } else {
5358 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
Jeff Brown85297452011-03-04 13:07:49 -08005359 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5360 scale, 0.0f, scale, 0.0f,
5361 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005362 }
5363
5364 // To eliminate noise while the joystick is at rest, filter out small variations
5365 // in axis values up front.
5366 axis.filter = axis.flat * 0.25f;
5367
5368 mAxes.add(abs, axis);
5369 }
5370 }
5371
5372 // If there are too many axes, start dropping them.
5373 // Prefer to keep explicitly mapped axes.
5374 if (mAxes.size() > PointerCoords::MAX_AXES) {
5375 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
5376 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5377 pruneAxes(true);
5378 pruneAxes(false);
5379 }
5380
5381 // Assign generic axis ids to remaining axes.
5382 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5383 size_t numAxes = mAxes.size();
5384 for (size_t i = 0; i < numAxes; i++) {
5385 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005386 if (axis.axisInfo.axis < 0) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005387 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5388 && haveAxis(nextGenericAxisId)) {
5389 nextGenericAxisId += 1;
5390 }
5391
5392 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
Jeff Brown85297452011-03-04 13:07:49 -08005393 axis.axisInfo.axis = nextGenericAxisId;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005394 nextGenericAxisId += 1;
5395 } else {
5396 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
5397 "have already been assigned to other axes.",
5398 getDeviceName().string(), mAxes.keyAt(i));
5399 mAxes.removeItemsAt(i--);
5400 numAxes -= 1;
5401 }
5402 }
5403 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005404}
5405
Jeff Brown85297452011-03-04 13:07:49 -08005406bool JoystickInputMapper::haveAxis(int32_t axisId) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005407 size_t numAxes = mAxes.size();
5408 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005409 const Axis& axis = mAxes.valueAt(i);
5410 if (axis.axisInfo.axis == axisId
5411 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5412 && axis.axisInfo.highAxis == axisId)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005413 return true;
5414 }
5415 }
5416 return false;
5417}
Jeff Browncb1404e2011-01-15 18:14:15 -08005418
Jeff Brown6f2fba42011-02-19 01:08:02 -08005419void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5420 size_t i = mAxes.size();
5421 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5422 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5423 continue;
5424 }
5425 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
5426 getDeviceName().string(), mAxes.keyAt(i));
5427 mAxes.removeItemsAt(i);
5428 }
5429}
5430
5431bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5432 switch (axis) {
5433 case AMOTION_EVENT_AXIS_X:
5434 case AMOTION_EVENT_AXIS_Y:
5435 case AMOTION_EVENT_AXIS_Z:
5436 case AMOTION_EVENT_AXIS_RX:
5437 case AMOTION_EVENT_AXIS_RY:
5438 case AMOTION_EVENT_AXIS_RZ:
5439 case AMOTION_EVENT_AXIS_HAT_X:
5440 case AMOTION_EVENT_AXIS_HAT_Y:
5441 case AMOTION_EVENT_AXIS_ORIENTATION:
Jeff Brown85297452011-03-04 13:07:49 -08005442 case AMOTION_EVENT_AXIS_RUDDER:
5443 case AMOTION_EVENT_AXIS_WHEEL:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005444 return true;
5445 default:
5446 return false;
5447 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005448}
5449
5450void JoystickInputMapper::reset() {
5451 // Recenter all axes.
5452 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08005453
Jeff Brown6f2fba42011-02-19 01:08:02 -08005454 size_t numAxes = mAxes.size();
5455 for (size_t i = 0; i < numAxes; i++) {
5456 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005457 axis.resetValue();
Jeff Brown6f2fba42011-02-19 01:08:02 -08005458 }
5459
5460 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005461
5462 InputMapper::reset();
5463}
5464
5465void JoystickInputMapper::process(const RawEvent* rawEvent) {
5466 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005467 case EV_ABS: {
5468 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5469 if (index >= 0) {
5470 Axis& axis = mAxes.editValueAt(index);
Jeff Brown85297452011-03-04 13:07:49 -08005471 float newValue, highNewValue;
5472 switch (axis.axisInfo.mode) {
5473 case AxisInfo::MODE_INVERT:
5474 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5475 * axis.scale + axis.offset;
5476 highNewValue = 0.0f;
5477 break;
5478 case AxisInfo::MODE_SPLIT:
5479 if (rawEvent->value < axis.axisInfo.splitValue) {
5480 newValue = (axis.axisInfo.splitValue - rawEvent->value)
5481 * axis.scale + axis.offset;
5482 highNewValue = 0.0f;
5483 } else if (rawEvent->value > axis.axisInfo.splitValue) {
5484 newValue = 0.0f;
5485 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5486 * axis.highScale + axis.highOffset;
5487 } else {
5488 newValue = 0.0f;
5489 highNewValue = 0.0f;
5490 }
5491 break;
5492 default:
5493 newValue = rawEvent->value * axis.scale + axis.offset;
5494 highNewValue = 0.0f;
5495 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005496 }
Jeff Brown85297452011-03-04 13:07:49 -08005497 axis.newValue = newValue;
5498 axis.highNewValue = highNewValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08005499 }
5500 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005501 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005502
5503 case EV_SYN:
5504 switch (rawEvent->scanCode) {
5505 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005506 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005507 break;
5508 }
5509 break;
5510 }
5511}
5512
Jeff Brown6f2fba42011-02-19 01:08:02 -08005513void JoystickInputMapper::sync(nsecs_t when, bool force) {
Jeff Brown85297452011-03-04 13:07:49 -08005514 if (!filterAxes(force)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005515 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08005516 }
5517
5518 int32_t metaState = mContext->getGlobalMetaState();
5519
Jeff Brown6f2fba42011-02-19 01:08:02 -08005520 PointerCoords pointerCoords;
5521 pointerCoords.clear();
5522
5523 size_t numAxes = mAxes.size();
5524 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005525 const Axis& axis = mAxes.valueAt(i);
5526 pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5527 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5528 pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5529 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005530 }
5531
Jeff Brown56194eb2011-03-02 19:23:13 -08005532 // Moving a joystick axis should not wake the devide because joysticks can
5533 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
5534 // button will likely wake the device.
5535 // TODO: Use the input device configuration to control this behavior more finely.
5536 uint32_t policyFlags = 0;
5537
Jeff Brown6f2fba42011-02-19 01:08:02 -08005538 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08005539 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brown6f2fba42011-02-19 01:08:02 -08005540 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
5541 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08005542}
5543
Jeff Brown85297452011-03-04 13:07:49 -08005544bool JoystickInputMapper::filterAxes(bool force) {
5545 bool atLeastOneSignificantChange = force;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005546 size_t numAxes = mAxes.size();
5547 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005548 Axis& axis = mAxes.editValueAt(i);
5549 if (force || hasValueChangedSignificantly(axis.filter,
5550 axis.newValue, axis.currentValue, axis.min, axis.max)) {
5551 axis.currentValue = axis.newValue;
5552 atLeastOneSignificantChange = true;
5553 }
5554 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5555 if (force || hasValueChangedSignificantly(axis.filter,
5556 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
5557 axis.highCurrentValue = axis.highNewValue;
5558 atLeastOneSignificantChange = true;
5559 }
5560 }
5561 }
5562 return atLeastOneSignificantChange;
5563}
5564
5565bool JoystickInputMapper::hasValueChangedSignificantly(
5566 float filter, float newValue, float currentValue, float min, float max) {
5567 if (newValue != currentValue) {
5568 // Filter out small changes in value unless the value is converging on the axis
5569 // bounds or center point. This is intended to reduce the amount of information
5570 // sent to applications by particularly noisy joysticks (such as PS3).
5571 if (fabs(newValue - currentValue) > filter
5572 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
5573 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
5574 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
5575 return true;
5576 }
5577 }
5578 return false;
5579}
5580
5581bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
5582 float filter, float newValue, float currentValue, float thresholdValue) {
5583 float newDistance = fabs(newValue - thresholdValue);
5584 if (newDistance < filter) {
5585 float oldDistance = fabs(currentValue - thresholdValue);
5586 if (newDistance < oldDistance) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005587 return true;
5588 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005589 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005590 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08005591}
5592
Jeff Brown46b9ac02010-04-22 18:58:52 -07005593} // namespace android