blob: 9d69c6071e644f3ccad9581bc06b445e3a5d2c7c [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown9f2106f2011-05-24 14:40:35 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brownace13b12011-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 Brown46b9ac0a2010-04-22 18:58:52 -070041#include <cutils/log.h>
Jeff Brown6b53e8d2010-11-10 16:03:06 -080042#include <ui/Keyboard.h>
Jeff Brown90655042010-12-02 13:50:46 -080043#include <ui/VirtualKeyMap.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070044
45#include <stddef.h>
Jeff Brown8d608662010-08-30 03:02:23 -070046#include <stdlib.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070047#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070048#include <errno.h>
49#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070050#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070051
Jeff Brown8d608662010-08-30 03:02:23 -070052#define INDENT " "
Jeff Brownef3d7e82010-09-30 14:33:04 -070053#define INDENT2 " "
54#define INDENT3 " "
55#define INDENT4 " "
Jeff Brownaba321a2011-06-28 20:34:40 -070056#define INDENT5 " "
Jeff Brown8d608662010-08-30 03:02:23 -070057
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070058namespace android {
59
Jeff Brownace13b12011-03-09 17:39:48 -080060// --- Constants ---
61
Jeff Brown80fd47c2011-05-24 01:07:44 -070062// Maximum number of slots supported when using the slot-based Multitouch Protocol B.
63static const size_t MAX_SLOTS = 32;
64
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070065// --- Static Functions ---
66
67template<typename T>
68inline static T abs(const T& value) {
69 return value < 0 ? - value : value;
70}
71
72template<typename T>
73inline static T min(const T& a, const T& b) {
74 return a < b ? a : b;
75}
76
Jeff Brown5c225b12010-06-16 01:53:36 -070077template<typename T>
78inline static void swap(T& a, T& b) {
79 T temp = a;
80 a = b;
81 b = temp;
82}
83
Jeff Brown8d608662010-08-30 03:02:23 -070084inline static float avg(float x, float y) {
85 return (x + y) / 2;
86}
87
Jeff Brown2352b972011-04-12 22:39:53 -070088inline static float distance(float x1, float y1, float x2, float y2) {
89 return hypotf(x1 - x2, y1 - y2);
Jeff Brownace13b12011-03-09 17:39:48 -080090}
91
Jeff Brown517bb4c2011-01-14 19:09:23 -080092inline static int32_t signExtendNybble(int32_t value) {
93 return value >= 8 ? value - 16 : value;
94}
95
Jeff Brownef3d7e82010-09-30 14:33:04 -070096static inline const char* toString(bool value) {
97 return value ? "true" : "false";
98}
99
Jeff Brown9626b142011-03-03 02:09:54 -0800100static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
101 const int32_t map[][4], size_t mapSize) {
102 if (orientation != DISPLAY_ORIENTATION_0) {
103 for (size_t i = 0; i < mapSize; i++) {
104 if (value == map[i][0]) {
105 return map[i][orientation];
106 }
107 }
108 }
109 return value;
110}
111
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700112static const int32_t keyCodeRotationMap[][4] = {
113 // key codes enumerated counter-clockwise with the original (unrotated) key first
114 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -0700115 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
116 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
117 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
118 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700119};
Jeff Brown9626b142011-03-03 02:09:54 -0800120static const size_t keyCodeRotationMapSize =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700121 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
122
Jeff Brown60691392011-07-15 19:08:26 -0700123static int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9626b142011-03-03 02:09:54 -0800124 return rotateValueUsingRotationMap(keyCode, orientation,
125 keyCodeRotationMap, keyCodeRotationMapSize);
126}
127
Jeff Brown612891e2011-07-15 20:44:17 -0700128static void rotateDelta(int32_t orientation, float* deltaX, float* deltaY) {
129 float temp;
130 switch (orientation) {
131 case DISPLAY_ORIENTATION_90:
132 temp = *deltaX;
133 *deltaX = *deltaY;
134 *deltaY = -temp;
135 break;
136
137 case DISPLAY_ORIENTATION_180:
138 *deltaX = -*deltaX;
139 *deltaY = -*deltaY;
140 break;
141
142 case DISPLAY_ORIENTATION_270:
143 temp = *deltaX;
144 *deltaX = -*deltaY;
145 *deltaY = temp;
146 break;
147 }
148}
149
Jeff Brown6d0fec22010-07-23 21:28:06 -0700150static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
151 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
152}
153
Jeff Brownefd32662011-03-08 15:13:06 -0800154// Returns true if the pointer should be reported as being down given the specified
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700155// button states. This determines whether the event is reported as a touch event.
156static bool isPointerDown(int32_t buttonState) {
157 return buttonState &
158 (AMOTION_EVENT_BUTTON_PRIMARY | AMOTION_EVENT_BUTTON_SECONDARY
Jeff Brown53ca3f12011-06-27 18:36:00 -0700159 | AMOTION_EVENT_BUTTON_TERTIARY);
Jeff Brownefd32662011-03-08 15:13:06 -0800160}
161
Jeff Brown2352b972011-04-12 22:39:53 -0700162static float calculateCommonVector(float a, float b) {
163 if (a > 0 && b > 0) {
164 return a < b ? a : b;
165 } else if (a < 0 && b < 0) {
166 return a > b ? a : b;
167 } else {
168 return 0;
169 }
170}
171
Jeff Brownfe9f8ab2011-05-06 18:20:01 -0700172static void synthesizeButtonKey(InputReaderContext* context, int32_t action,
173 nsecs_t when, int32_t deviceId, uint32_t source,
174 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState,
175 int32_t buttonState, int32_t keyCode) {
176 if (
177 (action == AKEY_EVENT_ACTION_DOWN
178 && !(lastButtonState & buttonState)
179 && (currentButtonState & buttonState))
180 || (action == AKEY_EVENT_ACTION_UP
181 && (lastButtonState & buttonState)
182 && !(currentButtonState & buttonState))) {
183 context->getDispatcher()->notifyKey(when, deviceId, source, policyFlags,
184 action, 0, keyCode, 0, context->getGlobalMetaState(), when);
185 }
186}
187
188static void synthesizeButtonKeys(InputReaderContext* context, int32_t action,
189 nsecs_t when, int32_t deviceId, uint32_t source,
190 uint32_t policyFlags, int32_t lastButtonState, int32_t currentButtonState) {
191 synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
192 lastButtonState, currentButtonState,
193 AMOTION_EVENT_BUTTON_BACK, AKEYCODE_BACK);
194 synthesizeButtonKey(context, action, when, deviceId, source, policyFlags,
195 lastButtonState, currentButtonState,
196 AMOTION_EVENT_BUTTON_FORWARD, AKEYCODE_FORWARD);
197}
198
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700199
Jeff Brown46b9ac0a2010-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 Brown46b9ac0a2010-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),
Jeff Brown474dcb52011-06-14 20:22:50 -0700207 mConfigurationChangesToRefresh(0) {
208 refreshConfiguration(0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700209 updateGlobalMetaState();
210 updateInputConfiguration();
Jeff Brown46b9ac0a2010-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 Brown474dcb52011-06-14 20:22:50 -0700220 uint32_t changes;
221 { // acquire lock
222 AutoMutex _l(mStateLock);
223
224 changes = mConfigurationChangesToRefresh;
225 mConfigurationChangesToRefresh = 0;
226 } // release lock
227
228 if (changes) {
229 refreshConfiguration(changes);
Jeff Brown1a84fd12011-06-02 01:26:32 -0700230 }
231
Jeff Brownaa3855d2011-03-17 01:34:19 -0700232 int32_t timeoutMillis = -1;
233 if (mNextTimeout != LLONG_MAX) {
234 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
235 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
236 }
237
Jeff Brownb7198742011-03-18 18:14:26 -0700238 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
239 if (count) {
240 processEvents(mEventBuffer, count);
241 }
242 if (!count || timeoutMillis == 0) {
Jeff Brownaa3855d2011-03-17 01:34:19 -0700243 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
244#if DEBUG_RAW_EVENTS
245 LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
246#endif
247 mNextTimeout = LLONG_MAX;
248 timeoutExpired(now);
249 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700250}
251
Jeff Brownb7198742011-03-18 18:14:26 -0700252void InputReader::processEvents(const RawEvent* rawEvents, size_t count) {
253 for (const RawEvent* rawEvent = rawEvents; count;) {
254 int32_t type = rawEvent->type;
255 size_t batchSize = 1;
256 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
257 int32_t deviceId = rawEvent->deviceId;
258 while (batchSize < count) {
259 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
260 || rawEvent[batchSize].deviceId != deviceId) {
261 break;
262 }
263 batchSize += 1;
264 }
265#if DEBUG_RAW_EVENTS
266 LOGD("BatchSize: %d Count: %d", batchSize, count);
267#endif
268 processEventsForDevice(deviceId, rawEvent, batchSize);
269 } else {
270 switch (rawEvent->type) {
271 case EventHubInterface::DEVICE_ADDED:
272 addDevice(rawEvent->deviceId);
273 break;
274 case EventHubInterface::DEVICE_REMOVED:
275 removeDevice(rawEvent->deviceId);
276 break;
277 case EventHubInterface::FINISHED_DEVICE_SCAN:
278 handleConfigurationChanged(rawEvent->when);
279 break;
280 default:
Jeff Brownb6110c22011-04-01 16:15:13 -0700281 LOG_ASSERT(false); // can't happen
Jeff Brownb7198742011-03-18 18:14:26 -0700282 break;
283 }
284 }
285 count -= batchSize;
286 rawEvent += batchSize;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700287 }
288}
289
Jeff Brown7342bb92010-10-01 18:55:43 -0700290void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700291 String8 name = mEventHub->getDeviceName(deviceId);
292 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
293
294 InputDevice* device = createDevice(deviceId, name, classes);
Jeff Brown474dcb52011-06-14 20:22:50 -0700295 device->configure(&mConfig, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700296
Jeff Brown8d608662010-08-30 03:02:23 -0700297 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800298 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700299 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800300 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700301 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700302 }
303
Jeff Brown6d0fec22010-07-23 21:28:06 -0700304 bool added = false;
305 { // acquire device registry writer lock
306 RWLock::AutoWLock _wl(mDeviceRegistryLock);
307
308 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
309 if (deviceIndex < 0) {
310 mDevices.add(deviceId, device);
311 added = true;
312 }
313 } // release device registry writer lock
314
315 if (! added) {
316 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
317 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700318 return;
319 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700320}
321
Jeff Brown7342bb92010-10-01 18:55:43 -0700322void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700323 bool removed = false;
324 InputDevice* device = NULL;
325 { // acquire device registry writer lock
326 RWLock::AutoWLock _wl(mDeviceRegistryLock);
327
328 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
329 if (deviceIndex >= 0) {
330 device = mDevices.valueAt(deviceIndex);
331 mDevices.removeItemsAt(deviceIndex, 1);
332 removed = true;
333 }
334 } // release device registry writer lock
335
336 if (! removed) {
337 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700338 return;
339 }
340
Jeff Brown6d0fec22010-07-23 21:28:06 -0700341 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800342 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700343 device->getId(), device->getName().string());
344 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800345 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700346 device->getId(), device->getName().string(), device->getSources());
347 }
348
Jeff Brown8d608662010-08-30 03:02:23 -0700349 device->reset();
350
Jeff Brown6d0fec22010-07-23 21:28:06 -0700351 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700352}
353
Jeff Brown6d0fec22010-07-23 21:28:06 -0700354InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
355 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700356
Jeff Brown56194eb2011-03-02 19:23:13 -0800357 // External devices.
358 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
359 device->setExternal(true);
360 }
361
Jeff Brown6d0fec22010-07-23 21:28:06 -0700362 // Switch-like devices.
363 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
364 device->addMapper(new SwitchInputMapper(device));
365 }
366
367 // Keyboard-like devices.
Jeff Brownefd32662011-03-08 15:13:06 -0800368 uint32_t keyboardSource = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700369 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
370 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800371 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700372 }
373 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
374 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
375 }
376 if (classes & INPUT_DEVICE_CLASS_DPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800377 keyboardSource |= AINPUT_SOURCE_DPAD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700378 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800379 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800380 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
Jeff Browncb1404e2011-01-15 18:14:15 -0800381 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700382
Jeff Brownefd32662011-03-08 15:13:06 -0800383 if (keyboardSource != 0) {
384 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700385 }
386
Jeff Brown83c09682010-12-23 17:50:18 -0800387 // Cursor-like devices.
388 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
389 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700390 }
391
Jeff Brown58a2da82011-01-25 16:02:22 -0800392 // Touchscreens and touchpad devices.
393 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800394 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800395 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800396 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700397 }
398
Jeff Browncb1404e2011-01-15 18:14:15 -0800399 // Joystick-like devices.
400 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
401 device->addMapper(new JoystickInputMapper(device));
402 }
403
Jeff Brown6d0fec22010-07-23 21:28:06 -0700404 return device;
405}
406
Jeff Brownb7198742011-03-18 18:14:26 -0700407void InputReader::processEventsForDevice(int32_t deviceId,
408 const RawEvent* rawEvents, size_t count) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700409 { // acquire device registry reader lock
410 RWLock::AutoRLock _rl(mDeviceRegistryLock);
411
412 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
413 if (deviceIndex < 0) {
414 LOGW("Discarding event for unknown deviceId %d.", deviceId);
415 return;
416 }
417
418 InputDevice* device = mDevices.valueAt(deviceIndex);
419 if (device->isIgnored()) {
420 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
421 return;
422 }
423
Jeff Brownb7198742011-03-18 18:14:26 -0700424 device->process(rawEvents, count);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700425 } // release device registry reader lock
426}
427
Jeff Brownaa3855d2011-03-17 01:34:19 -0700428void InputReader::timeoutExpired(nsecs_t when) {
429 { // acquire device registry reader lock
430 RWLock::AutoRLock _rl(mDeviceRegistryLock);
431
432 for (size_t i = 0; i < mDevices.size(); i++) {
433 InputDevice* device = mDevices.valueAt(i);
434 if (!device->isIgnored()) {
435 device->timeoutExpired(when);
436 }
437 }
438 } // release device registry reader lock
439}
440
Jeff Brownc3db8582010-10-20 15:33:38 -0700441void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700442 // Reset global meta state because it depends on the list of all configured devices.
443 updateGlobalMetaState();
444
445 // Update input configuration.
446 updateInputConfiguration();
447
448 // Enqueue configuration changed.
449 mDispatcher->notifyConfigurationChanged(when);
450}
451
Jeff Brown474dcb52011-06-14 20:22:50 -0700452void InputReader::refreshConfiguration(uint32_t changes) {
Jeff Brown1a84fd12011-06-02 01:26:32 -0700453 mPolicy->getReaderConfiguration(&mConfig);
454 mEventHub->setExcludedDevices(mConfig.excludedDeviceNames);
455
Jeff Brown474dcb52011-06-14 20:22:50 -0700456 if (changes) {
457 LOGI("Reconfiguring input devices. changes=0x%08x", changes);
458
459 if (changes & InputReaderConfiguration::CHANGE_MUST_REOPEN) {
460 mEventHub->requestReopenDevices();
461 } else {
462 { // acquire device registry reader lock
463 RWLock::AutoRLock _rl(mDeviceRegistryLock);
464
465 for (size_t i = 0; i < mDevices.size(); i++) {
466 InputDevice* device = mDevices.valueAt(i);
467 device->configure(&mConfig, changes);
468 }
469 } // release device registry reader lock
470 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700471 }
472}
473
474void InputReader::updateGlobalMetaState() {
475 { // acquire state lock
476 AutoMutex _l(mStateLock);
477
478 mGlobalMetaState = 0;
479
480 { // acquire device registry reader lock
481 RWLock::AutoRLock _rl(mDeviceRegistryLock);
482
483 for (size_t i = 0; i < mDevices.size(); i++) {
484 InputDevice* device = mDevices.valueAt(i);
485 mGlobalMetaState |= device->getMetaState();
486 }
487 } // release device registry reader lock
488 } // release state lock
489}
490
491int32_t InputReader::getGlobalMetaState() {
492 { // acquire state lock
493 AutoMutex _l(mStateLock);
494
495 return mGlobalMetaState;
496 } // release state lock
497}
498
499void InputReader::updateInputConfiguration() {
500 { // acquire state lock
501 AutoMutex _l(mStateLock);
502
503 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
504 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
505 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
506 { // acquire device registry reader lock
507 RWLock::AutoRLock _rl(mDeviceRegistryLock);
508
509 InputDeviceInfo deviceInfo;
510 for (size_t i = 0; i < mDevices.size(); i++) {
511 InputDevice* device = mDevices.valueAt(i);
512 device->getDeviceInfo(& deviceInfo);
513 uint32_t sources = deviceInfo.getSources();
514
515 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
516 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
517 }
518 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
519 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
520 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
521 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
522 }
523 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
524 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700525 }
526 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700527 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700528
Jeff Brown6d0fec22010-07-23 21:28:06 -0700529 mInputConfiguration.touchScreen = touchScreenConfig;
530 mInputConfiguration.keyboard = keyboardConfig;
531 mInputConfiguration.navigation = navigationConfig;
532 } // release state lock
533}
534
Jeff Brownfe508922011-01-18 15:10:10 -0800535void InputReader::disableVirtualKeysUntil(nsecs_t time) {
536 mDisableVirtualKeysTimeout = time;
537}
538
539bool InputReader::shouldDropVirtualKey(nsecs_t now,
540 InputDevice* device, int32_t keyCode, int32_t scanCode) {
541 if (now < mDisableVirtualKeysTimeout) {
542 LOGI("Dropping virtual key from device %s because virtual keys are "
543 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
544 device->getName().string(),
545 (mDisableVirtualKeysTimeout - now) * 0.000001,
546 keyCode, scanCode);
547 return true;
548 } else {
549 return false;
550 }
551}
552
Jeff Brown05dc66a2011-03-02 14:41:58 -0800553void InputReader::fadePointer() {
554 { // acquire device registry reader lock
555 RWLock::AutoRLock _rl(mDeviceRegistryLock);
556
557 for (size_t i = 0; i < mDevices.size(); i++) {
558 InputDevice* device = mDevices.valueAt(i);
559 device->fadePointer();
560 }
561 } // release device registry reader lock
562}
563
Jeff Brownaa3855d2011-03-17 01:34:19 -0700564void InputReader::requestTimeoutAtTime(nsecs_t when) {
565 if (when < mNextTimeout) {
566 mNextTimeout = when;
567 }
568}
569
Jeff Brown6d0fec22010-07-23 21:28:06 -0700570void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
571 { // acquire state lock
572 AutoMutex _l(mStateLock);
573
574 *outConfiguration = mInputConfiguration;
575 } // release state lock
576}
577
578status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
579 { // acquire device registry reader lock
580 RWLock::AutoRLock _rl(mDeviceRegistryLock);
581
582 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
583 if (deviceIndex < 0) {
584 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700585 }
586
Jeff Brown6d0fec22010-07-23 21:28:06 -0700587 InputDevice* device = mDevices.valueAt(deviceIndex);
588 if (device->isIgnored()) {
589 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700590 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700591
592 device->getDeviceInfo(outDeviceInfo);
593 return OK;
594 } // release device registy reader lock
595}
596
597void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
598 outDeviceIds.clear();
599
600 { // acquire device registry reader lock
601 RWLock::AutoRLock _rl(mDeviceRegistryLock);
602
603 size_t numDevices = mDevices.size();
604 for (size_t i = 0; i < numDevices; i++) {
605 InputDevice* device = mDevices.valueAt(i);
606 if (! device->isIgnored()) {
607 outDeviceIds.add(device->getId());
608 }
609 }
610 } // release device registy reader lock
611}
612
613int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
614 int32_t keyCode) {
615 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
616}
617
618int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
619 int32_t scanCode) {
620 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
621}
622
623int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
624 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
625}
626
627int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
628 GetStateFunc getStateFunc) {
629 { // acquire device registry reader lock
630 RWLock::AutoRLock _rl(mDeviceRegistryLock);
631
632 int32_t result = AKEY_STATE_UNKNOWN;
633 if (deviceId >= 0) {
634 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
635 if (deviceIndex >= 0) {
636 InputDevice* device = mDevices.valueAt(deviceIndex);
637 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
638 result = (device->*getStateFunc)(sourceMask, code);
639 }
640 }
641 } else {
642 size_t numDevices = mDevices.size();
643 for (size_t i = 0; i < numDevices; i++) {
644 InputDevice* device = mDevices.valueAt(i);
645 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
646 result = (device->*getStateFunc)(sourceMask, code);
647 if (result >= AKEY_STATE_DOWN) {
648 return result;
649 }
650 }
651 }
652 }
653 return result;
654 } // release device registy reader lock
655}
656
657bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
658 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
659 memset(outFlags, 0, numCodes);
660 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
661}
662
663bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
664 const int32_t* keyCodes, uint8_t* outFlags) {
665 { // acquire device registry reader lock
666 RWLock::AutoRLock _rl(mDeviceRegistryLock);
667 bool result = false;
668 if (deviceId >= 0) {
669 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
670 if (deviceIndex >= 0) {
671 InputDevice* device = mDevices.valueAt(deviceIndex);
672 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
673 result = device->markSupportedKeyCodes(sourceMask,
674 numCodes, keyCodes, outFlags);
675 }
676 }
677 } else {
678 size_t numDevices = mDevices.size();
679 for (size_t i = 0; i < numDevices; i++) {
680 InputDevice* device = mDevices.valueAt(i);
681 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
682 result |= device->markSupportedKeyCodes(sourceMask,
683 numCodes, keyCodes, outFlags);
684 }
685 }
686 }
687 return result;
688 } // release device registy reader lock
689}
690
Jeff Brown474dcb52011-06-14 20:22:50 -0700691void InputReader::requestRefreshConfiguration(uint32_t changes) {
692 if (changes) {
693 bool needWake;
694 { // acquire lock
695 AutoMutex _l(mStateLock);
Jeff Brown93fa9b32011-06-14 17:09:25 -0700696
Jeff Brown474dcb52011-06-14 20:22:50 -0700697 needWake = !mConfigurationChangesToRefresh;
698 mConfigurationChangesToRefresh |= changes;
699 } // release lock
700
701 if (needWake) {
702 mEventHub->wake();
703 }
704 }
Jeff Brown1a84fd12011-06-02 01:26:32 -0700705}
706
Jeff Brownb88102f2010-09-08 11:49:43 -0700707void InputReader::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -0700708 mEventHub->dump(dump);
709 dump.append("\n");
710
711 dump.append("Input Reader State:\n");
712
Jeff Brownef3d7e82010-09-30 14:33:04 -0700713 { // acquire device registry reader lock
714 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700715
Jeff Brownef3d7e82010-09-30 14:33:04 -0700716 for (size_t i = 0; i < mDevices.size(); i++) {
717 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700718 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700719 } // release device registy reader lock
Jeff Brown214eaf42011-05-26 19:17:02 -0700720
721 dump.append(INDENT "Configuration:\n");
722 dump.append(INDENT2 "ExcludedDeviceNames: [");
723 for (size_t i = 0; i < mConfig.excludedDeviceNames.size(); i++) {
724 if (i != 0) {
725 dump.append(", ");
726 }
727 dump.append(mConfig.excludedDeviceNames.itemAt(i).string());
728 }
729 dump.append("]\n");
Jeff Brown214eaf42011-05-26 19:17:02 -0700730 dump.appendFormat(INDENT2 "VirtualKeyQuietTime: %0.1fms\n",
731 mConfig.virtualKeyQuietTime * 0.000001f);
732
Jeff Brown19c97d462011-06-01 12:33:19 -0700733 dump.appendFormat(INDENT2 "PointerVelocityControlParameters: "
734 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
735 mConfig.pointerVelocityControlParameters.scale,
736 mConfig.pointerVelocityControlParameters.lowThreshold,
737 mConfig.pointerVelocityControlParameters.highThreshold,
738 mConfig.pointerVelocityControlParameters.acceleration);
739
740 dump.appendFormat(INDENT2 "WheelVelocityControlParameters: "
741 "scale=%0.3f, lowThreshold=%0.3f, highThreshold=%0.3f, acceleration=%0.3f\n",
742 mConfig.wheelVelocityControlParameters.scale,
743 mConfig.wheelVelocityControlParameters.lowThreshold,
744 mConfig.wheelVelocityControlParameters.highThreshold,
745 mConfig.wheelVelocityControlParameters.acceleration);
746
Jeff Brown214eaf42011-05-26 19:17:02 -0700747 dump.appendFormat(INDENT2 "PointerGesture:\n");
Jeff Brown474dcb52011-06-14 20:22:50 -0700748 dump.appendFormat(INDENT3 "Enabled: %s\n",
749 toString(mConfig.pointerGesturesEnabled));
Jeff Brown214eaf42011-05-26 19:17:02 -0700750 dump.appendFormat(INDENT3 "QuietInterval: %0.1fms\n",
751 mConfig.pointerGestureQuietInterval * 0.000001f);
752 dump.appendFormat(INDENT3 "DragMinSwitchSpeed: %0.1fpx/s\n",
753 mConfig.pointerGestureDragMinSwitchSpeed);
754 dump.appendFormat(INDENT3 "TapInterval: %0.1fms\n",
755 mConfig.pointerGestureTapInterval * 0.000001f);
756 dump.appendFormat(INDENT3 "TapDragInterval: %0.1fms\n",
757 mConfig.pointerGestureTapDragInterval * 0.000001f);
758 dump.appendFormat(INDENT3 "TapSlop: %0.1fpx\n",
759 mConfig.pointerGestureTapSlop);
760 dump.appendFormat(INDENT3 "MultitouchSettleInterval: %0.1fms\n",
761 mConfig.pointerGestureMultitouchSettleInterval * 0.000001f);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -0700762 dump.appendFormat(INDENT3 "MultitouchMinDistance: %0.1fpx\n",
763 mConfig.pointerGestureMultitouchMinDistance);
Jeff Brown214eaf42011-05-26 19:17:02 -0700764 dump.appendFormat(INDENT3 "SwipeTransitionAngleCosine: %0.1f\n",
765 mConfig.pointerGestureSwipeTransitionAngleCosine);
766 dump.appendFormat(INDENT3 "SwipeMaxWidthRatio: %0.1f\n",
767 mConfig.pointerGestureSwipeMaxWidthRatio);
768 dump.appendFormat(INDENT3 "MovementSpeedRatio: %0.1f\n",
769 mConfig.pointerGestureMovementSpeedRatio);
770 dump.appendFormat(INDENT3 "ZoomSpeedRatio: %0.1f\n",
771 mConfig.pointerGestureZoomSpeedRatio);
Jeff Brownb88102f2010-09-08 11:49:43 -0700772}
773
Jeff Brown6d0fec22010-07-23 21:28:06 -0700774
775// --- InputReaderThread ---
776
777InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
778 Thread(/*canCallJava*/ true), mReader(reader) {
779}
780
781InputReaderThread::~InputReaderThread() {
782}
783
784bool InputReaderThread::threadLoop() {
785 mReader->loopOnce();
786 return true;
787}
788
789
790// --- InputDevice ---
791
792InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
Jeff Brown80fd47c2011-05-24 01:07:44 -0700793 mContext(context), mId(id), mName(name), mSources(0),
794 mIsExternal(false), mDropUntilNextSync(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700795}
796
797InputDevice::~InputDevice() {
798 size_t numMappers = mMappers.size();
799 for (size_t i = 0; i < numMappers; i++) {
800 delete mMappers[i];
801 }
802 mMappers.clear();
803}
804
Jeff Brownef3d7e82010-09-30 14:33:04 -0700805void InputDevice::dump(String8& dump) {
806 InputDeviceInfo deviceInfo;
807 getDeviceInfo(& deviceInfo);
808
Jeff Brown90655042010-12-02 13:50:46 -0800809 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700810 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800811 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700812 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
813 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800814
Jeff Brownefd32662011-03-08 15:13:06 -0800815 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
Jeff Browncc0c1592011-02-19 05:07:28 -0800816 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700817 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800818 for (size_t i = 0; i < ranges.size(); i++) {
Jeff Brownefd32662011-03-08 15:13:06 -0800819 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
820 const char* label = getAxisLabel(range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800821 char name[32];
822 if (label) {
823 strncpy(name, label, sizeof(name));
824 name[sizeof(name) - 1] = '\0';
825 } else {
Jeff Brownefd32662011-03-08 15:13:06 -0800826 snprintf(name, sizeof(name), "%d", range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800827 }
Jeff Brownefd32662011-03-08 15:13:06 -0800828 dump.appendFormat(INDENT3 "%s: source=0x%08x, "
829 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
830 name, range.source, range.min, range.max, range.flat, range.fuzz);
Jeff Browncc0c1592011-02-19 05:07:28 -0800831 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700832 }
833
834 size_t numMappers = mMappers.size();
835 for (size_t i = 0; i < numMappers; i++) {
836 InputMapper* mapper = mMappers[i];
837 mapper->dump(dump);
838 }
839}
840
Jeff Brown6d0fec22010-07-23 21:28:06 -0700841void InputDevice::addMapper(InputMapper* mapper) {
842 mMappers.add(mapper);
843}
844
Jeff Brown474dcb52011-06-14 20:22:50 -0700845void InputDevice::configure(const InputReaderConfiguration* config, uint32_t changes) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700846 mSources = 0;
847
Jeff Brown474dcb52011-06-14 20:22:50 -0700848 if (!isIgnored()) {
849 if (!changes) { // first time only
850 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
851 }
852
853 size_t numMappers = mMappers.size();
854 for (size_t i = 0; i < numMappers; i++) {
855 InputMapper* mapper = mMappers[i];
856 mapper->configure(config, changes);
857 mSources |= mapper->getSources();
858 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700859 }
860}
861
Jeff Brown6d0fec22010-07-23 21:28:06 -0700862void InputDevice::reset() {
863 size_t numMappers = mMappers.size();
864 for (size_t i = 0; i < numMappers; i++) {
865 InputMapper* mapper = mMappers[i];
866 mapper->reset();
867 }
868}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700869
Jeff Brownb7198742011-03-18 18:14:26 -0700870void InputDevice::process(const RawEvent* rawEvents, size_t count) {
871 // Process all of the events in order for each mapper.
872 // We cannot simply ask each mapper to process them in bulk because mappers may
873 // have side-effects that must be interleaved. For example, joystick movement events and
874 // gamepad button presses are handled by different mappers but they should be dispatched
875 // in the order received.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700876 size_t numMappers = mMappers.size();
Jeff Brownb7198742011-03-18 18:14:26 -0700877 for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
878#if DEBUG_RAW_EVENTS
879 LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
Jeff Brown2e45fb62011-06-29 21:19:05 -0700880 "keycode=0x%04x value=0x%08x flags=0x%08x",
Jeff Brownb7198742011-03-18 18:14:26 -0700881 rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
882 rawEvent->value, rawEvent->flags);
883#endif
884
Jeff Brown80fd47c2011-05-24 01:07:44 -0700885 if (mDropUntilNextSync) {
886 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
887 mDropUntilNextSync = false;
888#if DEBUG_RAW_EVENTS
889 LOGD("Recovered from input event buffer overrun.");
890#endif
891 } else {
892#if DEBUG_RAW_EVENTS
893 LOGD("Dropped input event while waiting for next input sync.");
894#endif
895 }
896 } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_DROPPED) {
897 LOGI("Detected input event buffer overrun for device %s.", mName.string());
898 mDropUntilNextSync = true;
899 reset();
900 } else {
901 for (size_t i = 0; i < numMappers; i++) {
902 InputMapper* mapper = mMappers[i];
903 mapper->process(rawEvent);
904 }
Jeff Brownb7198742011-03-18 18:14:26 -0700905 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700906 }
907}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700908
Jeff Brownaa3855d2011-03-17 01:34:19 -0700909void InputDevice::timeoutExpired(nsecs_t when) {
910 size_t numMappers = mMappers.size();
911 for (size_t i = 0; i < numMappers; i++) {
912 InputMapper* mapper = mMappers[i];
913 mapper->timeoutExpired(when);
914 }
915}
916
Jeff Brown6d0fec22010-07-23 21:28:06 -0700917void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
918 outDeviceInfo->initialize(mId, mName);
919
920 size_t numMappers = mMappers.size();
921 for (size_t i = 0; i < numMappers; i++) {
922 InputMapper* mapper = mMappers[i];
923 mapper->populateDeviceInfo(outDeviceInfo);
924 }
925}
926
927int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
928 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
929}
930
931int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
932 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
933}
934
935int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
936 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
937}
938
939int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
940 int32_t result = AKEY_STATE_UNKNOWN;
941 size_t numMappers = mMappers.size();
942 for (size_t i = 0; i < numMappers; i++) {
943 InputMapper* mapper = mMappers[i];
944 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
945 result = (mapper->*getStateFunc)(sourceMask, code);
946 if (result >= AKEY_STATE_DOWN) {
947 return result;
948 }
949 }
950 }
951 return result;
952}
953
954bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
955 const int32_t* keyCodes, uint8_t* outFlags) {
956 bool result = false;
957 size_t numMappers = mMappers.size();
958 for (size_t i = 0; i < numMappers; i++) {
959 InputMapper* mapper = mMappers[i];
960 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
961 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
962 }
963 }
964 return result;
965}
966
967int32_t InputDevice::getMetaState() {
968 int32_t result = 0;
969 size_t numMappers = mMappers.size();
970 for (size_t i = 0; i < numMappers; i++) {
971 InputMapper* mapper = mMappers[i];
972 result |= mapper->getMetaState();
973 }
974 return result;
975}
976
Jeff Brown05dc66a2011-03-02 14:41:58 -0800977void InputDevice::fadePointer() {
978 size_t numMappers = mMappers.size();
979 for (size_t i = 0; i < numMappers; i++) {
980 InputMapper* mapper = mMappers[i];
981 mapper->fadePointer();
982 }
983}
984
Jeff Brown6d0fec22010-07-23 21:28:06 -0700985
Jeff Brown49754db2011-07-01 17:37:58 -0700986// --- CursorButtonAccumulator ---
987
988CursorButtonAccumulator::CursorButtonAccumulator() {
989 clearButtons();
990}
991
992void CursorButtonAccumulator::clearButtons() {
993 mBtnLeft = 0;
994 mBtnRight = 0;
995 mBtnMiddle = 0;
996 mBtnBack = 0;
997 mBtnSide = 0;
998 mBtnForward = 0;
999 mBtnExtra = 0;
1000 mBtnTask = 0;
1001}
1002
1003void CursorButtonAccumulator::process(const RawEvent* rawEvent) {
1004 if (rawEvent->type == EV_KEY) {
1005 switch (rawEvent->scanCode) {
1006 case BTN_LEFT:
1007 mBtnLeft = rawEvent->value;
1008 break;
1009 case BTN_RIGHT:
1010 mBtnRight = rawEvent->value;
1011 break;
1012 case BTN_MIDDLE:
1013 mBtnMiddle = rawEvent->value;
1014 break;
1015 case BTN_BACK:
1016 mBtnBack = rawEvent->value;
1017 break;
1018 case BTN_SIDE:
1019 mBtnSide = rawEvent->value;
1020 break;
1021 case BTN_FORWARD:
1022 mBtnForward = rawEvent->value;
1023 break;
1024 case BTN_EXTRA:
1025 mBtnExtra = rawEvent->value;
1026 break;
1027 case BTN_TASK:
1028 mBtnTask = rawEvent->value;
1029 break;
1030 }
1031 }
1032}
1033
1034uint32_t CursorButtonAccumulator::getButtonState() const {
1035 uint32_t result = 0;
1036 if (mBtnLeft) {
1037 result |= AMOTION_EVENT_BUTTON_PRIMARY;
1038 }
1039 if (mBtnRight) {
1040 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1041 }
1042 if (mBtnMiddle) {
1043 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1044 }
1045 if (mBtnBack || mBtnSide) {
1046 result |= AMOTION_EVENT_BUTTON_BACK;
1047 }
1048 if (mBtnForward || mBtnExtra) {
1049 result |= AMOTION_EVENT_BUTTON_FORWARD;
1050 }
1051 return result;
1052}
1053
1054
1055// --- CursorMotionAccumulator ---
1056
1057CursorMotionAccumulator::CursorMotionAccumulator() :
1058 mHaveRelWheel(false), mHaveRelHWheel(false) {
1059 clearRelativeAxes();
1060}
1061
1062void CursorMotionAccumulator::configure(InputDevice* device) {
1063 mHaveRelWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_WHEEL);
1064 mHaveRelHWheel = device->getEventHub()->hasRelativeAxis(device->getId(), REL_HWHEEL);
1065}
1066
1067void CursorMotionAccumulator::clearRelativeAxes() {
1068 mRelX = 0;
1069 mRelY = 0;
1070 mRelWheel = 0;
1071 mRelHWheel = 0;
1072}
1073
1074void CursorMotionAccumulator::process(const RawEvent* rawEvent) {
1075 if (rawEvent->type == EV_REL) {
1076 switch (rawEvent->scanCode) {
1077 case REL_X:
1078 mRelX = rawEvent->value;
1079 break;
1080 case REL_Y:
1081 mRelY = rawEvent->value;
1082 break;
1083 case REL_WHEEL:
1084 mRelWheel = rawEvent->value;
1085 break;
1086 case REL_HWHEEL:
1087 mRelHWheel = rawEvent->value;
1088 break;
1089 }
1090 }
1091}
1092
1093
1094// --- TouchButtonAccumulator ---
1095
1096TouchButtonAccumulator::TouchButtonAccumulator() :
1097 mHaveBtnTouch(false) {
1098 clearButtons();
1099}
1100
1101void TouchButtonAccumulator::configure(InputDevice* device) {
1102 mHaveBtnTouch = device->getEventHub()->hasScanCode(device->getId(), BTN_TOUCH);
1103}
1104
1105void TouchButtonAccumulator::clearButtons() {
1106 mBtnTouch = 0;
1107 mBtnStylus = 0;
1108 mBtnStylus2 = 0;
1109 mBtnToolFinger = 0;
1110 mBtnToolPen = 0;
1111 mBtnToolRubber = 0;
1112}
1113
1114void TouchButtonAccumulator::process(const RawEvent* rawEvent) {
1115 if (rawEvent->type == EV_KEY) {
1116 switch (rawEvent->scanCode) {
1117 case BTN_TOUCH:
1118 mBtnTouch = rawEvent->value;
1119 break;
1120 case BTN_STYLUS:
1121 mBtnStylus = rawEvent->value;
1122 break;
1123 case BTN_STYLUS2:
1124 mBtnStylus2 = rawEvent->value;
1125 break;
1126 case BTN_TOOL_FINGER:
1127 mBtnToolFinger = rawEvent->value;
1128 break;
1129 case BTN_TOOL_PEN:
1130 mBtnToolPen = rawEvent->value;
1131 break;
1132 case BTN_TOOL_RUBBER:
1133 mBtnToolRubber = rawEvent->value;
1134 break;
1135 }
1136 }
1137}
1138
1139uint32_t TouchButtonAccumulator::getButtonState() const {
1140 uint32_t result = 0;
1141 if (mBtnStylus) {
1142 result |= AMOTION_EVENT_BUTTON_SECONDARY;
1143 }
1144 if (mBtnStylus2) {
1145 result |= AMOTION_EVENT_BUTTON_TERTIARY;
1146 }
1147 return result;
1148}
1149
1150int32_t TouchButtonAccumulator::getToolType() const {
1151 if (mBtnToolRubber) {
1152 return AMOTION_EVENT_TOOL_TYPE_ERASER;
1153 }
1154 if (mBtnToolPen) {
1155 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1156 }
1157 if (mBtnToolFinger) {
1158 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1159 }
1160 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1161}
1162
1163bool TouchButtonAccumulator::isActive() const {
1164 return mBtnTouch || mBtnToolFinger || mBtnToolPen
1165 || mBtnToolRubber || mBtnStylus || mBtnStylus2;
1166}
1167
1168bool TouchButtonAccumulator::isHovering() const {
1169 return mHaveBtnTouch && !mBtnTouch;
1170}
1171
1172
1173// --- SingleTouchMotionAccumulator ---
1174
1175SingleTouchMotionAccumulator::SingleTouchMotionAccumulator() {
1176 clearAbsoluteAxes();
1177}
1178
1179void SingleTouchMotionAccumulator::clearAbsoluteAxes() {
1180 mAbsX = 0;
1181 mAbsY = 0;
1182 mAbsPressure = 0;
1183 mAbsToolWidth = 0;
1184 mAbsDistance = 0;
1185}
1186
1187void SingleTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1188 if (rawEvent->type == EV_ABS) {
1189 switch (rawEvent->scanCode) {
1190 case ABS_X:
1191 mAbsX = rawEvent->value;
1192 break;
1193 case ABS_Y:
1194 mAbsY = rawEvent->value;
1195 break;
1196 case ABS_PRESSURE:
1197 mAbsPressure = rawEvent->value;
1198 break;
1199 case ABS_TOOL_WIDTH:
1200 mAbsToolWidth = rawEvent->value;
1201 break;
1202 case ABS_DISTANCE:
1203 mAbsDistance = rawEvent->value;
1204 break;
1205 }
1206 }
1207}
1208
1209
1210// --- MultiTouchMotionAccumulator ---
1211
1212MultiTouchMotionAccumulator::MultiTouchMotionAccumulator() :
1213 mCurrentSlot(-1), mSlots(NULL), mSlotCount(0), mUsingSlotsProtocol(false) {
1214}
1215
1216MultiTouchMotionAccumulator::~MultiTouchMotionAccumulator() {
1217 delete[] mSlots;
1218}
1219
1220void MultiTouchMotionAccumulator::configure(size_t slotCount, bool usingSlotsProtocol) {
1221 mSlotCount = slotCount;
1222 mUsingSlotsProtocol = usingSlotsProtocol;
1223
1224 delete[] mSlots;
1225 mSlots = new Slot[slotCount];
1226}
1227
1228void MultiTouchMotionAccumulator::clearSlots(int32_t initialSlot) {
1229 for (size_t i = 0; i < mSlotCount; i++) {
1230 mSlots[i].clearIfInUse();
1231 }
1232 mCurrentSlot = initialSlot;
1233}
1234
1235void MultiTouchMotionAccumulator::process(const RawEvent* rawEvent) {
1236 if (rawEvent->type == EV_ABS) {
1237 bool newSlot = false;
1238 if (mUsingSlotsProtocol) {
1239 if (rawEvent->scanCode == ABS_MT_SLOT) {
1240 mCurrentSlot = rawEvent->value;
1241 newSlot = true;
1242 }
1243 } else if (mCurrentSlot < 0) {
1244 mCurrentSlot = 0;
1245 }
1246
1247 if (mCurrentSlot < 0 || size_t(mCurrentSlot) >= mSlotCount) {
1248#if DEBUG_POINTERS
1249 if (newSlot) {
1250 LOGW("MultiTouch device emitted invalid slot index %d but it "
1251 "should be between 0 and %d; ignoring this slot.",
1252 mCurrentSlot, mSlotCount - 1);
1253 }
1254#endif
1255 } else {
1256 Slot* slot = &mSlots[mCurrentSlot];
1257
1258 switch (rawEvent->scanCode) {
1259 case ABS_MT_POSITION_X:
1260 slot->mInUse = true;
1261 slot->mAbsMTPositionX = rawEvent->value;
1262 break;
1263 case ABS_MT_POSITION_Y:
1264 slot->mInUse = true;
1265 slot->mAbsMTPositionY = rawEvent->value;
1266 break;
1267 case ABS_MT_TOUCH_MAJOR:
1268 slot->mInUse = true;
1269 slot->mAbsMTTouchMajor = rawEvent->value;
1270 break;
1271 case ABS_MT_TOUCH_MINOR:
1272 slot->mInUse = true;
1273 slot->mAbsMTTouchMinor = rawEvent->value;
1274 slot->mHaveAbsMTTouchMinor = true;
1275 break;
1276 case ABS_MT_WIDTH_MAJOR:
1277 slot->mInUse = true;
1278 slot->mAbsMTWidthMajor = rawEvent->value;
1279 break;
1280 case ABS_MT_WIDTH_MINOR:
1281 slot->mInUse = true;
1282 slot->mAbsMTWidthMinor = rawEvent->value;
1283 slot->mHaveAbsMTWidthMinor = true;
1284 break;
1285 case ABS_MT_ORIENTATION:
1286 slot->mInUse = true;
1287 slot->mAbsMTOrientation = rawEvent->value;
1288 break;
1289 case ABS_MT_TRACKING_ID:
1290 if (mUsingSlotsProtocol && rawEvent->value < 0) {
1291 slot->clearIfInUse();
1292 } else {
1293 slot->mInUse = true;
1294 slot->mAbsMTTrackingId = rawEvent->value;
1295 }
1296 break;
1297 case ABS_MT_PRESSURE:
1298 slot->mInUse = true;
1299 slot->mAbsMTPressure = rawEvent->value;
1300 break;
1301 case ABS_MT_TOOL_TYPE:
1302 slot->mInUse = true;
1303 slot->mAbsMTToolType = rawEvent->value;
1304 slot->mHaveAbsMTToolType = true;
1305 break;
1306 }
1307 }
1308 } else if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_MT_REPORT) {
1309 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
1310 mCurrentSlot += 1;
1311 }
1312}
1313
1314
1315// --- MultiTouchMotionAccumulator::Slot ---
1316
1317MultiTouchMotionAccumulator::Slot::Slot() {
1318 clear();
1319}
1320
1321void MultiTouchMotionAccumulator::Slot::clearIfInUse() {
1322 if (mInUse) {
1323 clear();
1324 }
1325}
1326
1327void MultiTouchMotionAccumulator::Slot::clear() {
1328 mInUse = false;
1329 mHaveAbsMTTouchMinor = false;
1330 mHaveAbsMTWidthMinor = false;
1331 mHaveAbsMTToolType = false;
1332 mAbsMTPositionX = 0;
1333 mAbsMTPositionY = 0;
1334 mAbsMTTouchMajor = 0;
1335 mAbsMTTouchMinor = 0;
1336 mAbsMTWidthMajor = 0;
1337 mAbsMTWidthMinor = 0;
1338 mAbsMTOrientation = 0;
1339 mAbsMTTrackingId = -1;
1340 mAbsMTPressure = 0;
1341 mAbsMTToolType = 0;
1342 mAbsMTDistance = 0;
1343}
1344
1345int32_t MultiTouchMotionAccumulator::Slot::getToolType() const {
1346 if (mHaveAbsMTToolType) {
1347 switch (mAbsMTToolType) {
1348 case MT_TOOL_FINGER:
1349 return AMOTION_EVENT_TOOL_TYPE_FINGER;
1350 case MT_TOOL_PEN:
1351 return AMOTION_EVENT_TOOL_TYPE_STYLUS;
1352 }
1353 }
1354 return AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
1355}
1356
1357
Jeff Brown6d0fec22010-07-23 21:28:06 -07001358// --- InputMapper ---
1359
1360InputMapper::InputMapper(InputDevice* device) :
1361 mDevice(device), mContext(device->getContext()) {
1362}
1363
1364InputMapper::~InputMapper() {
1365}
1366
1367void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1368 info->addSource(getSources());
1369}
1370
Jeff Brownef3d7e82010-09-30 14:33:04 -07001371void InputMapper::dump(String8& dump) {
1372}
1373
Jeff Brown474dcb52011-06-14 20:22:50 -07001374void InputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001375}
1376
1377void InputMapper::reset() {
1378}
1379
Jeff Brownaa3855d2011-03-17 01:34:19 -07001380void InputMapper::timeoutExpired(nsecs_t when) {
1381}
1382
Jeff Brown6d0fec22010-07-23 21:28:06 -07001383int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1384 return AKEY_STATE_UNKNOWN;
1385}
1386
1387int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1388 return AKEY_STATE_UNKNOWN;
1389}
1390
1391int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1392 return AKEY_STATE_UNKNOWN;
1393}
1394
1395bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1396 const int32_t* keyCodes, uint8_t* outFlags) {
1397 return false;
1398}
1399
1400int32_t InputMapper::getMetaState() {
1401 return 0;
1402}
1403
Jeff Brown05dc66a2011-03-02 14:41:58 -08001404void InputMapper::fadePointer() {
1405}
1406
Jeff Browncb1404e2011-01-15 18:14:15 -08001407void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
1408 const RawAbsoluteAxisInfo& axis, const char* name) {
1409 if (axis.valid) {
Jeff Brownb3a2d132011-06-12 18:14:50 -07001410 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d, resolution=%d\n",
1411 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz, axis.resolution);
Jeff Browncb1404e2011-01-15 18:14:15 -08001412 } else {
1413 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
1414 }
1415}
1416
Jeff Brown6d0fec22010-07-23 21:28:06 -07001417
1418// --- SwitchInputMapper ---
1419
1420SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
1421 InputMapper(device) {
1422}
1423
1424SwitchInputMapper::~SwitchInputMapper() {
1425}
1426
1427uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -08001428 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001429}
1430
1431void SwitchInputMapper::process(const RawEvent* rawEvent) {
1432 switch (rawEvent->type) {
1433 case EV_SW:
1434 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
1435 break;
1436 }
1437}
1438
1439void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -07001440 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001441}
1442
1443int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1444 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1445}
1446
1447
1448// --- KeyboardInputMapper ---
1449
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001450KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brownefd32662011-03-08 15:13:06 -08001451 uint32_t source, int32_t keyboardType) :
1452 InputMapper(device), mSource(source),
Jeff Brown6d0fec22010-07-23 21:28:06 -07001453 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001454 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001455}
1456
1457KeyboardInputMapper::~KeyboardInputMapper() {
1458}
1459
Jeff Brown6328cdc2010-07-29 18:18:33 -07001460void KeyboardInputMapper::initializeLocked() {
1461 mLocked.metaState = AMETA_NONE;
1462 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001463}
1464
1465uint32_t KeyboardInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001466 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001467}
1468
1469void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1470 InputMapper::populateDeviceInfo(info);
1471
1472 info->setKeyboardType(mKeyboardType);
1473}
1474
Jeff Brownef3d7e82010-09-30 14:33:04 -07001475void KeyboardInputMapper::dump(String8& dump) {
1476 { // acquire lock
1477 AutoMutex _l(mLock);
1478 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001479 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001480 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
1481 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
1482 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
1483 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1484 } // release lock
1485}
1486
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001487
Jeff Brown474dcb52011-06-14 20:22:50 -07001488void KeyboardInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
1489 InputMapper::configure(config, changes);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001490
Jeff Brown474dcb52011-06-14 20:22:50 -07001491 if (!changes) { // first time only
1492 // Configure basic parameters.
1493 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001494
Jeff Brown474dcb52011-06-14 20:22:50 -07001495 // Reset LEDs.
1496 {
1497 AutoMutex _l(mLock);
1498 resetLedStateLocked();
1499 }
Jeff Brown49ed71d2010-12-06 17:13:33 -08001500 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001501}
1502
1503void KeyboardInputMapper::configureParameters() {
1504 mParameters.orientationAware = false;
1505 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
1506 mParameters.orientationAware);
1507
1508 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
1509}
1510
1511void KeyboardInputMapper::dumpParameters(String8& dump) {
1512 dump.append(INDENT3 "Parameters:\n");
1513 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1514 mParameters.associatedDisplayId);
1515 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1516 toString(mParameters.orientationAware));
1517}
1518
Jeff Brown6d0fec22010-07-23 21:28:06 -07001519void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001520 for (;;) {
1521 int32_t keyCode, scanCode;
1522 { // acquire lock
1523 AutoMutex _l(mLock);
1524
1525 // Synthesize key up event on reset if keys are currently down.
1526 if (mLocked.keyDowns.isEmpty()) {
1527 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001528 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001529 break; // done
1530 }
1531
1532 const KeyDown& keyDown = mLocked.keyDowns.top();
1533 keyCode = keyDown.keyCode;
1534 scanCode = keyDown.scanCode;
1535 } // release lock
1536
Jeff Brown6d0fec22010-07-23 21:28:06 -07001537 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001538 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001539 }
1540
1541 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001542 getContext()->updateGlobalMetaState();
1543}
1544
1545void KeyboardInputMapper::process(const RawEvent* rawEvent) {
1546 switch (rawEvent->type) {
1547 case EV_KEY: {
1548 int32_t scanCode = rawEvent->scanCode;
1549 if (isKeyboardOrGamepadKey(scanCode)) {
1550 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
1551 rawEvent->flags);
1552 }
1553 break;
1554 }
1555 }
1556}
1557
1558bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
1559 return scanCode < BTN_MOUSE
1560 || scanCode >= KEY_OK
Jeff Brown9e8e40c2011-03-03 03:39:29 -08001561 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
Jeff Browncb1404e2011-01-15 18:14:15 -08001562 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001563}
1564
Jeff Brown6328cdc2010-07-29 18:18:33 -07001565void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
1566 int32_t scanCode, uint32_t policyFlags) {
1567 int32_t newMetaState;
1568 nsecs_t downTime;
1569 bool metaStateChanged = false;
1570
1571 { // acquire lock
1572 AutoMutex _l(mLock);
1573
1574 if (down) {
1575 // Rotate key codes according to orientation if needed.
1576 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001577 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001578 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001579 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1580 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001581 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001582 }
1583
1584 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001585 }
1586
Jeff Brown6328cdc2010-07-29 18:18:33 -07001587 // Add key down.
1588 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1589 if (keyDownIndex >= 0) {
1590 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001591 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001592 } else {
1593 // key down
Jeff Brownfe508922011-01-18 15:10:10 -08001594 if ((policyFlags & POLICY_FLAG_VIRTUAL)
1595 && mContext->shouldDropVirtualKey(when,
1596 getDevice(), keyCode, scanCode)) {
1597 return;
1598 }
1599
Jeff Brown6328cdc2010-07-29 18:18:33 -07001600 mLocked.keyDowns.push();
1601 KeyDown& keyDown = mLocked.keyDowns.editTop();
1602 keyDown.keyCode = keyCode;
1603 keyDown.scanCode = scanCode;
1604 }
1605
1606 mLocked.downTime = when;
1607 } else {
1608 // Remove key down.
1609 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1610 if (keyDownIndex >= 0) {
1611 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001612 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001613 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1614 } else {
1615 // key was not actually down
1616 LOGI("Dropping key up from device %s because the key was not down. "
1617 "keyCode=%d, scanCode=%d",
1618 getDeviceName().string(), keyCode, scanCode);
1619 return;
1620 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001621 }
1622
Jeff Brown6328cdc2010-07-29 18:18:33 -07001623 int32_t oldMetaState = mLocked.metaState;
1624 newMetaState = updateMetaState(keyCode, down, oldMetaState);
1625 if (oldMetaState != newMetaState) {
1626 mLocked.metaState = newMetaState;
1627 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -07001628 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001629 }
Jeff Brownfd0358292010-06-30 16:10:35 -07001630
Jeff Brown6328cdc2010-07-29 18:18:33 -07001631 downTime = mLocked.downTime;
1632 } // release lock
1633
Jeff Brown56194eb2011-03-02 19:23:13 -08001634 // Key down on external an keyboard should wake the device.
1635 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1636 // For internal keyboards, the key layout file should specify the policy flags for
1637 // each wake key individually.
1638 // TODO: Use the input device configuration to control this behavior more finely.
1639 if (down && getDevice()->isExternal()
1640 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1641 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1642 }
1643
Jeff Brown6328cdc2010-07-29 18:18:33 -07001644 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001645 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001646 }
1647
Jeff Brown05dc66a2011-03-02 14:41:58 -08001648 if (down && !isMetaKey(keyCode)) {
1649 getContext()->fadePointer();
1650 }
1651
Jeff Brownefd32662011-03-08 15:13:06 -08001652 getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001653 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1654 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001655}
1656
Jeff Brown6328cdc2010-07-29 18:18:33 -07001657ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1658 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001659 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001660 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001661 return i;
1662 }
1663 }
1664 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001665}
1666
Jeff Brown6d0fec22010-07-23 21:28:06 -07001667int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1668 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1669}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001670
Jeff Brown6d0fec22010-07-23 21:28:06 -07001671int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1672 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1673}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001674
Jeff Brown6d0fec22010-07-23 21:28:06 -07001675bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1676 const int32_t* keyCodes, uint8_t* outFlags) {
1677 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1678}
1679
1680int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001681 { // acquire lock
1682 AutoMutex _l(mLock);
1683 return mLocked.metaState;
1684 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001685}
1686
Jeff Brown49ed71d2010-12-06 17:13:33 -08001687void KeyboardInputMapper::resetLedStateLocked() {
1688 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1689 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1690 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1691
1692 updateLedStateLocked(true);
1693}
1694
1695void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1696 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1697 ledState.on = false;
1698}
1699
Jeff Brown497a92c2010-09-12 17:55:08 -07001700void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1701 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001702 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001703 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001704 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001705 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001706 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001707}
1708
1709void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1710 int32_t led, int32_t modifier, bool reset) {
1711 if (ledState.avail) {
1712 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001713 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001714 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1715 ledState.on = desiredState;
1716 }
1717 }
1718}
1719
Jeff Brown6d0fec22010-07-23 21:28:06 -07001720
Jeff Brown83c09682010-12-23 17:50:18 -08001721// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001722
Jeff Brown83c09682010-12-23 17:50:18 -08001723CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001724 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001725 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001726}
1727
Jeff Brown83c09682010-12-23 17:50:18 -08001728CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001729}
1730
Jeff Brown83c09682010-12-23 17:50:18 -08001731uint32_t CursorInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001732 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001733}
1734
Jeff Brown83c09682010-12-23 17:50:18 -08001735void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001736 InputMapper::populateDeviceInfo(info);
1737
Jeff Brown83c09682010-12-23 17:50:18 -08001738 if (mParameters.mode == Parameters::MODE_POINTER) {
1739 float minX, minY, maxX, maxY;
1740 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brownefd32662011-03-08 15:13:06 -08001741 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
1742 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001743 }
1744 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001745 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
1746 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001747 }
Jeff Brownefd32662011-03-08 15:13:06 -08001748 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001749
Jeff Brown49754db2011-07-01 17:37:58 -07001750 if (mCursorMotionAccumulator.haveRelativeVWheel()) {
Jeff Brownefd32662011-03-08 15:13:06 -08001751 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001752 }
Jeff Brown49754db2011-07-01 17:37:58 -07001753 if (mCursorMotionAccumulator.haveRelativeHWheel()) {
Jeff Brownefd32662011-03-08 15:13:06 -08001754 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001755 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001756}
1757
Jeff Brown83c09682010-12-23 17:50:18 -08001758void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001759 { // acquire lock
1760 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001761 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001762 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001763 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1764 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001765 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1766 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown49754db2011-07-01 17:37:58 -07001767 dump.appendFormat(INDENT3 "HaveVWheel: %s\n",
1768 toString(mCursorMotionAccumulator.haveRelativeVWheel()));
1769 dump.appendFormat(INDENT3 "HaveHWheel: %s\n",
1770 toString(mCursorMotionAccumulator.haveRelativeHWheel()));
Jeff Brown6f2fba42011-02-19 01:08:02 -08001771 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1772 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001773 dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
1774 dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState)));
Jeff Brownef3d7e82010-09-30 14:33:04 -07001775 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1776 } // release lock
1777}
1778
Jeff Brown474dcb52011-06-14 20:22:50 -07001779void CursorInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
1780 InputMapper::configure(config, changes);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001781
Jeff Brown474dcb52011-06-14 20:22:50 -07001782 if (!changes) { // first time only
Jeff Brown49754db2011-07-01 17:37:58 -07001783 mCursorMotionAccumulator.configure(getDevice());
1784
Jeff Brown474dcb52011-06-14 20:22:50 -07001785 // Configure basic parameters.
1786 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001787
Jeff Brown474dcb52011-06-14 20:22:50 -07001788 // Configure device mode.
1789 switch (mParameters.mode) {
1790 case Parameters::MODE_POINTER:
1791 mSource = AINPUT_SOURCE_MOUSE;
1792 mXPrecision = 1.0f;
1793 mYPrecision = 1.0f;
1794 mXScale = 1.0f;
1795 mYScale = 1.0f;
1796 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1797 break;
1798 case Parameters::MODE_NAVIGATION:
1799 mSource = AINPUT_SOURCE_TRACKBALL;
1800 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1801 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1802 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1803 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1804 break;
1805 }
1806
1807 mVWheelScale = 1.0f;
1808 mHWheelScale = 1.0f;
Jeff Brown83c09682010-12-23 17:50:18 -08001809 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001810
Jeff Brown474dcb52011-06-14 20:22:50 -07001811 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
1812 mPointerVelocityControl.setParameters(config->pointerVelocityControlParameters);
1813 mWheelXVelocityControl.setParameters(config->wheelVelocityControlParameters);
1814 mWheelYVelocityControl.setParameters(config->wheelVelocityControlParameters);
1815 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001816}
1817
Jeff Brown83c09682010-12-23 17:50:18 -08001818void CursorInputMapper::configureParameters() {
1819 mParameters.mode = Parameters::MODE_POINTER;
1820 String8 cursorModeString;
1821 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1822 if (cursorModeString == "navigation") {
1823 mParameters.mode = Parameters::MODE_NAVIGATION;
1824 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1825 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1826 }
1827 }
1828
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001829 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001830 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001831 mParameters.orientationAware);
1832
Jeff Brown83c09682010-12-23 17:50:18 -08001833 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1834 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001835}
1836
Jeff Brown83c09682010-12-23 17:50:18 -08001837void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001838 dump.append(INDENT3 "Parameters:\n");
1839 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1840 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001841
1842 switch (mParameters.mode) {
1843 case Parameters::MODE_POINTER:
1844 dump.append(INDENT4 "Mode: pointer\n");
1845 break;
1846 case Parameters::MODE_NAVIGATION:
1847 dump.append(INDENT4 "Mode: navigation\n");
1848 break;
1849 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07001850 LOG_ASSERT(false);
Jeff Brown83c09682010-12-23 17:50:18 -08001851 }
1852
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001853 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1854 toString(mParameters.orientationAware));
1855}
1856
Jeff Brown83c09682010-12-23 17:50:18 -08001857void CursorInputMapper::initializeLocked() {
Jeff Brown49754db2011-07-01 17:37:58 -07001858 mCursorButtonAccumulator.clearButtons();
1859 mCursorMotionAccumulator.clearRelativeAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001860
Jeff Brownefd32662011-03-08 15:13:06 -08001861 mLocked.buttonState = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001862 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001863}
1864
Jeff Brown83c09682010-12-23 17:50:18 -08001865void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001866 for (;;) {
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07001867 int32_t buttonState;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001868 { // acquire lock
1869 AutoMutex _l(mLock);
1870
Jeff Brownefd32662011-03-08 15:13:06 -08001871 buttonState = mLocked.buttonState;
1872 if (!buttonState) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001873 initializeLocked();
1874 break; // done
1875 }
1876 } // release lock
1877
Jeff Brown19c97d462011-06-01 12:33:19 -07001878 // Reset velocity.
1879 mPointerVelocityControl.reset();
1880 mWheelXVelocityControl.reset();
1881 mWheelYVelocityControl.reset();
1882
Jeff Brown83c09682010-12-23 17:50:18 -08001883 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001884 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown49754db2011-07-01 17:37:58 -07001885 mCursorButtonAccumulator.clearButtons();
1886 mCursorMotionAccumulator.clearRelativeAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001887 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001888 }
1889
Jeff Brown6d0fec22010-07-23 21:28:06 -07001890 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001891}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001892
Jeff Brown83c09682010-12-23 17:50:18 -08001893void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown49754db2011-07-01 17:37:58 -07001894 mCursorButtonAccumulator.process(rawEvent);
1895 mCursorMotionAccumulator.process(rawEvent);
Jeff Brownefd32662011-03-08 15:13:06 -08001896
Jeff Brown49754db2011-07-01 17:37:58 -07001897 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
1898 sync(rawEvent->when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001899 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001900}
1901
Jeff Brown83c09682010-12-23 17:50:18 -08001902void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown9626b142011-03-03 02:09:54 -08001903 int32_t motionEventAction;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07001904 int32_t lastButtonState, currentButtonState;
1905 PointerProperties pointerProperties;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001906 PointerCoords pointerCoords;
1907 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001908 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001909 { // acquire lock
1910 AutoMutex _l(mLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001911
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07001912 lastButtonState = mLocked.buttonState;
Jeff Brown49754db2011-07-01 17:37:58 -07001913 currentButtonState = mCursorButtonAccumulator.getButtonState();
1914 mLocked.buttonState = currentButtonState;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07001915
Jeff Brown49754db2011-07-01 17:37:58 -07001916 bool wasDown = isPointerDown(lastButtonState);
1917 bool down = isPointerDown(currentButtonState);
1918 bool downChanged;
1919 if (!wasDown && down) {
1920 mLocked.downTime = when;
1921 downChanged = true;
1922 } else if (wasDown && !down) {
1923 downChanged = true;
Jeff Brownefd32662011-03-08 15:13:06 -08001924 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001925 downChanged = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001926 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001927 downTime = mLocked.downTime;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001928
Jeff Brown6328cdc2010-07-29 18:18:33 -07001929 if (downChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08001930 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1931 } else if (down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001932 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001933 } else {
1934 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001935 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001936
Jeff Brown49754db2011-07-01 17:37:58 -07001937 float deltaX = mCursorMotionAccumulator.getRelativeX() * mXScale;
1938 float deltaY = mCursorMotionAccumulator.getRelativeY() * mYScale;
1939
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001940 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001941 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001942 // Rotate motion based on display orientation if needed.
1943 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1944 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001945 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1946 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001947 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001948 }
1949
Jeff Brown612891e2011-07-15 20:44:17 -07001950 rotateDelta(orientation, &deltaX, &deltaY);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001951 }
Jeff Brown83c09682010-12-23 17:50:18 -08001952
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07001953 pointerProperties.clear();
1954 pointerProperties.id = 0;
1955 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_MOUSE;
1956
1957 pointerCoords.clear();
1958
Jeff Brown49754db2011-07-01 17:37:58 -07001959 vscroll = mCursorMotionAccumulator.getRelativeVWheel();
1960 hscroll = mCursorMotionAccumulator.getRelativeHWheel();
Jeff Brown19c97d462011-06-01 12:33:19 -07001961
Jeff Brown49754db2011-07-01 17:37:58 -07001962 mWheelYVelocityControl.move(when, NULL, &vscroll);
Jeff Brown19c97d462011-06-01 12:33:19 -07001963 mWheelXVelocityControl.move(when, &hscroll, NULL);
1964
1965 mPointerVelocityControl.move(when, &deltaX, &deltaY);
Jeff Brown2352b972011-04-12 22:39:53 -07001966
Jeff Brown83c09682010-12-23 17:50:18 -08001967 if (mPointerController != NULL) {
Jeff Brown2352b972011-04-12 22:39:53 -07001968 if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
Jeff Brown49754db2011-07-01 17:37:58 -07001969 || currentButtonState != lastButtonState) {
Jeff Brown2352b972011-04-12 22:39:53 -07001970 mPointerController->setPresentation(
1971 PointerControllerInterface::PRESENTATION_POINTER);
1972
1973 if (deltaX != 0 || deltaY != 0) {
1974 mPointerController->move(deltaX, deltaY);
1975 }
1976
Jeff Brown49754db2011-07-01 17:37:58 -07001977 if (currentButtonState != lastButtonState) {
1978 mPointerController->setButtonState(currentButtonState);
Jeff Brown2352b972011-04-12 22:39:53 -07001979 }
1980
Jeff Brown538881e2011-05-25 18:23:38 -07001981 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
Jeff Brown83c09682010-12-23 17:50:18 -08001982 }
Jeff Brownefd32662011-03-08 15:13:06 -08001983
Jeff Brown91c69ab2011-02-14 17:03:18 -08001984 float x, y;
1985 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001986 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1987 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown83c09682010-12-23 17:50:18 -08001988 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001989 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1990 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001991 }
1992
Jeff Brownefd32662011-03-08 15:13:06 -08001993 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001994 } // release lock
1995
Jeff Brown56194eb2011-03-02 19:23:13 -08001996 // Moving an external trackball or mouse should wake the device.
1997 // We don't do this for internal cursor devices to prevent them from waking up
1998 // the device in your pocket.
1999 // TODO: Use the input device configuration to control this behavior more finely.
2000 uint32_t policyFlags = 0;
2001 if (getDevice()->isExternal()) {
2002 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2003 }
2004
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002005 // Synthesize key down from buttons if needed.
2006 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mSource,
2007 policyFlags, lastButtonState, currentButtonState);
2008
2009 // Send motion event.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002010 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownefd32662011-03-08 15:13:06 -08002011 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Browna6111372011-07-14 21:48:23 -07002012 motionEventAction, 0, metaState, currentButtonState, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002013 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Brownb6997262010-10-08 22:31:17 -07002014
Jeff Browna032cc02011-03-07 16:56:21 -08002015 // Send hover move after UP to tell the application that the mouse is hovering now.
2016 if (motionEventAction == AMOTION_EVENT_ACTION_UP
2017 && mPointerController != NULL) {
2018 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002019 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
2020 metaState, currentButtonState, AMOTION_EVENT_EDGE_FLAG_NONE,
2021 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Browna032cc02011-03-07 16:56:21 -08002022 }
Jeff Brown33bbfd22011-02-24 20:55:35 -08002023
Jeff Browna032cc02011-03-07 16:56:21 -08002024 // Send scroll events.
Jeff Brown33bbfd22011-02-24 20:55:35 -08002025 if (vscroll != 0 || hscroll != 0) {
2026 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
2027 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
2028
Jeff Brownefd32662011-03-08 15:13:06 -08002029 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002030 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, currentButtonState,
2031 AMOTION_EVENT_EDGE_FLAG_NONE,
2032 1, &pointerProperties, &pointerCoords, mXPrecision, mYPrecision, downTime);
Jeff Brown33bbfd22011-02-24 20:55:35 -08002033 }
Jeff Browna032cc02011-03-07 16:56:21 -08002034
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07002035 // Synthesize key up from buttons if needed.
2036 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mSource,
2037 policyFlags, lastButtonState, currentButtonState);
2038
Jeff Brown49754db2011-07-01 17:37:58 -07002039 mCursorMotionAccumulator.clearRelativeAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002040}
2041
Jeff Brown83c09682010-12-23 17:50:18 -08002042int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07002043 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
2044 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
2045 } else {
2046 return AKEY_STATE_UNKNOWN;
2047 }
2048}
2049
Jeff Brown05dc66a2011-03-02 14:41:58 -08002050void CursorInputMapper::fadePointer() {
2051 { // acquire lock
2052 AutoMutex _l(mLock);
Jeff Brownefd32662011-03-08 15:13:06 -08002053 if (mPointerController != NULL) {
Jeff Brown538881e2011-05-25 18:23:38 -07002054 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Jeff Brownefd32662011-03-08 15:13:06 -08002055 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002056 } // release lock
2057}
2058
Jeff Brown6d0fec22010-07-23 21:28:06 -07002059
2060// --- TouchInputMapper ---
2061
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002062TouchInputMapper::TouchInputMapper(InputDevice* device) :
2063 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002064 mLocked.surfaceOrientation = -1;
2065 mLocked.surfaceWidth = -1;
2066 mLocked.surfaceHeight = -1;
2067
2068 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002069}
2070
2071TouchInputMapper::~TouchInputMapper() {
2072}
2073
2074uint32_t TouchInputMapper::getSources() {
Jeff Brownace13b12011-03-09 17:39:48 -08002075 return mTouchSource | mPointerSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002076}
2077
2078void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
2079 InputMapper::populateDeviceInfo(info);
2080
Jeff Brown6328cdc2010-07-29 18:18:33 -07002081 { // acquire lock
2082 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002083
Jeff Brown6328cdc2010-07-29 18:18:33 -07002084 // Ensure surface information is up to date so that orientation changes are
2085 // noticed immediately.
Jeff Brownefd32662011-03-08 15:13:06 -08002086 if (!configureSurfaceLocked()) {
2087 return;
2088 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002089
Jeff Brownefd32662011-03-08 15:13:06 -08002090 info->addMotionRange(mLocked.orientedRanges.x);
2091 info->addMotionRange(mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07002092
2093 if (mLocked.orientedRanges.havePressure) {
Jeff Brownefd32662011-03-08 15:13:06 -08002094 info->addMotionRange(mLocked.orientedRanges.pressure);
Jeff Brown8d608662010-08-30 03:02:23 -07002095 }
2096
2097 if (mLocked.orientedRanges.haveSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08002098 info->addMotionRange(mLocked.orientedRanges.size);
Jeff Brown8d608662010-08-30 03:02:23 -07002099 }
2100
Jeff Brownc6d282b2010-10-14 21:42:15 -07002101 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08002102 info->addMotionRange(mLocked.orientedRanges.touchMajor);
2103 info->addMotionRange(mLocked.orientedRanges.touchMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07002104 }
2105
Jeff Brownc6d282b2010-10-14 21:42:15 -07002106 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08002107 info->addMotionRange(mLocked.orientedRanges.toolMajor);
2108 info->addMotionRange(mLocked.orientedRanges.toolMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07002109 }
2110
2111 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brownefd32662011-03-08 15:13:06 -08002112 info->addMotionRange(mLocked.orientedRanges.orientation);
Jeff Brown8d608662010-08-30 03:02:23 -07002113 }
Jeff Brownace13b12011-03-09 17:39:48 -08002114
Jeff Brown80fd47c2011-05-24 01:07:44 -07002115 if (mLocked.orientedRanges.haveDistance) {
2116 info->addMotionRange(mLocked.orientedRanges.distance);
2117 }
2118
Jeff Brownace13b12011-03-09 17:39:48 -08002119 if (mPointerController != NULL) {
2120 float minX, minY, maxX, maxY;
2121 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
2122 info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource,
2123 minX, maxX, 0.0f, 0.0f);
2124 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource,
2125 minY, maxY, 0.0f, 0.0f);
2126 }
2127 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource,
2128 0.0f, 1.0f, 0.0f, 0.0f);
2129 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002130 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002131}
2132
Jeff Brownef3d7e82010-09-30 14:33:04 -07002133void TouchInputMapper::dump(String8& dump) {
2134 { // acquire lock
2135 AutoMutex _l(mLock);
2136 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07002137 dumpParameters(dump);
2138 dumpVirtualKeysLocked(dump);
2139 dumpRawAxes(dump);
2140 dumpCalibration(dump);
2141 dumpSurfaceLocked(dump);
Jeff Brownefd32662011-03-08 15:13:06 -08002142
Jeff Brown511ee5f2010-10-18 13:32:20 -07002143 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07002144 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
2145 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
2146 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
2147 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
2148 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
2149 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
2150 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
2151 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
2152 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
2153 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
2154 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
Jeff Brownefd32662011-03-08 15:13:06 -08002155 dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale);
Jeff Brown80fd47c2011-05-24 01:07:44 -07002156 dump.appendFormat(INDENT4 "DistanceScale: %0.3f\n", mLocked.distanceScale);
Jeff Brownefd32662011-03-08 15:13:06 -08002157
2158 dump.appendFormat(INDENT3 "Last Touch:\n");
Jeff Brownace13b12011-03-09 17:39:48 -08002159 dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
Jeff Brownaba321a2011-06-28 20:34:40 -07002160 dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
2161 for (uint32_t i = 0; i < mLastTouch.pointerCount; i++) {
2162 const PointerData& pointer = mLastTouch.pointers[i];
2163 dump.appendFormat(INDENT5 "[%d]: id=%d, x=%d, y=%d, pressure=%d, "
2164 "touchMajor=%d, touchMinor=%d, toolMajor=%d, toolMinor=%d, "
Jeff Brown49754db2011-07-01 17:37:58 -07002165 "orientation=%d, distance=%d, toolType=%d, isHovering=%s\n", i,
Jeff Brownaba321a2011-06-28 20:34:40 -07002166 pointer.id, pointer.x, pointer.y, pointer.pressure,
2167 pointer.touchMajor, pointer.touchMinor, pointer.toolMajor, pointer.toolMinor,
Jeff Brown49754db2011-07-01 17:37:58 -07002168 pointer.orientation, pointer.distance,
2169 pointer.toolType, toString(pointer.isHovering));
Jeff Brownaba321a2011-06-28 20:34:40 -07002170 }
Jeff Brownace13b12011-03-09 17:39:48 -08002171
2172 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2173 dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
2174 dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
2175 mLocked.pointerGestureXMovementScale);
2176 dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
2177 mLocked.pointerGestureYMovementScale);
2178 dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
2179 mLocked.pointerGestureXZoomScale);
2180 dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
2181 mLocked.pointerGestureYZoomScale);
Jeff Brown2352b972011-04-12 22:39:53 -07002182 dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
2183 mLocked.pointerGestureMaxSwipeWidth);
Jeff Brownace13b12011-03-09 17:39:48 -08002184 }
Jeff Brownef3d7e82010-09-30 14:33:04 -07002185 } // release lock
2186}
2187
Jeff Brown6328cdc2010-07-29 18:18:33 -07002188void TouchInputMapper::initializeLocked() {
2189 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002190 mLastTouch.clear();
2191 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002192
Jeff Brown6328cdc2010-07-29 18:18:33 -07002193 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07002194
2195 mLocked.orientedRanges.havePressure = false;
2196 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002197 mLocked.orientedRanges.haveTouchSize = false;
2198 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07002199 mLocked.orientedRanges.haveOrientation = false;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002200 mLocked.orientedRanges.haveDistance = false;
Jeff Brownace13b12011-03-09 17:39:48 -08002201
2202 mPointerGesture.reset();
Jeff Brown8d608662010-08-30 03:02:23 -07002203}
2204
Jeff Brown474dcb52011-06-14 20:22:50 -07002205void TouchInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
2206 InputMapper::configure(config, changes);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002207
Jeff Brown474dcb52011-06-14 20:22:50 -07002208 mConfig = *config;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002209
Jeff Brown474dcb52011-06-14 20:22:50 -07002210 if (!changes) { // first time only
2211 // Configure basic parameters.
2212 configureParameters();
2213
2214 // Configure sources.
2215 switch (mParameters.deviceType) {
2216 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
2217 mTouchSource = AINPUT_SOURCE_TOUCHSCREEN;
2218 mPointerSource = 0;
2219 break;
2220 case Parameters::DEVICE_TYPE_TOUCH_PAD:
2221 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
2222 mPointerSource = 0;
2223 break;
2224 case Parameters::DEVICE_TYPE_POINTER:
2225 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
2226 mPointerSource = AINPUT_SOURCE_MOUSE;
2227 break;
2228 default:
2229 LOG_ASSERT(false);
2230 }
2231
2232 // Configure absolute axis information.
2233 configureRawAxes();
2234
2235 // Prepare input device calibration.
2236 parseCalibration();
2237 resolveCalibration();
2238
2239 { // acquire lock
2240 AutoMutex _l(mLock);
2241
2242 // Configure surface dimensions and orientation.
2243 configureSurfaceLocked();
2244 } // release lock
Jeff Brown83c09682010-12-23 17:50:18 -08002245 }
2246
Jeff Brown474dcb52011-06-14 20:22:50 -07002247 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_SPEED)) {
2248 mPointerGesture.pointerVelocityControl.setParameters(
2249 mConfig.pointerVelocityControlParameters);
2250 }
Jeff Brown8d608662010-08-30 03:02:23 -07002251
Jeff Brown474dcb52011-06-14 20:22:50 -07002252 if (!changes || (changes & InputReaderConfiguration::CHANGE_POINTER_GESTURE_ENABLEMENT)) {
2253 // Reset the touch screen when pointer gesture enablement changes.
2254 reset();
2255 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002256}
2257
Jeff Brown8d608662010-08-30 03:02:23 -07002258void TouchInputMapper::configureParameters() {
Jeff Brownb1268222011-06-03 17:06:16 -07002259 // Use the pointer presentation mode for devices that do not support distinct
2260 // multitouch. The spot-based presentation relies on being able to accurately
2261 // locate two or more fingers on the touch pad.
2262 mParameters.gestureMode = getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_SEMI_MT)
2263 ? Parameters::GESTURE_MODE_POINTER : Parameters::GESTURE_MODE_SPOTS;
Jeff Brown2352b972011-04-12 22:39:53 -07002264
Jeff Brown538881e2011-05-25 18:23:38 -07002265 String8 gestureModeString;
2266 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.gestureMode"),
2267 gestureModeString)) {
2268 if (gestureModeString == "pointer") {
2269 mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
2270 } else if (gestureModeString == "spots") {
2271 mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
2272 } else if (gestureModeString != "default") {
2273 LOGW("Invalid value for touch.gestureMode: '%s'", gestureModeString.string());
2274 }
2275 }
2276
Jeff Brownace13b12011-03-09 17:39:48 -08002277 if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
2278 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
2279 // The device is a cursor device with a touch pad attached.
2280 // By default don't use the touch pad to move the pointer.
2281 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown80fd47c2011-05-24 01:07:44 -07002282 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_POINTER)) {
2283 // The device is a pointing device like a track pad.
2284 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2285 } else if (getEventHub()->hasInputProperty(getDeviceId(), INPUT_PROP_DIRECT)) {
2286 // The device is a touch screen.
2287 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brownace13b12011-03-09 17:39:48 -08002288 } else {
Jeff Brown80fd47c2011-05-24 01:07:44 -07002289 // The device is a touch pad of unknown purpose.
Jeff Brownace13b12011-03-09 17:39:48 -08002290 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
2291 }
2292
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002293 String8 deviceTypeString;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002294 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
2295 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08002296 if (deviceTypeString == "touchScreen") {
2297 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brownefd32662011-03-08 15:13:06 -08002298 } else if (deviceTypeString == "touchPad") {
2299 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brownace13b12011-03-09 17:39:48 -08002300 } else if (deviceTypeString == "pointer") {
2301 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
Jeff Brown538881e2011-05-25 18:23:38 -07002302 } else if (deviceTypeString != "default") {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002303 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
2304 }
2305 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002306
Jeff Brownefd32662011-03-08 15:13:06 -08002307 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002308 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
2309 mParameters.orientationAware);
2310
Jeff Brownefd32662011-03-08 15:13:06 -08002311 mParameters.associatedDisplayId = mParameters.orientationAware
2312 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
Jeff Brownace13b12011-03-09 17:39:48 -08002313 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
Jeff Brownefd32662011-03-08 15:13:06 -08002314 ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07002315}
2316
Jeff Brownef3d7e82010-09-30 14:33:04 -07002317void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002318 dump.append(INDENT3 "Parameters:\n");
2319
Jeff Brown538881e2011-05-25 18:23:38 -07002320 switch (mParameters.gestureMode) {
2321 case Parameters::GESTURE_MODE_POINTER:
2322 dump.append(INDENT4 "GestureMode: pointer\n");
2323 break;
2324 case Parameters::GESTURE_MODE_SPOTS:
2325 dump.append(INDENT4 "GestureMode: spots\n");
2326 break;
2327 default:
2328 assert(false);
2329 }
2330
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002331 switch (mParameters.deviceType) {
2332 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
2333 dump.append(INDENT4 "DeviceType: touchScreen\n");
2334 break;
2335 case Parameters::DEVICE_TYPE_TOUCH_PAD:
2336 dump.append(INDENT4 "DeviceType: touchPad\n");
2337 break;
Jeff Brownace13b12011-03-09 17:39:48 -08002338 case Parameters::DEVICE_TYPE_POINTER:
2339 dump.append(INDENT4 "DeviceType: pointer\n");
2340 break;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002341 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07002342 LOG_ASSERT(false);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002343 }
2344
2345 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
2346 mParameters.associatedDisplayId);
2347 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
2348 toString(mParameters.orientationAware));
Jeff Brownb88102f2010-09-08 11:49:43 -07002349}
2350
Jeff Brown8d608662010-08-30 03:02:23 -07002351void TouchInputMapper::configureRawAxes() {
2352 mRawAxes.x.clear();
2353 mRawAxes.y.clear();
2354 mRawAxes.pressure.clear();
2355 mRawAxes.touchMajor.clear();
2356 mRawAxes.touchMinor.clear();
2357 mRawAxes.toolMajor.clear();
2358 mRawAxes.toolMinor.clear();
2359 mRawAxes.orientation.clear();
Jeff Brown80fd47c2011-05-24 01:07:44 -07002360 mRawAxes.distance.clear();
2361 mRawAxes.trackingId.clear();
2362 mRawAxes.slot.clear();
Jeff Brown8d608662010-08-30 03:02:23 -07002363}
2364
Jeff Brownef3d7e82010-09-30 14:33:04 -07002365void TouchInputMapper::dumpRawAxes(String8& dump) {
2366 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08002367 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
2368 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
2369 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
2370 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
2371 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
2372 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
2373 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
2374 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown80fd47c2011-05-24 01:07:44 -07002375 dumpRawAbsoluteAxisInfo(dump, mRawAxes.distance, "Distance");
2376 dumpRawAbsoluteAxisInfo(dump, mRawAxes.trackingId, "TrackingId");
2377 dumpRawAbsoluteAxisInfo(dump, mRawAxes.slot, "Slot");
Jeff Brown6d0fec22010-07-23 21:28:06 -07002378}
2379
Jeff Brown6328cdc2010-07-29 18:18:33 -07002380bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown9626b142011-03-03 02:09:54 -08002381 // Ensure we have valid X and Y axes.
2382 if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
2383 LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
2384 "The device will be inoperable.", getDeviceName().string());
2385 return false;
2386 }
2387
Jeff Brown6d0fec22010-07-23 21:28:06 -07002388 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002389 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown9626b142011-03-03 02:09:54 -08002390 int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2391 int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002392
2393 if (mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002394 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002395 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
Jeff Brownefd32662011-03-08 15:13:06 -08002396 &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
2397 &mLocked.associatedDisplayOrientation)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002398 return false;
2399 }
Jeff Brownefd32662011-03-08 15:13:06 -08002400
2401 // A touch screen inherits the dimensions of the display.
2402 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2403 width = mLocked.associatedDisplayWidth;
2404 height = mLocked.associatedDisplayHeight;
2405 }
2406
2407 // The device inherits the orientation of the display if it is orientation aware.
2408 if (mParameters.orientationAware) {
2409 orientation = mLocked.associatedDisplayOrientation;
2410 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002411 }
2412
Jeff Brownace13b12011-03-09 17:39:48 -08002413 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2414 && mPointerController == NULL) {
2415 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2416 }
2417
Jeff Brown6328cdc2010-07-29 18:18:33 -07002418 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002419 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002420 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002421 }
2422
Jeff Brown6328cdc2010-07-29 18:18:33 -07002423 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002424 if (sizeChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08002425 LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07002426 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07002427
Jeff Brown6328cdc2010-07-29 18:18:33 -07002428 mLocked.surfaceWidth = width;
2429 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002430
Jeff Brown8d608662010-08-30 03:02:23 -07002431 // Configure X and Y factors.
Jeff Brown9626b142011-03-03 02:09:54 -08002432 mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
2433 mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
2434 mLocked.xPrecision = 1.0f / mLocked.xScale;
2435 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002436
Jeff Brownefd32662011-03-08 15:13:06 -08002437 mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
2438 mLocked.orientedRanges.x.source = mTouchSource;
2439 mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
2440 mLocked.orientedRanges.y.source = mTouchSource;
2441
Jeff Brown9626b142011-03-03 02:09:54 -08002442 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002443
Jeff Brown8d608662010-08-30 03:02:23 -07002444 // Scale factor for terms that are not oriented in a particular axis.
2445 // If the pixels are square then xScale == yScale otherwise we fake it
2446 // by choosing an average.
2447 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002448
Jeff Brown8d608662010-08-30 03:02:23 -07002449 // Size of diagonal axis.
Jeff Brown2352b972011-04-12 22:39:53 -07002450 float diagonalSize = hypotf(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002451
Jeff Brown8d608662010-08-30 03:02:23 -07002452 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002453 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
2454 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002455
2456 mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
2457 mLocked.orientedRanges.touchMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002458 mLocked.orientedRanges.touchMajor.min = 0;
2459 mLocked.orientedRanges.touchMajor.max = diagonalSize;
2460 mLocked.orientedRanges.touchMajor.flat = 0;
2461 mLocked.orientedRanges.touchMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002462
Jeff Brown8d608662010-08-30 03:02:23 -07002463 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08002464 mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002465 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002466
Jeff Brown8d608662010-08-30 03:02:23 -07002467 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002468 mLocked.toolSizeLinearScale = 0;
2469 mLocked.toolSizeLinearBias = 0;
2470 mLocked.toolSizeAreaScale = 0;
2471 mLocked.toolSizeAreaBias = 0;
2472 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2473 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
2474 if (mCalibration.haveToolSizeLinearScale) {
2475 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07002476 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002477 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07002478 / mRawAxes.toolMajor.maxValue;
2479 }
2480
Jeff Brownc6d282b2010-10-14 21:42:15 -07002481 if (mCalibration.haveToolSizeLinearBias) {
2482 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2483 }
2484 } else if (mCalibration.toolSizeCalibration ==
2485 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
2486 if (mCalibration.haveToolSizeLinearScale) {
2487 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2488 } else {
2489 mLocked.toolSizeLinearScale = min(width, height);
2490 }
2491
2492 if (mCalibration.haveToolSizeLinearBias) {
2493 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2494 }
2495
2496 if (mCalibration.haveToolSizeAreaScale) {
2497 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
2498 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2499 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
2500 }
2501
2502 if (mCalibration.haveToolSizeAreaBias) {
2503 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07002504 }
2505 }
2506
Jeff Brownc6d282b2010-10-14 21:42:15 -07002507 mLocked.orientedRanges.haveToolSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002508
2509 mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
2510 mLocked.orientedRanges.toolMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002511 mLocked.orientedRanges.toolMajor.min = 0;
2512 mLocked.orientedRanges.toolMajor.max = diagonalSize;
2513 mLocked.orientedRanges.toolMajor.flat = 0;
2514 mLocked.orientedRanges.toolMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002515
Jeff Brown8d608662010-08-30 03:02:23 -07002516 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08002517 mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002518 }
2519
2520 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002521 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002522 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
2523 RawAbsoluteAxisInfo rawPressureAxis;
2524 switch (mCalibration.pressureSource) {
2525 case Calibration::PRESSURE_SOURCE_PRESSURE:
2526 rawPressureAxis = mRawAxes.pressure;
2527 break;
2528 case Calibration::PRESSURE_SOURCE_TOUCH:
2529 rawPressureAxis = mRawAxes.touchMajor;
2530 break;
2531 default:
2532 rawPressureAxis.clear();
2533 }
2534
Jeff Brown8d608662010-08-30 03:02:23 -07002535 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2536 || mCalibration.pressureCalibration
2537 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2538 if (mCalibration.havePressureScale) {
2539 mLocked.pressureScale = mCalibration.pressureScale;
2540 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
2541 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
2542 }
2543 }
2544
2545 mLocked.orientedRanges.havePressure = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002546
2547 mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2548 mLocked.orientedRanges.pressure.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002549 mLocked.orientedRanges.pressure.min = 0;
2550 mLocked.orientedRanges.pressure.max = 1.0;
2551 mLocked.orientedRanges.pressure.flat = 0;
2552 mLocked.orientedRanges.pressure.fuzz = 0;
2553 }
2554
2555 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002556 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002557 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002558 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
2559 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2560 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
2561 }
2562 }
2563
2564 mLocked.orientedRanges.haveSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002565
2566 mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
2567 mLocked.orientedRanges.size.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002568 mLocked.orientedRanges.size.min = 0;
2569 mLocked.orientedRanges.size.max = 1.0;
2570 mLocked.orientedRanges.size.flat = 0;
2571 mLocked.orientedRanges.size.fuzz = 0;
2572 }
2573
2574 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07002575 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002576 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002577 if (mCalibration.orientationCalibration
2578 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
2579 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
2580 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
2581 }
2582 }
2583
Jeff Brown80fd47c2011-05-24 01:07:44 -07002584 mLocked.orientedRanges.haveOrientation = true;
2585
Jeff Brownefd32662011-03-08 15:13:06 -08002586 mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2587 mLocked.orientedRanges.orientation.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002588 mLocked.orientedRanges.orientation.min = - M_PI_2;
2589 mLocked.orientedRanges.orientation.max = M_PI_2;
2590 mLocked.orientedRanges.orientation.flat = 0;
2591 mLocked.orientedRanges.orientation.fuzz = 0;
2592 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07002593
2594 // Distance
2595 mLocked.distanceScale = 0;
2596 if (mCalibration.distanceCalibration != Calibration::DISTANCE_CALIBRATION_NONE) {
2597 if (mCalibration.distanceCalibration
2598 == Calibration::DISTANCE_CALIBRATION_SCALED) {
2599 if (mCalibration.haveDistanceScale) {
2600 mLocked.distanceScale = mCalibration.distanceScale;
2601 } else {
2602 mLocked.distanceScale = 1.0f;
2603 }
2604 }
2605
2606 mLocked.orientedRanges.haveDistance = true;
2607
2608 mLocked.orientedRanges.distance.axis = AMOTION_EVENT_AXIS_DISTANCE;
2609 mLocked.orientedRanges.distance.source = mTouchSource;
2610 mLocked.orientedRanges.distance.min =
2611 mRawAxes.distance.minValue * mLocked.distanceScale;
2612 mLocked.orientedRanges.distance.max =
2613 mRawAxes.distance.minValue * mLocked.distanceScale;
2614 mLocked.orientedRanges.distance.flat = 0;
2615 mLocked.orientedRanges.distance.fuzz =
2616 mRawAxes.distance.fuzz * mLocked.distanceScale;
2617 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002618 }
2619
2620 if (orientationChanged || sizeChanged) {
Jeff Brown9626b142011-03-03 02:09:54 -08002621 // Compute oriented surface dimensions, precision, scales and ranges.
2622 // Note that the maximum value reported is an inclusive maximum value so it is one
2623 // unit less than the total width or height of surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002624 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002625 case DISPLAY_ORIENTATION_90:
2626 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07002627 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
2628 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
Jeff Brown9626b142011-03-03 02:09:54 -08002629
Jeff Brown6328cdc2010-07-29 18:18:33 -07002630 mLocked.orientedXPrecision = mLocked.yPrecision;
2631 mLocked.orientedYPrecision = mLocked.xPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002632
2633 mLocked.orientedRanges.x.min = 0;
2634 mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2635 * mLocked.yScale;
2636 mLocked.orientedRanges.x.flat = 0;
2637 mLocked.orientedRanges.x.fuzz = mLocked.yScale;
2638
2639 mLocked.orientedRanges.y.min = 0;
2640 mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2641 * mLocked.xScale;
2642 mLocked.orientedRanges.y.flat = 0;
2643 mLocked.orientedRanges.y.fuzz = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002644 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002645
Jeff Brown6d0fec22010-07-23 21:28:06 -07002646 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07002647 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
2648 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
Jeff Brown9626b142011-03-03 02:09:54 -08002649
Jeff Brown6328cdc2010-07-29 18:18:33 -07002650 mLocked.orientedXPrecision = mLocked.xPrecision;
2651 mLocked.orientedYPrecision = mLocked.yPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002652
2653 mLocked.orientedRanges.x.min = 0;
2654 mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2655 * mLocked.xScale;
2656 mLocked.orientedRanges.x.flat = 0;
2657 mLocked.orientedRanges.x.fuzz = mLocked.xScale;
2658
2659 mLocked.orientedRanges.y.min = 0;
2660 mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2661 * mLocked.yScale;
2662 mLocked.orientedRanges.y.flat = 0;
2663 mLocked.orientedRanges.y.fuzz = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002664 break;
2665 }
Jeff Brownace13b12011-03-09 17:39:48 -08002666
2667 // Compute pointer gesture detection parameters.
2668 // TODO: These factors should not be hardcoded.
2669 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2670 int32_t rawWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2671 int32_t rawHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown2352b972011-04-12 22:39:53 -07002672 float rawDiagonal = hypotf(rawWidth, rawHeight);
2673 float displayDiagonal = hypotf(mLocked.associatedDisplayWidth,
2674 mLocked.associatedDisplayHeight);
Jeff Brownace13b12011-03-09 17:39:48 -08002675
Jeff Brown2352b972011-04-12 22:39:53 -07002676 // Scale movements such that one whole swipe of the touch pad covers a
Jeff Brown19c97d462011-06-01 12:33:19 -07002677 // given area relative to the diagonal size of the display when no acceleration
2678 // is applied.
Jeff Brownace13b12011-03-09 17:39:48 -08002679 // Assume that the touch pad has a square aspect ratio such that movements in
2680 // X and Y of the same number of raw units cover the same physical distance.
Jeff Brown474dcb52011-06-14 20:22:50 -07002681 mLocked.pointerGestureXMovementScale = mConfig.pointerGestureMovementSpeedRatio
Jeff Brown2352b972011-04-12 22:39:53 -07002682 * displayDiagonal / rawDiagonal;
Jeff Brownace13b12011-03-09 17:39:48 -08002683 mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
2684
2685 // Scale zooms to cover a smaller range of the display than movements do.
2686 // This value determines the area around the pointer that is affected by freeform
2687 // pointer gestures.
Jeff Brown474dcb52011-06-14 20:22:50 -07002688 mLocked.pointerGestureXZoomScale = mConfig.pointerGestureZoomSpeedRatio
Jeff Brown2352b972011-04-12 22:39:53 -07002689 * displayDiagonal / rawDiagonal;
2690 mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
Jeff Brownace13b12011-03-09 17:39:48 -08002691
Jeff Brown2352b972011-04-12 22:39:53 -07002692 // Max width between pointers to detect a swipe gesture is more than some fraction
2693 // of the diagonal axis of the touch pad. Touches that are wider than this are
2694 // translated into freeform gestures.
Jeff Brown214eaf42011-05-26 19:17:02 -07002695 mLocked.pointerGestureMaxSwipeWidth =
Jeff Brown474dcb52011-06-14 20:22:50 -07002696 mConfig.pointerGestureSwipeMaxWidthRatio * rawDiagonal;
Jeff Brown2352b972011-04-12 22:39:53 -07002697
2698 // Reset the current pointer gesture.
2699 mPointerGesture.reset();
2700
2701 // Remove any current spots.
2702 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2703 mPointerController->clearSpots();
2704 }
Jeff Brownace13b12011-03-09 17:39:48 -08002705 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002706 }
2707
2708 return true;
2709}
2710
Jeff Brownef3d7e82010-09-30 14:33:04 -07002711void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
2712 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
2713 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
2714 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07002715}
2716
Jeff Brown6328cdc2010-07-29 18:18:33 -07002717void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07002718 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08002719 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002720
Jeff Brown6328cdc2010-07-29 18:18:33 -07002721 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002722
Jeff Brown6328cdc2010-07-29 18:18:33 -07002723 if (virtualKeyDefinitions.size() == 0) {
2724 return;
2725 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002726
Jeff Brown6328cdc2010-07-29 18:18:33 -07002727 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
2728
Jeff Brown8d608662010-08-30 03:02:23 -07002729 int32_t touchScreenLeft = mRawAxes.x.minValue;
2730 int32_t touchScreenTop = mRawAxes.y.minValue;
Jeff Brown9626b142011-03-03 02:09:54 -08002731 int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2732 int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002733
2734 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07002735 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07002736 virtualKeyDefinitions[i];
2737
2738 mLocked.virtualKeys.add();
2739 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
2740
2741 virtualKey.scanCode = virtualKeyDefinition.scanCode;
2742 int32_t keyCode;
2743 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08002744 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002745 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002746 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
2747 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002748 mLocked.virtualKeys.pop(); // drop the key
2749 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002750 }
2751
Jeff Brown6328cdc2010-07-29 18:18:33 -07002752 virtualKey.keyCode = keyCode;
2753 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002754
Jeff Brown6328cdc2010-07-29 18:18:33 -07002755 // convert the key definition's display coordinates into touch coordinates for a hit box
2756 int32_t halfWidth = virtualKeyDefinition.width / 2;
2757 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002758
Jeff Brown6328cdc2010-07-29 18:18:33 -07002759 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
2760 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2761 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
2762 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2763 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
2764 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2765 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
2766 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brownef3d7e82010-09-30 14:33:04 -07002767 }
2768}
2769
2770void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
2771 if (!mLocked.virtualKeys.isEmpty()) {
2772 dump.append(INDENT3 "Virtual Keys:\n");
2773
2774 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
2775 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
2776 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
2777 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
2778 i, virtualKey.scanCode, virtualKey.keyCode,
2779 virtualKey.hitLeft, virtualKey.hitRight,
2780 virtualKey.hitTop, virtualKey.hitBottom);
2781 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002782 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002783}
2784
Jeff Brown8d608662010-08-30 03:02:23 -07002785void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002786 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07002787 Calibration& out = mCalibration;
2788
Jeff Brownc6d282b2010-10-14 21:42:15 -07002789 // Touch Size
2790 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2791 String8 touchSizeCalibrationString;
2792 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2793 if (touchSizeCalibrationString == "none") {
2794 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2795 } else if (touchSizeCalibrationString == "geometric") {
2796 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2797 } else if (touchSizeCalibrationString == "pressure") {
2798 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2799 } else if (touchSizeCalibrationString != "default") {
2800 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2801 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002802 }
2803 }
2804
Jeff Brownc6d282b2010-10-14 21:42:15 -07002805 // Tool Size
2806 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2807 String8 toolSizeCalibrationString;
2808 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2809 if (toolSizeCalibrationString == "none") {
2810 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2811 } else if (toolSizeCalibrationString == "geometric") {
2812 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2813 } else if (toolSizeCalibrationString == "linear") {
2814 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2815 } else if (toolSizeCalibrationString == "area") {
2816 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2817 } else if (toolSizeCalibrationString != "default") {
2818 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2819 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002820 }
2821 }
2822
Jeff Brownc6d282b2010-10-14 21:42:15 -07002823 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2824 out.toolSizeLinearScale);
2825 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2826 out.toolSizeLinearBias);
2827 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2828 out.toolSizeAreaScale);
2829 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2830 out.toolSizeAreaBias);
2831 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2832 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07002833
2834 // Pressure
2835 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2836 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002837 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002838 if (pressureCalibrationString == "none") {
2839 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2840 } else if (pressureCalibrationString == "physical") {
2841 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2842 } else if (pressureCalibrationString == "amplitude") {
2843 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2844 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002845 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002846 pressureCalibrationString.string());
2847 }
2848 }
2849
2850 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2851 String8 pressureSourceString;
2852 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2853 if (pressureSourceString == "pressure") {
2854 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2855 } else if (pressureSourceString == "touch") {
2856 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2857 } else if (pressureSourceString != "default") {
2858 LOGW("Invalid value for touch.pressure.source: '%s'",
2859 pressureSourceString.string());
2860 }
2861 }
2862
2863 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2864 out.pressureScale);
2865
2866 // Size
2867 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2868 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002869 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002870 if (sizeCalibrationString == "none") {
2871 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2872 } else if (sizeCalibrationString == "normalized") {
2873 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2874 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002875 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002876 sizeCalibrationString.string());
2877 }
2878 }
2879
2880 // Orientation
2881 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2882 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002883 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002884 if (orientationCalibrationString == "none") {
2885 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2886 } else if (orientationCalibrationString == "interpolated") {
2887 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002888 } else if (orientationCalibrationString == "vector") {
2889 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002890 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002891 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002892 orientationCalibrationString.string());
2893 }
2894 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07002895
2896 // Distance
2897 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_DEFAULT;
2898 String8 distanceCalibrationString;
2899 if (in.tryGetProperty(String8("touch.distance.calibration"), distanceCalibrationString)) {
2900 if (distanceCalibrationString == "none") {
2901 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
2902 } else if (distanceCalibrationString == "scaled") {
2903 out.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
2904 } else if (distanceCalibrationString != "default") {
2905 LOGW("Invalid value for touch.distance.calibration: '%s'",
2906 distanceCalibrationString.string());
2907 }
2908 }
2909
2910 out.haveDistanceScale = in.tryGetProperty(String8("touch.distance.scale"),
2911 out.distanceScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002912}
2913
2914void TouchInputMapper::resolveCalibration() {
2915 // Pressure
2916 switch (mCalibration.pressureSource) {
2917 case Calibration::PRESSURE_SOURCE_DEFAULT:
2918 if (mRawAxes.pressure.valid) {
2919 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2920 } else if (mRawAxes.touchMajor.valid) {
2921 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2922 }
2923 break;
2924
2925 case Calibration::PRESSURE_SOURCE_PRESSURE:
2926 if (! mRawAxes.pressure.valid) {
2927 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2928 "the pressure axis is not available.");
2929 }
2930 break;
2931
2932 case Calibration::PRESSURE_SOURCE_TOUCH:
2933 if (! mRawAxes.touchMajor.valid) {
2934 LOGW("Calibration property touch.pressure.source is 'touch' but "
2935 "the touchMajor axis is not available.");
2936 }
2937 break;
2938
2939 default:
2940 break;
2941 }
2942
2943 switch (mCalibration.pressureCalibration) {
2944 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2945 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2946 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2947 } else {
2948 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2949 }
2950 break;
2951
2952 default:
2953 break;
2954 }
2955
Jeff Brownc6d282b2010-10-14 21:42:15 -07002956 // Tool Size
2957 switch (mCalibration.toolSizeCalibration) {
2958 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002959 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002960 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002961 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002962 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002963 }
2964 break;
2965
2966 default:
2967 break;
2968 }
2969
Jeff Brownc6d282b2010-10-14 21:42:15 -07002970 // Touch Size
2971 switch (mCalibration.touchSizeCalibration) {
2972 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002973 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002974 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2975 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002976 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002977 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002978 }
2979 break;
2980
2981 default:
2982 break;
2983 }
2984
2985 // Size
2986 switch (mCalibration.sizeCalibration) {
2987 case Calibration::SIZE_CALIBRATION_DEFAULT:
2988 if (mRawAxes.toolMajor.valid) {
2989 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2990 } else {
2991 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2992 }
2993 break;
2994
2995 default:
2996 break;
2997 }
2998
2999 // Orientation
3000 switch (mCalibration.orientationCalibration) {
3001 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
3002 if (mRawAxes.orientation.valid) {
3003 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
3004 } else {
3005 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
3006 }
3007 break;
3008
3009 default:
3010 break;
3011 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07003012
3013 // Distance
3014 switch (mCalibration.distanceCalibration) {
3015 case Calibration::DISTANCE_CALIBRATION_DEFAULT:
3016 if (mRawAxes.distance.valid) {
3017 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_SCALED;
3018 } else {
3019 mCalibration.distanceCalibration = Calibration::DISTANCE_CALIBRATION_NONE;
3020 }
3021 break;
3022
3023 default:
3024 break;
3025 }
Jeff Brown8d608662010-08-30 03:02:23 -07003026}
3027
Jeff Brownef3d7e82010-09-30 14:33:04 -07003028void TouchInputMapper::dumpCalibration(String8& dump) {
3029 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07003030
Jeff Brownc6d282b2010-10-14 21:42:15 -07003031 // Touch Size
3032 switch (mCalibration.touchSizeCalibration) {
3033 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
3034 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003035 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07003036 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
3037 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003038 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07003039 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
3040 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003041 break;
3042 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07003043 LOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003044 }
3045
Jeff Brownc6d282b2010-10-14 21:42:15 -07003046 // Tool Size
3047 switch (mCalibration.toolSizeCalibration) {
3048 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
3049 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003050 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07003051 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
3052 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003053 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07003054 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
3055 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
3056 break;
3057 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
3058 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003059 break;
3060 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07003061 LOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003062 }
3063
Jeff Brownc6d282b2010-10-14 21:42:15 -07003064 if (mCalibration.haveToolSizeLinearScale) {
3065 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
3066 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07003067 }
3068
Jeff Brownc6d282b2010-10-14 21:42:15 -07003069 if (mCalibration.haveToolSizeLinearBias) {
3070 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
3071 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07003072 }
3073
Jeff Brownc6d282b2010-10-14 21:42:15 -07003074 if (mCalibration.haveToolSizeAreaScale) {
3075 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
3076 mCalibration.toolSizeAreaScale);
3077 }
3078
3079 if (mCalibration.haveToolSizeAreaBias) {
3080 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
3081 mCalibration.toolSizeAreaBias);
3082 }
3083
3084 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08003085 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08003086 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07003087 }
3088
3089 // Pressure
3090 switch (mCalibration.pressureCalibration) {
3091 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003092 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003093 break;
3094 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003095 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003096 break;
3097 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003098 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003099 break;
3100 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07003101 LOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003102 }
3103
3104 switch (mCalibration.pressureSource) {
3105 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003106 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003107 break;
3108 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003109 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003110 break;
3111 case Calibration::PRESSURE_SOURCE_DEFAULT:
3112 break;
3113 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07003114 LOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003115 }
3116
3117 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07003118 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
3119 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07003120 }
3121
3122 // Size
3123 switch (mCalibration.sizeCalibration) {
3124 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003125 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003126 break;
3127 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003128 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003129 break;
3130 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07003131 LOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003132 }
3133
3134 // Orientation
3135 switch (mCalibration.orientationCalibration) {
3136 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003137 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003138 break;
3139 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07003140 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07003141 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08003142 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
3143 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
3144 break;
Jeff Brown8d608662010-08-30 03:02:23 -07003145 default:
Jeff Brownb6110c22011-04-01 16:15:13 -07003146 LOG_ASSERT(false);
Jeff Brown8d608662010-08-30 03:02:23 -07003147 }
Jeff Brown80fd47c2011-05-24 01:07:44 -07003148
3149 // Distance
3150 switch (mCalibration.distanceCalibration) {
3151 case Calibration::DISTANCE_CALIBRATION_NONE:
3152 dump.append(INDENT4 "touch.distance.calibration: none\n");
3153 break;
3154 case Calibration::DISTANCE_CALIBRATION_SCALED:
3155 dump.append(INDENT4 "touch.distance.calibration: scaled\n");
3156 break;
3157 default:
3158 LOG_ASSERT(false);
3159 }
3160
3161 if (mCalibration.haveDistanceScale) {
3162 dump.appendFormat(INDENT4 "touch.distance.scale: %0.3f\n",
3163 mCalibration.distanceScale);
3164 }
Jeff Brown8d608662010-08-30 03:02:23 -07003165}
3166
Jeff Brown6d0fec22010-07-23 21:28:06 -07003167void TouchInputMapper::reset() {
3168 // Synthesize touch up event if touch is currently down.
3169 // This will also take care of finishing virtual key processing if needed.
3170 if (mLastTouch.pointerCount != 0) {
3171 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
3172 mCurrentTouch.clear();
3173 syncTouch(when, true);
3174 }
3175
Jeff Brown6328cdc2010-07-29 18:18:33 -07003176 { // acquire lock
3177 AutoMutex _l(mLock);
3178 initializeLocked();
Jeff Brown2352b972011-04-12 22:39:53 -07003179
3180 if (mPointerController != NULL
3181 && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
Jeff Brown474dcb52011-06-14 20:22:50 -07003182 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Jeff Brown2352b972011-04-12 22:39:53 -07003183 mPointerController->clearSpots();
3184 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003185 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003186
Jeff Brown6328cdc2010-07-29 18:18:33 -07003187 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07003188}
3189
3190void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brownaa3855d2011-03-17 01:34:19 -07003191#if DEBUG_RAW_EVENTS
3192 if (!havePointerIds) {
3193 LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount);
3194 } else {
3195 LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, "
3196 "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount,
3197 mLastTouch.idBits.value & ~mCurrentTouch.idBits.value,
3198 mCurrentTouch.idBits.value & ~mLastTouch.idBits.value,
3199 mLastTouch.idBits.value & mCurrentTouch.idBits.value,
3200 mLastTouch.idBits.value, mCurrentTouch.idBits.value);
3201 }
3202#endif
3203
Jeff Brown6328cdc2010-07-29 18:18:33 -07003204 // Preprocess pointer data.
Jeff Brownaa3855d2011-03-17 01:34:19 -07003205 if (!havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003206 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003207 }
3208
Jeff Brown49754db2011-07-01 17:37:58 -07003209 // Handle initial down events.
Jeff Brown56194eb2011-03-02 19:23:13 -08003210 uint32_t policyFlags = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -08003211 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brownefd32662011-03-08 15:13:06 -08003212 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
3213 // If this is a touch screen, hide the pointer on an initial down.
3214 getContext()->fadePointer();
3215 }
Jeff Brown56194eb2011-03-02 19:23:13 -08003216
3217 // Initial downs on external touch devices should wake the device.
3218 // We don't do this for internal touch screens to prevent them from waking
3219 // up in your pocket.
3220 // TODO: Use the input device configuration to control this behavior more finely.
3221 if (getDevice()->isExternal()) {
3222 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
3223 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08003224 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003225
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003226 // Synthesize key down from buttons if needed.
3227 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_DOWN, when, getDeviceId(), mTouchSource,
3228 policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState);
3229
3230 // Send motion events.
Jeff Brown79ac9692011-04-19 21:20:10 -07003231 TouchResult touchResult;
3232 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
3233 && mLastTouch.buttonState == mCurrentTouch.buttonState) {
3234 // Drop spurious syncs.
3235 touchResult = DROP_STROKE;
3236 } else {
3237 // Process touches and virtual keys.
3238 touchResult = consumeOffScreenTouches(when, policyFlags);
3239 if (touchResult == DISPATCH_TOUCH) {
3240 suppressSwipeOntoVirtualKeys(when);
Jeff Brown474dcb52011-06-14 20:22:50 -07003241 if (mPointerController != NULL && mConfig.pointerGesturesEnabled) {
Jeff Brown79ac9692011-04-19 21:20:10 -07003242 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
3243 }
3244 dispatchTouches(when, policyFlags);
Jeff Brownace13b12011-03-09 17:39:48 -08003245 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003246 }
3247
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003248 // Synthesize key up from buttons if needed.
3249 synthesizeButtonKeys(getContext(), AKEY_EVENT_ACTION_UP, when, getDeviceId(), mTouchSource,
3250 policyFlags, mLastTouch.buttonState, mCurrentTouch.buttonState);
3251
Jeff Brown6328cdc2010-07-29 18:18:33 -07003252 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brownace13b12011-03-09 17:39:48 -08003253 // Keep the button state so we can track edge-triggered button state changes.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003254 if (touchResult == DROP_STROKE) {
3255 mLastTouch.clear();
Jeff Browna4d1bc52011-07-01 19:23:40 -07003256 mLastTouch.buttonState = mCurrentTouch.buttonState;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003257 } else {
Jeff Browna4d1bc52011-07-01 19:23:40 -07003258 mLastTouch.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003259 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003260}
3261
Jeff Brown79ac9692011-04-19 21:20:10 -07003262void TouchInputMapper::timeoutExpired(nsecs_t when) {
3263 if (mPointerController != NULL) {
3264 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
3265 }
3266}
3267
Jeff Brown6d0fec22010-07-23 21:28:06 -07003268TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
3269 nsecs_t when, uint32_t policyFlags) {
3270 int32_t keyEventAction, keyEventFlags;
3271 int32_t keyCode, scanCode, downTime;
3272 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07003273
Jeff Brown6328cdc2010-07-29 18:18:33 -07003274 { // acquire lock
3275 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003276
Jeff Brown6328cdc2010-07-29 18:18:33 -07003277 // Update surface size and orientation, including virtual key positions.
3278 if (! configureSurfaceLocked()) {
3279 return DROP_STROKE;
3280 }
3281
3282 // Check for virtual key press.
3283 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003284 if (mCurrentTouch.pointerCount == 0) {
3285 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07003286 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003287#if DEBUG_VIRTUAL_KEYS
3288 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07003289 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003290#endif
3291 keyEventAction = AKEY_EVENT_ACTION_UP;
3292 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
3293 touchResult = SKIP_TOUCH;
3294 goto DispatchVirtualKey;
3295 }
3296
3297 if (mCurrentTouch.pointerCount == 1) {
3298 int32_t x = mCurrentTouch.pointers[0].x;
3299 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003300 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
3301 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003302 // Pointer is still within the space of the virtual key.
3303 return SKIP_TOUCH;
3304 }
3305 }
3306
3307 // Pointer left virtual key area or another pointer also went down.
3308 // Send key cancellation and drop the stroke so subsequent motions will be
3309 // considered fresh downs. This is useful when the user swipes away from the
3310 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07003311 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003312#if DEBUG_VIRTUAL_KEYS
3313 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07003314 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003315#endif
3316 keyEventAction = AKEY_EVENT_ACTION_UP;
3317 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
3318 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07003319
3320 // Check whether the pointer moved inside the display area where we should
3321 // start a new stroke.
3322 int32_t x = mCurrentTouch.pointers[0].x;
3323 int32_t y = mCurrentTouch.pointers[0].y;
3324 if (isPointInsideSurfaceLocked(x, y)) {
3325 mLastTouch.clear();
3326 touchResult = DISPATCH_TOUCH;
3327 } else {
3328 touchResult = DROP_STROKE;
3329 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07003330 } else {
3331 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
3332 // Pointer just went down. Handle off-screen touches, if needed.
3333 int32_t x = mCurrentTouch.pointers[0].x;
3334 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003335 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07003336 // If exactly one pointer went down, check for virtual key hit.
3337 // Otherwise we will drop the entire stroke.
3338 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003339 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003340 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08003341 if (mContext->shouldDropVirtualKey(when, getDevice(),
3342 virtualKey->keyCode, virtualKey->scanCode)) {
3343 return DROP_STROKE;
3344 }
3345
Jeff Brown6328cdc2010-07-29 18:18:33 -07003346 mLocked.currentVirtualKey.down = true;
3347 mLocked.currentVirtualKey.downTime = when;
3348 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
3349 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07003350#if DEBUG_VIRTUAL_KEYS
3351 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07003352 mLocked.currentVirtualKey.keyCode,
3353 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07003354#endif
3355 keyEventAction = AKEY_EVENT_ACTION_DOWN;
3356 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
3357 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
3358 touchResult = SKIP_TOUCH;
3359 goto DispatchVirtualKey;
3360 }
3361 }
3362 return DROP_STROKE;
3363 }
3364 }
3365 return DISPATCH_TOUCH;
3366 }
3367
3368 DispatchVirtualKey:
3369 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07003370 keyCode = mLocked.currentVirtualKey.keyCode;
3371 scanCode = mLocked.currentVirtualKey.scanCode;
3372 downTime = mLocked.currentVirtualKey.downTime;
3373 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07003374
3375 // Dispatch virtual key.
3376 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07003377 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07003378 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
3379 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
3380 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003381}
3382
Jeff Brownefd32662011-03-08 15:13:06 -08003383void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
Jeff Brownfe508922011-01-18 15:10:10 -08003384 // Disable all virtual key touches that happen within a short time interval of the
3385 // most recent touch. The idea is to filter out stray virtual key presses when
3386 // interacting with the touch screen.
3387 //
3388 // Problems we're trying to solve:
3389 //
3390 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
3391 // virtual key area that is implemented by a separate touch panel and accidentally
3392 // triggers a virtual key.
3393 //
3394 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
3395 // area and accidentally triggers a virtual key. This often happens when virtual keys
3396 // are layed out below the screen near to where the on screen keyboard's space bar
3397 // is displayed.
Jeff Brown474dcb52011-06-14 20:22:50 -07003398 if (mConfig.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
3399 mContext->disableVirtualKeysUntil(when + mConfig.virtualKeyQuietTime);
Jeff Brownfe508922011-01-18 15:10:10 -08003400 }
3401}
3402
Jeff Brown6d0fec22010-07-23 21:28:06 -07003403void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
3404 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3405 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003406 if (currentPointerCount == 0 && lastPointerCount == 0) {
3407 return; // nothing to do!
3408 }
3409
Jeff Brownace13b12011-03-09 17:39:48 -08003410 // Update current touch coordinates.
Jeff Brownace13b12011-03-09 17:39:48 -08003411 float xPrecision, yPrecision;
Jeff Browna6111372011-07-14 21:48:23 -07003412 prepareTouches(&xPrecision, &yPrecision);
Jeff Brownace13b12011-03-09 17:39:48 -08003413
3414 // Dispatch motions.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003415 BitSet32 currentIdBits = mCurrentTouch.idBits;
3416 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003417 int32_t metaState = getContext()->getGlobalMetaState();
3418 int32_t buttonState = mCurrentTouch.buttonState;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003419
3420 if (currentIdBits == lastIdBits) {
3421 // No pointer id changes so this is a move event.
3422 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownace13b12011-03-09 17:39:48 -08003423 dispatchMotion(when, policyFlags, mTouchSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003424 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState,
3425 AMOTION_EVENT_EDGE_FLAG_NONE,
3426 mCurrentTouchProperties, mCurrentTouchCoords,
3427 mCurrentTouch.idToIndex, currentIdBits, -1,
Jeff Brownace13b12011-03-09 17:39:48 -08003428 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003429 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07003430 // There may be pointers going up and pointers going down and pointers moving
3431 // all at the same time.
Jeff Brownace13b12011-03-09 17:39:48 -08003432 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
3433 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07003434 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
Jeff Brownace13b12011-03-09 17:39:48 -08003435 BitSet32 dispatchedIdBits(lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07003436
Jeff Brownace13b12011-03-09 17:39:48 -08003437 // Update last coordinates of pointers that have moved so that we observe the new
3438 // pointer positions at the same time as other pointers that have just gone up.
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003439 bool moveNeeded = updateMovedPointers(
3440 mCurrentTouchProperties, mCurrentTouchCoords, mCurrentTouch.idToIndex,
3441 mLastTouchProperties, mLastTouchCoords, mLastTouch.idToIndex,
Jeff Brownace13b12011-03-09 17:39:48 -08003442 moveIdBits);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003443 if (buttonState != mLastTouch.buttonState) {
3444 moveNeeded = true;
3445 }
Jeff Brownc3db8582010-10-20 15:33:38 -07003446
Jeff Brownace13b12011-03-09 17:39:48 -08003447 // Dispatch pointer up events.
Jeff Brownc3db8582010-10-20 15:33:38 -07003448 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003449 uint32_t upId = upIdBits.firstMarkedBit();
3450 upIdBits.clearBit(upId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003451
Jeff Brownace13b12011-03-09 17:39:48 -08003452 dispatchMotion(when, policyFlags, mTouchSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003453 AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, buttonState, 0,
3454 mLastTouchProperties, mLastTouchCoords,
3455 mLastTouch.idToIndex, dispatchedIdBits, upId,
Jeff Brownace13b12011-03-09 17:39:48 -08003456 xPrecision, yPrecision, mDownTime);
3457 dispatchedIdBits.clearBit(upId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003458 }
3459
Jeff Brownc3db8582010-10-20 15:33:38 -07003460 // Dispatch move events if any of the remaining pointers moved from their old locations.
3461 // Although applications receive new locations as part of individual pointer up
3462 // events, they do not generally handle them except when presented in a move event.
3463 if (moveNeeded) {
Jeff Brownb6110c22011-04-01 16:15:13 -07003464 LOG_ASSERT(moveIdBits.value == dispatchedIdBits.value);
Jeff Brownace13b12011-03-09 17:39:48 -08003465 dispatchMotion(when, policyFlags, mTouchSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003466 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, 0,
3467 mCurrentTouchProperties, mCurrentTouchCoords,
3468 mCurrentTouch.idToIndex, dispatchedIdBits, -1,
Jeff Brownace13b12011-03-09 17:39:48 -08003469 xPrecision, yPrecision, mDownTime);
Jeff Brownc3db8582010-10-20 15:33:38 -07003470 }
3471
3472 // Dispatch pointer down events using the new pointer locations.
3473 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003474 uint32_t downId = downIdBits.firstMarkedBit();
3475 downIdBits.clearBit(downId);
Jeff Brownace13b12011-03-09 17:39:48 -08003476 dispatchedIdBits.markBit(downId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003477
Jeff Brownace13b12011-03-09 17:39:48 -08003478 if (dispatchedIdBits.count() == 1) {
3479 // First pointer is going down. Set down time.
Jeff Brown6d0fec22010-07-23 21:28:06 -07003480 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003481 }
3482
Jeff Brownace13b12011-03-09 17:39:48 -08003483 dispatchMotion(when, policyFlags, mTouchSource,
Jeff Browna6111372011-07-14 21:48:23 -07003484 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003485 mCurrentTouchProperties, mCurrentTouchCoords,
3486 mCurrentTouch.idToIndex, dispatchedIdBits, downId,
Jeff Brownace13b12011-03-09 17:39:48 -08003487 xPrecision, yPrecision, mDownTime);
3488 }
3489 }
3490
3491 // Update state for next time.
3492 for (uint32_t i = 0; i < currentPointerCount; i++) {
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003493 mLastTouchProperties[i].copyFrom(mCurrentTouchProperties[i]);
Jeff Brownace13b12011-03-09 17:39:48 -08003494 mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]);
3495 }
3496}
3497
Jeff Browna6111372011-07-14 21:48:23 -07003498void TouchInputMapper::prepareTouches(float* outXPrecision, float* outYPrecision) {
Jeff Brownace13b12011-03-09 17:39:48 -08003499 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3500 uint32_t lastPointerCount = mLastTouch.pointerCount;
3501
3502 AutoMutex _l(mLock);
3503
3504 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
3505 // display or surface coordinates (PointerCoords) and adjust for display orientation.
3506 for (uint32_t i = 0; i < currentPointerCount; i++) {
3507 const PointerData& in = mCurrentTouch.pointers[i];
3508
3509 // ToolMajor and ToolMinor
3510 float toolMajor, toolMinor;
3511 switch (mCalibration.toolSizeCalibration) {
3512 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
3513 toolMajor = in.toolMajor * mLocked.geometricScale;
3514 if (mRawAxes.toolMinor.valid) {
3515 toolMinor = in.toolMinor * mLocked.geometricScale;
3516 } else {
3517 toolMinor = toolMajor;
3518 }
3519 break;
3520 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
3521 toolMajor = in.toolMajor != 0
3522 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
3523 : 0;
3524 if (mRawAxes.toolMinor.valid) {
3525 toolMinor = in.toolMinor != 0
3526 ? in.toolMinor * mLocked.toolSizeLinearScale
3527 + mLocked.toolSizeLinearBias
3528 : 0;
3529 } else {
3530 toolMinor = toolMajor;
3531 }
3532 break;
3533 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
3534 if (in.toolMajor != 0) {
3535 float diameter = sqrtf(in.toolMajor
3536 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
3537 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
3538 } else {
3539 toolMajor = 0;
3540 }
3541 toolMinor = toolMajor;
3542 break;
3543 default:
3544 toolMajor = 0;
3545 toolMinor = 0;
3546 break;
3547 }
3548
3549 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
3550 toolMajor /= currentPointerCount;
3551 toolMinor /= currentPointerCount;
3552 }
3553
3554 // Pressure
3555 float rawPressure;
3556 switch (mCalibration.pressureSource) {
3557 case Calibration::PRESSURE_SOURCE_PRESSURE:
3558 rawPressure = in.pressure;
3559 break;
3560 case Calibration::PRESSURE_SOURCE_TOUCH:
3561 rawPressure = in.touchMajor;
3562 break;
3563 default:
3564 rawPressure = 0;
3565 }
3566
3567 float pressure;
3568 switch (mCalibration.pressureCalibration) {
3569 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3570 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3571 pressure = rawPressure * mLocked.pressureScale;
3572 break;
3573 default:
3574 pressure = 1;
3575 break;
3576 }
3577
3578 // TouchMajor and TouchMinor
3579 float touchMajor, touchMinor;
3580 switch (mCalibration.touchSizeCalibration) {
3581 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
3582 touchMajor = in.touchMajor * mLocked.geometricScale;
3583 if (mRawAxes.touchMinor.valid) {
3584 touchMinor = in.touchMinor * mLocked.geometricScale;
3585 } else {
3586 touchMinor = touchMajor;
3587 }
3588 break;
3589 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
3590 touchMajor = toolMajor * pressure;
3591 touchMinor = toolMinor * pressure;
3592 break;
3593 default:
3594 touchMajor = 0;
3595 touchMinor = 0;
3596 break;
3597 }
3598
3599 if (touchMajor > toolMajor) {
3600 touchMajor = toolMajor;
3601 }
3602 if (touchMinor > toolMinor) {
3603 touchMinor = toolMinor;
3604 }
3605
3606 // Size
3607 float size;
3608 switch (mCalibration.sizeCalibration) {
3609 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
3610 float rawSize = mRawAxes.toolMinor.valid
3611 ? avg(in.toolMajor, in.toolMinor)
3612 : in.toolMajor;
3613 size = rawSize * mLocked.sizeScale;
3614 break;
3615 }
3616 default:
3617 size = 0;
3618 break;
3619 }
3620
3621 // Orientation
3622 float orientation;
3623 switch (mCalibration.orientationCalibration) {
3624 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3625 orientation = in.orientation * mLocked.orientationScale;
3626 break;
3627 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3628 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3629 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3630 if (c1 != 0 || c2 != 0) {
3631 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brown2352b972011-04-12 22:39:53 -07003632 float scale = 1.0f + hypotf(c1, c2) / 16.0f;
Jeff Brownace13b12011-03-09 17:39:48 -08003633 touchMajor *= scale;
3634 touchMinor /= scale;
3635 toolMajor *= scale;
3636 toolMinor /= scale;
3637 } else {
3638 orientation = 0;
3639 }
3640 break;
3641 }
3642 default:
3643 orientation = 0;
3644 }
3645
Jeff Brown80fd47c2011-05-24 01:07:44 -07003646 // Distance
3647 float distance;
3648 switch (mCalibration.distanceCalibration) {
3649 case Calibration::DISTANCE_CALIBRATION_SCALED:
3650 distance = in.distance * mLocked.distanceScale;
3651 break;
3652 default:
3653 distance = 0;
3654 }
3655
Jeff Brownace13b12011-03-09 17:39:48 -08003656 // X and Y
3657 // Adjust coords for surface orientation.
3658 float x, y;
3659 switch (mLocked.surfaceOrientation) {
3660 case DISPLAY_ORIENTATION_90:
3661 x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3662 y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3663 orientation -= M_PI_2;
3664 if (orientation < - M_PI_2) {
3665 orientation += M_PI;
3666 }
3667 break;
3668 case DISPLAY_ORIENTATION_180:
3669 x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3670 y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3671 break;
3672 case DISPLAY_ORIENTATION_270:
3673 x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3674 y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3675 orientation += M_PI_2;
3676 if (orientation > M_PI_2) {
3677 orientation -= M_PI;
3678 }
3679 break;
3680 default:
3681 x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3682 y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3683 break;
3684 }
3685
3686 // Write output coords.
3687 PointerCoords& out = mCurrentTouchCoords[i];
3688 out.clear();
3689 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3690 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3691 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3692 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3693 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3694 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3695 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3696 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3697 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
Jeff Brown80fd47c2011-05-24 01:07:44 -07003698 if (distance != 0) {
3699 out.setAxisValue(AMOTION_EVENT_AXIS_DISTANCE, distance);
3700 }
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003701
3702 // Write output properties.
3703 PointerProperties& properties = mCurrentTouchProperties[i];
3704 properties.clear();
3705 properties.id = mCurrentTouch.pointers[i].id;
Jeff Brown49754db2011-07-01 17:37:58 -07003706 properties.toolType = mCurrentTouch.pointers[i].toolType;
Jeff Brownace13b12011-03-09 17:39:48 -08003707 }
3708
Jeff Brownace13b12011-03-09 17:39:48 -08003709 *outXPrecision = mLocked.orientedXPrecision;
3710 *outYPrecision = mLocked.orientedYPrecision;
3711}
3712
Jeff Brown79ac9692011-04-19 21:20:10 -07003713void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3714 bool isTimeout) {
Jeff Brownace13b12011-03-09 17:39:48 -08003715 // Update current gesture coordinates.
3716 bool cancelPreviousGesture, finishPreviousGesture;
Jeff Brown79ac9692011-04-19 21:20:10 -07003717 bool sendEvents = preparePointerGestures(when,
3718 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3719 if (!sendEvents) {
3720 return;
3721 }
Jeff Brown19c97d462011-06-01 12:33:19 -07003722 if (finishPreviousGesture) {
3723 cancelPreviousGesture = false;
3724 }
Jeff Brownace13b12011-03-09 17:39:48 -08003725
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003726 // Update the pointer presentation and spots.
3727 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3728 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_SPOT);
3729 if (finishPreviousGesture || cancelPreviousGesture) {
3730 mPointerController->clearSpots();
3731 }
Jeff Browncb5ffcf2011-06-06 20:03:18 -07003732 mPointerController->setSpots(mPointerGesture.currentGestureCoords,
3733 mPointerGesture.currentGestureIdToIndex,
3734 mPointerGesture.currentGestureIdBits);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07003735 } else {
3736 mPointerController->setPresentation(PointerControllerInterface::PRESENTATION_POINTER);
3737 }
Jeff Brown214eaf42011-05-26 19:17:02 -07003738
Jeff Brown538881e2011-05-25 18:23:38 -07003739 // Show or hide the pointer if needed.
3740 switch (mPointerGesture.currentGestureMode) {
3741 case PointerGesture::NEUTRAL:
3742 case PointerGesture::QUIET:
3743 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3744 && (mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3745 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)) {
3746 // Remind the user of where the pointer is after finishing a gesture with spots.
3747 mPointerController->unfade(PointerControllerInterface::TRANSITION_GRADUAL);
3748 }
3749 break;
3750 case PointerGesture::TAP:
3751 case PointerGesture::TAP_DRAG:
3752 case PointerGesture::BUTTON_CLICK_OR_DRAG:
3753 case PointerGesture::HOVER:
3754 case PointerGesture::PRESS:
3755 // Unfade the pointer when the current gesture manipulates the
3756 // area directly under the pointer.
3757 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3758 break;
3759 case PointerGesture::SWIPE:
3760 case PointerGesture::FREEFORM:
3761 // Fade the pointer when the current gesture manipulates a different
3762 // area and there are spots to guide the user experience.
3763 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3764 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
3765 } else {
3766 mPointerController->unfade(PointerControllerInterface::TRANSITION_IMMEDIATE);
3767 }
3768 break;
Jeff Brown2352b972011-04-12 22:39:53 -07003769 }
3770
Jeff Brownace13b12011-03-09 17:39:48 -08003771 // Send events!
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003772 int32_t metaState = getContext()->getGlobalMetaState();
3773 int32_t buttonState = mCurrentTouch.buttonState;
Jeff Brownace13b12011-03-09 17:39:48 -08003774
3775 // Update last coordinates of pointers that have moved so that we observe the new
3776 // pointer positions at the same time as other pointers that have just gone up.
Jeff Brown79ac9692011-04-19 21:20:10 -07003777 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
3778 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
3779 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown2352b972011-04-12 22:39:53 -07003780 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
Jeff Brownace13b12011-03-09 17:39:48 -08003781 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
3782 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
3783 bool moveNeeded = false;
3784 if (down && !cancelPreviousGesture && !finishPreviousGesture
Jeff Brown2352b972011-04-12 22:39:53 -07003785 && !mPointerGesture.lastGestureIdBits.isEmpty()
3786 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
Jeff Brownace13b12011-03-09 17:39:48 -08003787 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
3788 & mPointerGesture.lastGestureIdBits.value);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003789 moveNeeded = updateMovedPointers(mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003790 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003791 mPointerGesture.lastGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003792 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3793 movedGestureIdBits);
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003794 if (buttonState != mLastTouch.buttonState) {
3795 moveNeeded = true;
3796 }
Jeff Brownace13b12011-03-09 17:39:48 -08003797 }
3798
3799 // Send motion events for all pointers that went up or were canceled.
3800 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
3801 if (!dispatchedGestureIdBits.isEmpty()) {
3802 if (cancelPreviousGesture) {
3803 dispatchMotion(when, policyFlags, mPointerSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003804 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, buttonState,
3805 AMOTION_EVENT_EDGE_FLAG_NONE,
3806 mPointerGesture.lastGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003807 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3808 dispatchedGestureIdBits, -1,
3809 0, 0, mPointerGesture.downTime);
3810
3811 dispatchedGestureIdBits.clear();
3812 } else {
3813 BitSet32 upGestureIdBits;
3814 if (finishPreviousGesture) {
3815 upGestureIdBits = dispatchedGestureIdBits;
3816 } else {
3817 upGestureIdBits.value = dispatchedGestureIdBits.value
3818 & ~mPointerGesture.currentGestureIdBits.value;
3819 }
3820 while (!upGestureIdBits.isEmpty()) {
3821 uint32_t id = upGestureIdBits.firstMarkedBit();
3822 upGestureIdBits.clearBit(id);
3823
3824 dispatchMotion(when, policyFlags, mPointerSource,
3825 AMOTION_EVENT_ACTION_POINTER_UP, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003826 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3827 mPointerGesture.lastGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003828 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3829 dispatchedGestureIdBits, id,
3830 0, 0, mPointerGesture.downTime);
3831
3832 dispatchedGestureIdBits.clearBit(id);
3833 }
3834 }
3835 }
3836
3837 // Send motion events for all pointers that moved.
3838 if (moveNeeded) {
3839 dispatchMotion(when, policyFlags, mPointerSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003840 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3841 mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003842 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3843 dispatchedGestureIdBits, -1,
3844 0, 0, mPointerGesture.downTime);
3845 }
3846
3847 // Send motion events for all pointers that went down.
3848 if (down) {
3849 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
3850 & ~dispatchedGestureIdBits.value);
3851 while (!downGestureIdBits.isEmpty()) {
3852 uint32_t id = downGestureIdBits.firstMarkedBit();
3853 downGestureIdBits.clearBit(id);
3854 dispatchedGestureIdBits.markBit(id);
3855
Jeff Brownace13b12011-03-09 17:39:48 -08003856 if (dispatchedGestureIdBits.count() == 1) {
Jeff Brownace13b12011-03-09 17:39:48 -08003857 mPointerGesture.downTime = when;
3858 }
3859
3860 dispatchMotion(when, policyFlags, mPointerSource,
Jeff Browna6111372011-07-14 21:48:23 -07003861 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, buttonState, 0,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003862 mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003863 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3864 dispatchedGestureIdBits, id,
3865 0, 0, mPointerGesture.downTime);
3866 }
3867 }
3868
Jeff Brownace13b12011-03-09 17:39:48 -08003869 // Send motion events for hover.
3870 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
3871 dispatchMotion(when, policyFlags, mPointerSource,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003872 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
3873 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3874 mPointerGesture.currentGestureProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08003875 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3876 mPointerGesture.currentGestureIdBits, -1,
3877 0, 0, mPointerGesture.downTime);
Jeff Brown81346812011-06-28 20:08:48 -07003878 } else if (dispatchedGestureIdBits.isEmpty()
3879 && !mPointerGesture.lastGestureIdBits.isEmpty()) {
3880 // Synthesize a hover move event after all pointers go up to indicate that
3881 // the pointer is hovering again even if the user is not currently touching
3882 // the touch pad. This ensures that a view will receive a fresh hover enter
3883 // event after a tap.
3884 float x, y;
3885 mPointerController->getPosition(&x, &y);
3886
3887 PointerProperties pointerProperties;
3888 pointerProperties.clear();
3889 pointerProperties.id = 0;
Jeff Brown49754db2011-07-01 17:37:58 -07003890 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brown81346812011-06-28 20:08:48 -07003891
3892 PointerCoords pointerCoords;
3893 pointerCoords.clear();
3894 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3895 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3896
3897 getDispatcher()->notifyMotion(when, getDeviceId(), mPointerSource, policyFlags,
3898 AMOTION_EVENT_ACTION_HOVER_MOVE, 0,
3899 metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
3900 1, &pointerProperties, &pointerCoords, 0, 0, mPointerGesture.downTime);
Jeff Brownace13b12011-03-09 17:39:48 -08003901 }
3902
3903 // Update state.
3904 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
3905 if (!down) {
Jeff Brownace13b12011-03-09 17:39:48 -08003906 mPointerGesture.lastGestureIdBits.clear();
3907 } else {
Jeff Brownace13b12011-03-09 17:39:48 -08003908 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
3909 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
3910 uint32_t id = idBits.firstMarkedBit();
3911 idBits.clearBit(id);
3912 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07003913 mPointerGesture.lastGestureProperties[index].copyFrom(
3914 mPointerGesture.currentGestureProperties[index]);
Jeff Brownace13b12011-03-09 17:39:48 -08003915 mPointerGesture.lastGestureCoords[index].copyFrom(
3916 mPointerGesture.currentGestureCoords[index]);
3917 mPointerGesture.lastGestureIdToIndex[id] = index;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003918 }
3919 }
3920}
3921
Jeff Brown79ac9692011-04-19 21:20:10 -07003922bool TouchInputMapper::preparePointerGestures(nsecs_t when,
3923 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
Jeff Brownace13b12011-03-09 17:39:48 -08003924 *outCancelPreviousGesture = false;
3925 *outFinishPreviousGesture = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003926
Jeff Brownace13b12011-03-09 17:39:48 -08003927 AutoMutex _l(mLock);
Jeff Brown6328cdc2010-07-29 18:18:33 -07003928
Jeff Brown79ac9692011-04-19 21:20:10 -07003929 // Handle TAP timeout.
3930 if (isTimeout) {
3931#if DEBUG_GESTURES
3932 LOGD("Gestures: Processing timeout");
3933#endif
3934
3935 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
Jeff Brown474dcb52011-06-14 20:22:50 -07003936 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
Jeff Brown79ac9692011-04-19 21:20:10 -07003937 // The tap/drag timeout has not yet expired.
Jeff Brown214eaf42011-05-26 19:17:02 -07003938 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime
Jeff Brown474dcb52011-06-14 20:22:50 -07003939 + mConfig.pointerGestureTapDragInterval);
Jeff Brown79ac9692011-04-19 21:20:10 -07003940 } else {
3941 // The tap is finished.
3942#if DEBUG_GESTURES
3943 LOGD("Gestures: TAP finished");
3944#endif
3945 *outFinishPreviousGesture = true;
3946
3947 mPointerGesture.activeGestureId = -1;
3948 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
3949 mPointerGesture.currentGestureIdBits.clear();
3950
Jeff Brown19c97d462011-06-01 12:33:19 -07003951 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown79ac9692011-04-19 21:20:10 -07003952 return true;
3953 }
3954 }
3955
3956 // We did not handle this timeout.
3957 return false;
3958 }
3959
Jeff Brownace13b12011-03-09 17:39:48 -08003960 // Update the velocity tracker.
3961 {
3962 VelocityTracker::Position positions[MAX_POINTERS];
3963 uint32_t count = 0;
3964 for (BitSet32 idBits(mCurrentTouch.idBits); !idBits.isEmpty(); count++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003965 uint32_t id = idBits.firstMarkedBit();
3966 idBits.clearBit(id);
Jeff Brownace13b12011-03-09 17:39:48 -08003967 uint32_t index = mCurrentTouch.idToIndex[id];
3968 positions[count].x = mCurrentTouch.pointers[index].x
3969 * mLocked.pointerGestureXMovementScale;
3970 positions[count].y = mCurrentTouch.pointers[index].y
3971 * mLocked.pointerGestureYMovementScale;
3972 }
3973 mPointerGesture.velocityTracker.addMovement(when, mCurrentTouch.idBits, positions);
3974 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003975
Jeff Brownace13b12011-03-09 17:39:48 -08003976 // Pick a new active touch id if needed.
3977 // Choose an arbitrary pointer that just went down, if there is one.
3978 // Otherwise choose an arbitrary remaining pointer.
3979 // This guarantees we always have an active touch id when there is at least one pointer.
Jeff Brown2352b972011-04-12 22:39:53 -07003980 // We keep the same active touch id for as long as possible.
3981 bool activeTouchChanged = false;
3982 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
3983 int32_t activeTouchId = lastActiveTouchId;
3984 if (activeTouchId < 0) {
3985 if (!mCurrentTouch.idBits.isEmpty()) {
3986 activeTouchChanged = true;
3987 activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3988 mPointerGesture.firstTouchTime = when;
Jeff Brownace13b12011-03-09 17:39:48 -08003989 }
Jeff Brown2352b972011-04-12 22:39:53 -07003990 } else if (!mCurrentTouch.idBits.hasBit(activeTouchId)) {
3991 activeTouchChanged = true;
3992 if (!mCurrentTouch.idBits.isEmpty()) {
3993 activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3994 } else {
3995 activeTouchId = mPointerGesture.activeTouchId = -1;
Jeff Brownace13b12011-03-09 17:39:48 -08003996 }
3997 }
3998
3999 // Determine whether we are in quiet time.
Jeff Brown2352b972011-04-12 22:39:53 -07004000 bool isQuietTime = false;
4001 if (activeTouchId < 0) {
4002 mPointerGesture.resetQuietTime();
4003 } else {
Jeff Brown474dcb52011-06-14 20:22:50 -07004004 isQuietTime = when < mPointerGesture.quietTime + mConfig.pointerGestureQuietInterval;
Jeff Brown2352b972011-04-12 22:39:53 -07004005 if (!isQuietTime) {
4006 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
4007 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
4008 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
4009 && mCurrentTouch.pointerCount < 2) {
4010 // Enter quiet time when exiting swipe or freeform state.
4011 // This is to prevent accidentally entering the hover state and flinging the
4012 // pointer when finishing a swipe and there is still one pointer left onscreen.
4013 isQuietTime = true;
Jeff Brown79ac9692011-04-19 21:20:10 -07004014 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown2352b972011-04-12 22:39:53 -07004015 && mCurrentTouch.pointerCount >= 2
4016 && !isPointerDown(mCurrentTouch.buttonState)) {
4017 // Enter quiet time when releasing the button and there are still two or more
4018 // fingers down. This may indicate that one finger was used to press the button
4019 // but it has not gone up yet.
4020 isQuietTime = true;
4021 }
4022 if (isQuietTime) {
4023 mPointerGesture.quietTime = when;
4024 }
Jeff Brownace13b12011-03-09 17:39:48 -08004025 }
4026 }
4027
4028 // Switch states based on button and pointer state.
4029 if (isQuietTime) {
4030 // Case 1: Quiet time. (QUIET)
4031#if DEBUG_GESTURES
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004032 LOGD("Gestures: QUIET for next %0.3fms", (mPointerGesture.quietTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004033 + mConfig.pointerGestureQuietInterval - when) * 0.000001f);
Jeff Brownace13b12011-03-09 17:39:48 -08004034#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004035 if (mPointerGesture.lastGestureMode != PointerGesture::QUIET) {
4036 *outFinishPreviousGesture = true;
4037 }
Jeff Brownace13b12011-03-09 17:39:48 -08004038
4039 mPointerGesture.activeGestureId = -1;
4040 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
Jeff Brownace13b12011-03-09 17:39:48 -08004041 mPointerGesture.currentGestureIdBits.clear();
Jeff Brown2352b972011-04-12 22:39:53 -07004042
Jeff Brown19c97d462011-06-01 12:33:19 -07004043 mPointerGesture.pointerVelocityControl.reset();
Jeff Brownace13b12011-03-09 17:39:48 -08004044 } else if (isPointerDown(mCurrentTouch.buttonState)) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004045 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
Jeff Brownace13b12011-03-09 17:39:48 -08004046 // The pointer follows the active touch point.
4047 // Emit DOWN, MOVE, UP events at the pointer location.
4048 //
4049 // Only the active touch matters; other fingers are ignored. This policy helps
4050 // to handle the case where the user places a second finger on the touch pad
4051 // to apply the necessary force to depress an integrated button below the surface.
4052 // We don't want the second finger to be delivered to applications.
4053 //
4054 // For this to work well, we need to make sure to track the pointer that is really
4055 // active. If the user first puts one finger down to click then adds another
4056 // finger to drag then the active pointer should switch to the finger that is
4057 // being dragged.
4058#if DEBUG_GESTURES
Jeff Brown79ac9692011-04-19 21:20:10 -07004059 LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
Jeff Brownace13b12011-03-09 17:39:48 -08004060 "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount);
4061#endif
4062 // Reset state when just starting.
Jeff Brown79ac9692011-04-19 21:20:10 -07004063 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
Jeff Brownace13b12011-03-09 17:39:48 -08004064 *outFinishPreviousGesture = true;
4065 mPointerGesture.activeGestureId = 0;
4066 }
4067
4068 // Switch pointers if needed.
4069 // Find the fastest pointer and follow it.
Jeff Brown19c97d462011-06-01 12:33:19 -07004070 if (activeTouchId >= 0 && mCurrentTouch.pointerCount > 1) {
4071 int32_t bestId = -1;
Jeff Brown474dcb52011-06-14 20:22:50 -07004072 float bestSpeed = mConfig.pointerGestureDragMinSwitchSpeed;
Jeff Brown19c97d462011-06-01 12:33:19 -07004073 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
4074 uint32_t id = mCurrentTouch.pointers[i].id;
4075 float vx, vy;
4076 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
4077 float speed = hypotf(vx, vy);
4078 if (speed > bestSpeed) {
4079 bestId = id;
4080 bestSpeed = speed;
Jeff Brownace13b12011-03-09 17:39:48 -08004081 }
Jeff Brown8d608662010-08-30 03:02:23 -07004082 }
Jeff Brown19c97d462011-06-01 12:33:19 -07004083 }
4084 if (bestId >= 0 && bestId != activeTouchId) {
4085 mPointerGesture.activeTouchId = activeTouchId = bestId;
4086 activeTouchChanged = true;
Jeff Brownace13b12011-03-09 17:39:48 -08004087#if DEBUG_GESTURES
Jeff Brown19c97d462011-06-01 12:33:19 -07004088 LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
4089 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
Jeff Brownace13b12011-03-09 17:39:48 -08004090#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07004091 }
Jeff Brown19c97d462011-06-01 12:33:19 -07004092 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004093
Jeff Brown19c97d462011-06-01 12:33:19 -07004094 if (activeTouchId >= 0 && mLastTouch.idBits.hasBit(activeTouchId)) {
4095 const PointerData& currentPointer =
4096 mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
4097 const PointerData& lastPointer =
4098 mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
4099 float deltaX = (currentPointer.x - lastPointer.x)
4100 * mLocked.pointerGestureXMovementScale;
4101 float deltaY = (currentPointer.y - lastPointer.y)
4102 * mLocked.pointerGestureYMovementScale;
Jeff Brown2352b972011-04-12 22:39:53 -07004103
Jeff Brown612891e2011-07-15 20:44:17 -07004104 rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07004105 mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
4106
4107 // Move the pointer using a relative motion.
4108 // When using spots, the click will occur at the position of the anchor
4109 // spot and all other spots will move there.
4110 mPointerController->move(deltaX, deltaY);
4111 } else {
4112 mPointerGesture.pointerVelocityControl.reset();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004113 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004114
Jeff Brownace13b12011-03-09 17:39:48 -08004115 float x, y;
4116 mPointerController->getPosition(&x, &y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08004117
Jeff Brown79ac9692011-04-19 21:20:10 -07004118 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
Jeff Brownace13b12011-03-09 17:39:48 -08004119 mPointerGesture.currentGestureIdBits.clear();
4120 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4121 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004122 mPointerGesture.currentGestureProperties[0].clear();
4123 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
Jeff Brown49754db2011-07-01 17:37:58 -07004124 mPointerGesture.currentGestureProperties[0].toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004125 mPointerGesture.currentGestureCoords[0].clear();
4126 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4127 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4128 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4129 } else if (mCurrentTouch.pointerCount == 0) {
4130 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004131 if (mPointerGesture.lastGestureMode != PointerGesture::NEUTRAL) {
4132 *outFinishPreviousGesture = true;
4133 }
Jeff Brownace13b12011-03-09 17:39:48 -08004134
Jeff Brown79ac9692011-04-19 21:20:10 -07004135 // Watch for taps coming out of HOVER or TAP_DRAG mode.
Jeff Brown214eaf42011-05-26 19:17:02 -07004136 // Checking for taps after TAP_DRAG allows us to detect double-taps.
Jeff Brownace13b12011-03-09 17:39:48 -08004137 bool tapped = false;
Jeff Brown79ac9692011-04-19 21:20:10 -07004138 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
4139 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
Jeff Brown2352b972011-04-12 22:39:53 -07004140 && mLastTouch.pointerCount == 1) {
Jeff Brown474dcb52011-06-14 20:22:50 -07004141 if (when <= mPointerGesture.tapDownTime + mConfig.pointerGestureTapInterval) {
Jeff Brownace13b12011-03-09 17:39:48 -08004142 float x, y;
4143 mPointerController->getPosition(&x, &y);
Jeff Brown474dcb52011-06-14 20:22:50 -07004144 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4145 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
Jeff Brownace13b12011-03-09 17:39:48 -08004146#if DEBUG_GESTURES
4147 LOGD("Gestures: TAP");
4148#endif
Jeff Brown79ac9692011-04-19 21:20:10 -07004149
4150 mPointerGesture.tapUpTime = when;
Jeff Brown214eaf42011-05-26 19:17:02 -07004151 getContext()->requestTimeoutAtTime(when
Jeff Brown474dcb52011-06-14 20:22:50 -07004152 + mConfig.pointerGestureTapDragInterval);
Jeff Brown79ac9692011-04-19 21:20:10 -07004153
Jeff Brownace13b12011-03-09 17:39:48 -08004154 mPointerGesture.activeGestureId = 0;
4155 mPointerGesture.currentGestureMode = PointerGesture::TAP;
Jeff Brownace13b12011-03-09 17:39:48 -08004156 mPointerGesture.currentGestureIdBits.clear();
4157 mPointerGesture.currentGestureIdBits.markBit(
4158 mPointerGesture.activeGestureId);
4159 mPointerGesture.currentGestureIdToIndex[
4160 mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004161 mPointerGesture.currentGestureProperties[0].clear();
4162 mPointerGesture.currentGestureProperties[0].id =
4163 mPointerGesture.activeGestureId;
4164 mPointerGesture.currentGestureProperties[0].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004165 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004166 mPointerGesture.currentGestureCoords[0].clear();
4167 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown2352b972011-04-12 22:39:53 -07004168 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
Jeff Brownace13b12011-03-09 17:39:48 -08004169 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown2352b972011-04-12 22:39:53 -07004170 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
Jeff Brownace13b12011-03-09 17:39:48 -08004171 mPointerGesture.currentGestureCoords[0].setAxisValue(
4172 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown2352b972011-04-12 22:39:53 -07004173
Jeff Brownace13b12011-03-09 17:39:48 -08004174 tapped = true;
4175 } else {
4176#if DEBUG_GESTURES
4177 LOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
Jeff Brown2352b972011-04-12 22:39:53 -07004178 x - mPointerGesture.tapX,
4179 y - mPointerGesture.tapY);
Jeff Brownace13b12011-03-09 17:39:48 -08004180#endif
4181 }
4182 } else {
4183#if DEBUG_GESTURES
Jeff Brown79ac9692011-04-19 21:20:10 -07004184 LOGD("Gestures: Not a TAP, %0.3fms since down",
4185 (when - mPointerGesture.tapDownTime) * 0.000001f);
Jeff Brownace13b12011-03-09 17:39:48 -08004186#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07004187 }
Jeff Brownace13b12011-03-09 17:39:48 -08004188 }
Jeff Brown2352b972011-04-12 22:39:53 -07004189
Jeff Brown19c97d462011-06-01 12:33:19 -07004190 mPointerGesture.pointerVelocityControl.reset();
4191
Jeff Brownace13b12011-03-09 17:39:48 -08004192 if (!tapped) {
4193#if DEBUG_GESTURES
4194 LOGD("Gestures: NEUTRAL");
4195#endif
4196 mPointerGesture.activeGestureId = -1;
4197 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
Jeff Brownace13b12011-03-09 17:39:48 -08004198 mPointerGesture.currentGestureIdBits.clear();
4199 }
4200 } else if (mCurrentTouch.pointerCount == 1) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004201 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
Jeff Brownace13b12011-03-09 17:39:48 -08004202 // The pointer follows the active touch point.
Jeff Brown79ac9692011-04-19 21:20:10 -07004203 // When in HOVER, emit HOVER_MOVE events at the pointer location.
4204 // When in TAP_DRAG, emit MOVE events at the pointer location.
Jeff Brownb6110c22011-04-01 16:15:13 -07004205 LOG_ASSERT(activeTouchId >= 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004206
Jeff Brown79ac9692011-04-19 21:20:10 -07004207 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
4208 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
Jeff Brown474dcb52011-06-14 20:22:50 -07004209 if (when <= mPointerGesture.tapUpTime + mConfig.pointerGestureTapDragInterval) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004210 float x, y;
4211 mPointerController->getPosition(&x, &y);
Jeff Brown474dcb52011-06-14 20:22:50 -07004212 if (fabs(x - mPointerGesture.tapX) <= mConfig.pointerGestureTapSlop
4213 && fabs(y - mPointerGesture.tapY) <= mConfig.pointerGestureTapSlop) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004214 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4215 } else {
Jeff Brownace13b12011-03-09 17:39:48 -08004216#if DEBUG_GESTURES
Jeff Brown79ac9692011-04-19 21:20:10 -07004217 LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
4218 x - mPointerGesture.tapX,
4219 y - mPointerGesture.tapY);
Jeff Brownace13b12011-03-09 17:39:48 -08004220#endif
Jeff Brown79ac9692011-04-19 21:20:10 -07004221 }
4222 } else {
4223#if DEBUG_GESTURES
4224 LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
4225 (when - mPointerGesture.tapUpTime) * 0.000001f);
4226#endif
4227 }
4228 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
4229 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
4230 }
Jeff Brownace13b12011-03-09 17:39:48 -08004231
4232 if (mLastTouch.idBits.hasBit(activeTouchId)) {
4233 const PointerData& currentPointer =
4234 mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
4235 const PointerData& lastPointer =
4236 mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
4237 float deltaX = (currentPointer.x - lastPointer.x)
4238 * mLocked.pointerGestureXMovementScale;
4239 float deltaY = (currentPointer.y - lastPointer.y)
4240 * mLocked.pointerGestureYMovementScale;
Jeff Brown2352b972011-04-12 22:39:53 -07004241
Jeff Brown612891e2011-07-15 20:44:17 -07004242 rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07004243 mPointerGesture.pointerVelocityControl.move(when, &deltaX, &deltaY);
4244
Jeff Brown2352b972011-04-12 22:39:53 -07004245 // Move the pointer using a relative motion.
Jeff Brown79ac9692011-04-19 21:20:10 -07004246 // When using spots, the hover or drag will occur at the position of the anchor spot.
Jeff Brownace13b12011-03-09 17:39:48 -08004247 mPointerController->move(deltaX, deltaY);
Jeff Brown19c97d462011-06-01 12:33:19 -07004248 } else {
4249 mPointerGesture.pointerVelocityControl.reset();
Jeff Brownace13b12011-03-09 17:39:48 -08004250 }
4251
Jeff Brown79ac9692011-04-19 21:20:10 -07004252 bool down;
4253 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
4254#if DEBUG_GESTURES
4255 LOGD("Gestures: TAP_DRAG");
4256#endif
4257 down = true;
4258 } else {
4259#if DEBUG_GESTURES
4260 LOGD("Gestures: HOVER");
4261#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004262 if (mPointerGesture.lastGestureMode != PointerGesture::HOVER) {
4263 *outFinishPreviousGesture = true;
4264 }
Jeff Brown79ac9692011-04-19 21:20:10 -07004265 mPointerGesture.activeGestureId = 0;
4266 down = false;
4267 }
Jeff Brownace13b12011-03-09 17:39:48 -08004268
4269 float x, y;
4270 mPointerController->getPosition(&x, &y);
4271
Jeff Brownace13b12011-03-09 17:39:48 -08004272 mPointerGesture.currentGestureIdBits.clear();
4273 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4274 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004275 mPointerGesture.currentGestureProperties[0].clear();
4276 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4277 mPointerGesture.currentGestureProperties[0].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004278 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004279 mPointerGesture.currentGestureCoords[0].clear();
4280 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4281 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown79ac9692011-04-19 21:20:10 -07004282 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
4283 down ? 1.0f : 0.0f);
4284
Jeff Brownace13b12011-03-09 17:39:48 -08004285 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brown79ac9692011-04-19 21:20:10 -07004286 mPointerGesture.resetTap();
4287 mPointerGesture.tapDownTime = when;
Jeff Brown2352b972011-04-12 22:39:53 -07004288 mPointerGesture.tapX = x;
4289 mPointerGesture.tapY = y;
4290 }
Jeff Brownace13b12011-03-09 17:39:48 -08004291 } else {
Jeff Brown2352b972011-04-12 22:39:53 -07004292 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
4293 // We need to provide feedback for each finger that goes down so we cannot wait
4294 // for the fingers to move before deciding what to do.
Jeff Brownace13b12011-03-09 17:39:48 -08004295 //
Jeff Brown2352b972011-04-12 22:39:53 -07004296 // The ambiguous case is deciding what to do when there are two fingers down but they
4297 // have not moved enough to determine whether they are part of a drag or part of a
4298 // freeform gesture, or just a press or long-press at the pointer location.
4299 //
4300 // When there are two fingers we start with the PRESS hypothesis and we generate a
4301 // down at the pointer location.
4302 //
4303 // When the two fingers move enough or when additional fingers are added, we make
4304 // a decision to transition into SWIPE or FREEFORM mode accordingly.
Jeff Brownb6110c22011-04-01 16:15:13 -07004305 LOG_ASSERT(activeTouchId >= 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004306
Jeff Brown214eaf42011-05-26 19:17:02 -07004307 bool settled = when >= mPointerGesture.firstTouchTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004308 + mConfig.pointerGestureMultitouchSettleInterval;
Jeff Brown2352b972011-04-12 22:39:53 -07004309 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
Jeff Brownace13b12011-03-09 17:39:48 -08004310 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
4311 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
Jeff Brownace13b12011-03-09 17:39:48 -08004312 *outFinishPreviousGesture = true;
Jeff Brown19c97d462011-06-01 12:33:19 -07004313 } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
4314 // Additional pointers have gone down but not yet settled.
4315 // Reset the gesture.
4316#if DEBUG_GESTURES
4317 LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004318 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004319 + mConfig.pointerGestureMultitouchSettleInterval - when)
Jeff Brown19c97d462011-06-01 12:33:19 -07004320 * 0.000001f);
4321#endif
4322 *outCancelPreviousGesture = true;
4323 } else {
4324 // Continue previous gesture.
4325 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
4326 }
4327
4328 if (*outFinishPreviousGesture || *outCancelPreviousGesture) {
Jeff Brown2352b972011-04-12 22:39:53 -07004329 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
4330 mPointerGesture.activeGestureId = 0;
Jeff Brown538881e2011-05-25 18:23:38 -07004331 mPointerGesture.referenceIdBits.clear();
Jeff Brown19c97d462011-06-01 12:33:19 -07004332 mPointerGesture.pointerVelocityControl.reset();
Jeff Brownace13b12011-03-09 17:39:48 -08004333
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004334 // Use the centroid and pointer location as the reference points for the gesture.
Jeff Brown2352b972011-04-12 22:39:53 -07004335#if DEBUG_GESTURES
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004336 LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
4337 "settle time remaining %0.3fms", (mPointerGesture.firstTouchTime
Jeff Brown474dcb52011-06-14 20:22:50 -07004338 + mConfig.pointerGestureMultitouchSettleInterval - when)
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004339 * 0.000001f);
Jeff Brown2352b972011-04-12 22:39:53 -07004340#endif
Jeff Browncb5ffcf2011-06-06 20:03:18 -07004341 mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
4342 &mPointerGesture.referenceTouchY);
4343 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
4344 &mPointerGesture.referenceGestureY);
Jeff Brown2352b972011-04-12 22:39:53 -07004345 }
Jeff Brownace13b12011-03-09 17:39:48 -08004346
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004347 // Clear the reference deltas for fingers not yet included in the reference calculation.
4348 for (BitSet32 idBits(mCurrentTouch.idBits.value & ~mPointerGesture.referenceIdBits.value);
4349 !idBits.isEmpty(); ) {
4350 uint32_t id = idBits.firstMarkedBit();
4351 idBits.clearBit(id);
4352
4353 mPointerGesture.referenceDeltas[id].dx = 0;
4354 mPointerGesture.referenceDeltas[id].dy = 0;
4355 }
4356 mPointerGesture.referenceIdBits = mCurrentTouch.idBits;
4357
4358 // Add delta for all fingers and calculate a common movement delta.
4359 float commonDeltaX = 0, commonDeltaY = 0;
4360 BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
4361 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
4362 bool first = (idBits == commonIdBits);
4363 uint32_t id = idBits.firstMarkedBit();
4364 idBits.clearBit(id);
4365
4366 const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
4367 const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
4368 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4369 delta.dx += cpd.x - lpd.x;
4370 delta.dy += cpd.y - lpd.y;
4371
4372 if (first) {
4373 commonDeltaX = delta.dx;
4374 commonDeltaY = delta.dy;
Jeff Brown2352b972011-04-12 22:39:53 -07004375 } else {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004376 commonDeltaX = calculateCommonVector(commonDeltaX, delta.dx);
4377 commonDeltaY = calculateCommonVector(commonDeltaY, delta.dy);
4378 }
4379 }
Jeff Brownace13b12011-03-09 17:39:48 -08004380
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004381 // Consider transitions from PRESS to SWIPE or MULTITOUCH.
4382 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
4383 float dist[MAX_POINTER_ID + 1];
4384 int32_t distOverThreshold = 0;
4385 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
4386 uint32_t id = idBits.firstMarkedBit();
4387 idBits.clearBit(id);
Jeff Brownace13b12011-03-09 17:39:48 -08004388
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004389 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
4390 dist[id] = hypotf(delta.dx * mLocked.pointerGestureXZoomScale,
4391 delta.dy * mLocked.pointerGestureYZoomScale);
Jeff Brown474dcb52011-06-14 20:22:50 -07004392 if (dist[id] > mConfig.pointerGestureMultitouchMinDistance) {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004393 distOverThreshold += 1;
4394 }
4395 }
4396
4397 // Only transition when at least two pointers have moved further than
4398 // the minimum distance threshold.
4399 if (distOverThreshold >= 2) {
4400 float d;
4401 if (mCurrentTouch.pointerCount > 2) {
4402 // There are more than two pointers, switch to FREEFORM.
Jeff Brown2352b972011-04-12 22:39:53 -07004403#if DEBUG_GESTURES
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004404 LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
4405 mCurrentTouch.pointerCount);
Jeff Brown2352b972011-04-12 22:39:53 -07004406#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004407 *outCancelPreviousGesture = true;
4408 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4409 } else if (((d = distance(
4410 mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
4411 mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
4412 > mLocked.pointerGestureMaxSwipeWidth)) {
4413 // There are two pointers but they are too far apart for a SWIPE,
4414 // switch to FREEFORM.
Jeff Brown2352b972011-04-12 22:39:53 -07004415#if DEBUG_GESTURES
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004416 LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
4417 d, mLocked.pointerGestureMaxSwipeWidth);
Jeff Brown2352b972011-04-12 22:39:53 -07004418#endif
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004419 *outCancelPreviousGesture = true;
4420 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4421 } else {
4422 // There are two pointers. Wait for both pointers to start moving
4423 // before deciding whether this is a SWIPE or FREEFORM gesture.
4424 uint32_t id1 = mCurrentTouch.pointers[0].id;
4425 uint32_t id2 = mCurrentTouch.pointers[1].id;
4426 float dist1 = dist[id1];
4427 float dist2 = dist[id2];
Jeff Brown474dcb52011-06-14 20:22:50 -07004428 if (dist1 >= mConfig.pointerGestureMultitouchMinDistance
4429 && dist2 >= mConfig.pointerGestureMultitouchMinDistance) {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004430 // Calculate the dot product of the displacement vectors.
4431 // When the vectors are oriented in approximately the same direction,
4432 // the angle betweeen them is near zero and the cosine of the angle
4433 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
4434 PointerGesture::Delta& delta1 = mPointerGesture.referenceDeltas[id1];
4435 PointerGesture::Delta& delta2 = mPointerGesture.referenceDeltas[id2];
Jeff Brown6674d9b2011-06-07 16:50:14 -07004436 float dx1 = delta1.dx * mLocked.pointerGestureXZoomScale;
4437 float dy1 = delta1.dy * mLocked.pointerGestureYZoomScale;
4438 float dx2 = delta2.dx * mLocked.pointerGestureXZoomScale;
4439 float dy2 = delta2.dy * mLocked.pointerGestureYZoomScale;
4440 float dot = dx1 * dx2 + dy1 * dy2;
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004441 float cosine = dot / (dist1 * dist2); // denominator always > 0
Jeff Brown474dcb52011-06-14 20:22:50 -07004442 if (cosine >= mConfig.pointerGestureSwipeTransitionAngleCosine) {
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004443 // Pointers are moving in the same direction. Switch to SWIPE.
4444#if DEBUG_GESTURES
4445 LOGD("Gestures: PRESS transitioned to SWIPE, "
4446 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4447 "cosine %0.3f >= %0.3f",
Jeff Brown474dcb52011-06-14 20:22:50 -07004448 dist1, mConfig.pointerGestureMultitouchMinDistance,
4449 dist2, mConfig.pointerGestureMultitouchMinDistance,
4450 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004451#endif
4452 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
4453 } else {
4454 // Pointers are moving in different directions. Switch to FREEFORM.
4455#if DEBUG_GESTURES
4456 LOGD("Gestures: PRESS transitioned to FREEFORM, "
4457 "dist1 %0.3f >= %0.3f, dist2 %0.3f >= %0.3f, "
4458 "cosine %0.3f < %0.3f",
Jeff Brown474dcb52011-06-14 20:22:50 -07004459 dist1, mConfig.pointerGestureMultitouchMinDistance,
4460 dist2, mConfig.pointerGestureMultitouchMinDistance,
4461 cosine, mConfig.pointerGestureSwipeTransitionAngleCosine);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004462#endif
4463 *outCancelPreviousGesture = true;
4464 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
4465 }
Jeff Brownace13b12011-03-09 17:39:48 -08004466 }
4467 }
Jeff Brownace13b12011-03-09 17:39:48 -08004468 }
4469 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
Jeff Brown2352b972011-04-12 22:39:53 -07004470 // Switch from SWIPE to FREEFORM if additional pointers go down.
4471 // Cancel previous gesture.
4472 if (mCurrentTouch.pointerCount > 2) {
4473#if DEBUG_GESTURES
4474 LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
4475 mCurrentTouch.pointerCount);
4476#endif
Jeff Brownace13b12011-03-09 17:39:48 -08004477 *outCancelPreviousGesture = true;
4478 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
Jeff Brown6328cdc2010-07-29 18:18:33 -07004479 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004480 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004481
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004482 // Move the reference points based on the overall group motion of the fingers
4483 // except in PRESS mode while waiting for a transition to occur.
4484 if (mPointerGesture.currentGestureMode != PointerGesture::PRESS
4485 && (commonDeltaX || commonDeltaY)) {
4486 for (BitSet32 idBits(mPointerGesture.referenceIdBits); !idBits.isEmpty(); ) {
Jeff Brown2352b972011-04-12 22:39:53 -07004487 uint32_t id = idBits.firstMarkedBit();
4488 idBits.clearBit(id);
4489
Jeff Brown538881e2011-05-25 18:23:38 -07004490 PointerGesture::Delta& delta = mPointerGesture.referenceDeltas[id];
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004491 delta.dx = 0;
4492 delta.dy = 0;
Jeff Brown2352b972011-04-12 22:39:53 -07004493 }
4494
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004495 mPointerGesture.referenceTouchX += commonDeltaX;
4496 mPointerGesture.referenceTouchY += commonDeltaY;
Jeff Brown538881e2011-05-25 18:23:38 -07004497
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004498 commonDeltaX *= mLocked.pointerGestureXMovementScale;
4499 commonDeltaY *= mLocked.pointerGestureYMovementScale;
Jeff Brown612891e2011-07-15 20:44:17 -07004500
4501 rotateDelta(mLocked.surfaceOrientation, &commonDeltaX, &commonDeltaY);
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004502 mPointerGesture.pointerVelocityControl.move(when, &commonDeltaX, &commonDeltaY);
Jeff Brown538881e2011-05-25 18:23:38 -07004503
Jeff Brownbb3fcba0c2011-06-06 19:23:05 -07004504 mPointerGesture.referenceGestureX += commonDeltaX;
4505 mPointerGesture.referenceGestureY += commonDeltaY;
Jeff Brown2352b972011-04-12 22:39:53 -07004506 }
4507
4508 // Report gestures.
Jeff Brown612891e2011-07-15 20:44:17 -07004509 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS
4510 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4511 // PRESS or SWIPE mode.
Jeff Brownace13b12011-03-09 17:39:48 -08004512#if DEBUG_GESTURES
Jeff Brown612891e2011-07-15 20:44:17 -07004513 LOGD("Gestures: PRESS or SWIPE activeTouchId=%d,"
Jeff Brown2352b972011-04-12 22:39:53 -07004514 "activeGestureId=%d, currentTouchPointerCount=%d",
4515 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4516#endif
4517 LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
4518
4519 mPointerGesture.currentGestureIdBits.clear();
4520 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4521 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004522 mPointerGesture.currentGestureProperties[0].clear();
4523 mPointerGesture.currentGestureProperties[0].id = mPointerGesture.activeGestureId;
4524 mPointerGesture.currentGestureProperties[0].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004525 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brown2352b972011-04-12 22:39:53 -07004526 mPointerGesture.currentGestureCoords[0].clear();
4527 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4528 mPointerGesture.referenceGestureX);
4529 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4530 mPointerGesture.referenceGestureY);
4531 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brownace13b12011-03-09 17:39:48 -08004532 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4533 // FREEFORM mode.
4534#if DEBUG_GESTURES
4535 LOGD("Gestures: FREEFORM activeTouchId=%d,"
4536 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown2352b972011-04-12 22:39:53 -07004537 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
Jeff Brownace13b12011-03-09 17:39:48 -08004538#endif
Jeff Brownb6110c22011-04-01 16:15:13 -07004539 LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004540
Jeff Brownace13b12011-03-09 17:39:48 -08004541 mPointerGesture.currentGestureIdBits.clear();
4542
4543 BitSet32 mappedTouchIdBits;
4544 BitSet32 usedGestureIdBits;
4545 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4546 // Initially, assign the active gesture id to the active touch point
4547 // if there is one. No other touch id bits are mapped yet.
4548 if (!*outCancelPreviousGesture) {
4549 mappedTouchIdBits.markBit(activeTouchId);
4550 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4551 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4552 mPointerGesture.activeGestureId;
4553 } else {
4554 mPointerGesture.activeGestureId = -1;
4555 }
4556 } else {
4557 // Otherwise, assume we mapped all touches from the previous frame.
4558 // Reuse all mappings that are still applicable.
4559 mappedTouchIdBits.value = mLastTouch.idBits.value & mCurrentTouch.idBits.value;
4560 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4561
4562 // Check whether we need to choose a new active gesture id because the
4563 // current went went up.
4564 for (BitSet32 upTouchIdBits(mLastTouch.idBits.value & ~mCurrentTouch.idBits.value);
4565 !upTouchIdBits.isEmpty(); ) {
4566 uint32_t upTouchId = upTouchIdBits.firstMarkedBit();
4567 upTouchIdBits.clearBit(upTouchId);
4568 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4569 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4570 mPointerGesture.activeGestureId = -1;
4571 break;
4572 }
4573 }
4574 }
4575
4576#if DEBUG_GESTURES
4577 LOGD("Gestures: FREEFORM follow up "
4578 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4579 "activeGestureId=%d",
4580 mappedTouchIdBits.value, usedGestureIdBits.value,
4581 mPointerGesture.activeGestureId);
4582#endif
4583
Jeff Brown2352b972011-04-12 22:39:53 -07004584 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
Jeff Brownace13b12011-03-09 17:39:48 -08004585 uint32_t touchId = mCurrentTouch.pointers[i].id;
4586 uint32_t gestureId;
4587 if (!mappedTouchIdBits.hasBit(touchId)) {
4588 gestureId = usedGestureIdBits.firstUnmarkedBit();
4589 usedGestureIdBits.markBit(gestureId);
4590 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4591#if DEBUG_GESTURES
4592 LOGD("Gestures: FREEFORM "
4593 "new mapping for touch id %d -> gesture id %d",
4594 touchId, gestureId);
4595#endif
4596 } else {
4597 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4598#if DEBUG_GESTURES
4599 LOGD("Gestures: FREEFORM "
4600 "existing mapping for touch id %d -> gesture id %d",
4601 touchId, gestureId);
4602#endif
4603 }
4604 mPointerGesture.currentGestureIdBits.markBit(gestureId);
4605 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4606
Jeff Brown612891e2011-07-15 20:44:17 -07004607 float deltaX = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4608 * mLocked.pointerGestureXZoomScale;
4609 float deltaY = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4610 * mLocked.pointerGestureYZoomScale;
4611 rotateDelta(mLocked.surfaceOrientation, &deltaX, &deltaY);
Jeff Brownace13b12011-03-09 17:39:48 -08004612
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004613 mPointerGesture.currentGestureProperties[i].clear();
4614 mPointerGesture.currentGestureProperties[i].id = gestureId;
4615 mPointerGesture.currentGestureProperties[i].toolType =
Jeff Brown49754db2011-07-01 17:37:58 -07004616 AMOTION_EVENT_TOOL_TYPE_FINGER;
Jeff Brownace13b12011-03-09 17:39:48 -08004617 mPointerGesture.currentGestureCoords[i].clear();
4618 mPointerGesture.currentGestureCoords[i].setAxisValue(
Jeff Brown612891e2011-07-15 20:44:17 -07004619 AMOTION_EVENT_AXIS_X, mPointerGesture.referenceGestureX + deltaX);
Jeff Brownace13b12011-03-09 17:39:48 -08004620 mPointerGesture.currentGestureCoords[i].setAxisValue(
Jeff Brown612891e2011-07-15 20:44:17 -07004621 AMOTION_EVENT_AXIS_Y, mPointerGesture.referenceGestureY + deltaY);
Jeff Brownace13b12011-03-09 17:39:48 -08004622 mPointerGesture.currentGestureCoords[i].setAxisValue(
4623 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4624 }
4625
4626 if (mPointerGesture.activeGestureId < 0) {
4627 mPointerGesture.activeGestureId =
4628 mPointerGesture.currentGestureIdBits.firstMarkedBit();
4629#if DEBUG_GESTURES
4630 LOGD("Gestures: FREEFORM new "
4631 "activeGestureId=%d", mPointerGesture.activeGestureId);
4632#endif
4633 }
Jeff Brown2352b972011-04-12 22:39:53 -07004634 }
Jeff Brownace13b12011-03-09 17:39:48 -08004635 }
4636
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004637 mPointerController->setButtonState(mCurrentTouch.buttonState);
4638
Jeff Brownace13b12011-03-09 17:39:48 -08004639#if DEBUG_GESTURES
4640 LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
Jeff Brown2352b972011-04-12 22:39:53 -07004641 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4642 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
Jeff Brownace13b12011-03-09 17:39:48 -08004643 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
Jeff Brown2352b972011-04-12 22:39:53 -07004644 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4645 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
Jeff Brownace13b12011-03-09 17:39:48 -08004646 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
4647 uint32_t id = idBits.firstMarkedBit();
4648 idBits.clearBit(id);
4649 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004650 const PointerProperties& properties = mPointerGesture.currentGestureProperties[index];
Jeff Brownace13b12011-03-09 17:39:48 -08004651 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004652 LOGD(" currentGesture[%d]: index=%d, toolType=%d, "
4653 "x=%0.3f, y=%0.3f, pressure=%0.3f",
4654 id, index, properties.toolType,
4655 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
Jeff Brownace13b12011-03-09 17:39:48 -08004656 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4657 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4658 }
4659 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
4660 uint32_t id = idBits.firstMarkedBit();
4661 idBits.clearBit(id);
4662 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004663 const PointerProperties& properties = mPointerGesture.lastGestureProperties[index];
Jeff Brownace13b12011-03-09 17:39:48 -08004664 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004665 LOGD(" lastGesture[%d]: index=%d, toolType=%d, "
4666 "x=%0.3f, y=%0.3f, pressure=%0.3f",
4667 id, index, properties.toolType,
4668 coords.getAxisValue(AMOTION_EVENT_AXIS_X),
Jeff Brownace13b12011-03-09 17:39:48 -08004669 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4670 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4671 }
4672#endif
Jeff Brown79ac9692011-04-19 21:20:10 -07004673 return true;
Jeff Brownace13b12011-03-09 17:39:48 -08004674}
4675
4676void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004677 int32_t action, int32_t flags, int32_t metaState, int32_t buttonState, int32_t edgeFlags,
4678 const PointerProperties* properties, const PointerCoords* coords,
4679 const uint32_t* idToIndex, BitSet32 idBits,
Jeff Brownace13b12011-03-09 17:39:48 -08004680 int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
4681 PointerCoords pointerCoords[MAX_POINTERS];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004682 PointerProperties pointerProperties[MAX_POINTERS];
Jeff Brownace13b12011-03-09 17:39:48 -08004683 uint32_t pointerCount = 0;
4684 while (!idBits.isEmpty()) {
4685 uint32_t id = idBits.firstMarkedBit();
4686 idBits.clearBit(id);
4687 uint32_t index = idToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004688 pointerProperties[pointerCount].copyFrom(properties[index]);
Jeff Brownace13b12011-03-09 17:39:48 -08004689 pointerCoords[pointerCount].copyFrom(coords[index]);
4690
4691 if (changedId >= 0 && id == uint32_t(changedId)) {
4692 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
4693 }
4694
4695 pointerCount += 1;
4696 }
4697
Jeff Brownb6110c22011-04-01 16:15:13 -07004698 LOG_ASSERT(pointerCount != 0);
Jeff Brownace13b12011-03-09 17:39:48 -08004699
4700 if (changedId >= 0 && pointerCount == 1) {
4701 // Replace initial down and final up action.
4702 // We can compare the action without masking off the changed pointer index
4703 // because we know the index is 0.
4704 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
4705 action = AMOTION_EVENT_ACTION_DOWN;
4706 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
4707 action = AMOTION_EVENT_ACTION_UP;
4708 } else {
4709 // Can't happen.
Jeff Brownb6110c22011-04-01 16:15:13 -07004710 LOG_ASSERT(false);
Jeff Brownace13b12011-03-09 17:39:48 -08004711 }
4712 }
4713
4714 getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004715 action, flags, metaState, buttonState, edgeFlags,
4716 pointerCount, pointerProperties, pointerCoords, xPrecision, yPrecision, downTime);
Jeff Brownace13b12011-03-09 17:39:48 -08004717}
4718
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004719bool TouchInputMapper::updateMovedPointers(const PointerProperties* inProperties,
Jeff Brownace13b12011-03-09 17:39:48 -08004720 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004721 PointerProperties* outProperties, PointerCoords* outCoords, const uint32_t* outIdToIndex,
4722 BitSet32 idBits) const {
Jeff Brownace13b12011-03-09 17:39:48 -08004723 bool changed = false;
4724 while (!idBits.isEmpty()) {
4725 uint32_t id = idBits.firstMarkedBit();
4726 idBits.clearBit(id);
4727
4728 uint32_t inIndex = inIdToIndex[id];
4729 uint32_t outIndex = outIdToIndex[id];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004730
4731 const PointerProperties& curInProperties = inProperties[inIndex];
Jeff Brownace13b12011-03-09 17:39:48 -08004732 const PointerCoords& curInCoords = inCoords[inIndex];
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004733 PointerProperties& curOutProperties = outProperties[outIndex];
Jeff Brownace13b12011-03-09 17:39:48 -08004734 PointerCoords& curOutCoords = outCoords[outIndex];
4735
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07004736 if (curInProperties != curOutProperties) {
4737 curOutProperties.copyFrom(curInProperties);
4738 changed = true;
4739 }
4740
Jeff Brownace13b12011-03-09 17:39:48 -08004741 if (curInCoords != curOutCoords) {
4742 curOutCoords.copyFrom(curInCoords);
4743 changed = true;
4744 }
4745 }
4746 return changed;
4747}
4748
4749void TouchInputMapper::fadePointer() {
4750 { // acquire lock
4751 AutoMutex _l(mLock);
4752 if (mPointerController != NULL) {
Jeff Brown538881e2011-05-25 18:23:38 -07004753 mPointerController->fade(PointerControllerInterface::TRANSITION_GRADUAL);
Jeff Brownace13b12011-03-09 17:39:48 -08004754 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004755 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004756}
4757
Jeff Brown6328cdc2010-07-29 18:18:33 -07004758bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown9626b142011-03-03 02:09:54 -08004759 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
4760 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004761}
4762
Jeff Brown6328cdc2010-07-29 18:18:33 -07004763const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
4764 int32_t x, int32_t y) {
4765 size_t numVirtualKeys = mLocked.virtualKeys.size();
4766 for (size_t i = 0; i < numVirtualKeys; i++) {
4767 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004768
4769#if DEBUG_VIRTUAL_KEYS
4770 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
4771 "left=%d, top=%d, right=%d, bottom=%d",
4772 x, y,
4773 virtualKey.keyCode, virtualKey.scanCode,
4774 virtualKey.hitLeft, virtualKey.hitTop,
4775 virtualKey.hitRight, virtualKey.hitBottom);
4776#endif
4777
4778 if (virtualKey.isHit(x, y)) {
4779 return & virtualKey;
4780 }
4781 }
4782
4783 return NULL;
4784}
4785
4786void TouchInputMapper::calculatePointerIds() {
4787 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
4788 uint32_t lastPointerCount = mLastTouch.pointerCount;
4789
4790 if (currentPointerCount == 0) {
4791 // No pointers to assign.
4792 mCurrentTouch.idBits.clear();
4793 } else if (lastPointerCount == 0) {
4794 // All pointers are new.
4795 mCurrentTouch.idBits.clear();
4796 for (uint32_t i = 0; i < currentPointerCount; i++) {
4797 mCurrentTouch.pointers[i].id = i;
4798 mCurrentTouch.idToIndex[i] = i;
4799 mCurrentTouch.idBits.markBit(i);
4800 }
4801 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
4802 // Only one pointer and no change in count so it must have the same id as before.
4803 uint32_t id = mLastTouch.pointers[0].id;
4804 mCurrentTouch.pointers[0].id = id;
4805 mCurrentTouch.idToIndex[id] = 0;
4806 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
4807 } else {
4808 // General case.
4809 // We build a heap of squared euclidean distances between current and last pointers
4810 // associated with the current and last pointer indices. Then, we find the best
4811 // match (by distance) for each current pointer.
4812 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
4813
4814 uint32_t heapSize = 0;
4815 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
4816 currentPointerIndex++) {
4817 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
4818 lastPointerIndex++) {
4819 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
4820 - mLastTouch.pointers[lastPointerIndex].x;
4821 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
4822 - mLastTouch.pointers[lastPointerIndex].y;
4823
4824 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4825
4826 // Insert new element into the heap (sift up).
4827 heap[heapSize].currentPointerIndex = currentPointerIndex;
4828 heap[heapSize].lastPointerIndex = lastPointerIndex;
4829 heap[heapSize].distance = distance;
4830 heapSize += 1;
4831 }
4832 }
4833
4834 // Heapify
4835 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
4836 startIndex -= 1;
4837 for (uint32_t parentIndex = startIndex; ;) {
4838 uint32_t childIndex = parentIndex * 2 + 1;
4839 if (childIndex >= heapSize) {
4840 break;
4841 }
4842
4843 if (childIndex + 1 < heapSize
4844 && heap[childIndex + 1].distance < heap[childIndex].distance) {
4845 childIndex += 1;
4846 }
4847
4848 if (heap[parentIndex].distance <= heap[childIndex].distance) {
4849 break;
4850 }
4851
4852 swap(heap[parentIndex], heap[childIndex]);
4853 parentIndex = childIndex;
4854 }
4855 }
4856
4857#if DEBUG_POINTER_ASSIGNMENT
4858 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
4859 for (size_t i = 0; i < heapSize; i++) {
4860 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
4861 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4862 heap[i].distance);
4863 }
4864#endif
4865
4866 // Pull matches out by increasing order of distance.
4867 // To avoid reassigning pointers that have already been matched, the loop keeps track
4868 // of which last and current pointers have been matched using the matchedXXXBits variables.
4869 // It also tracks the used pointer id bits.
4870 BitSet32 matchedLastBits(0);
4871 BitSet32 matchedCurrentBits(0);
4872 BitSet32 usedIdBits(0);
4873 bool first = true;
4874 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
4875 for (;;) {
4876 if (first) {
4877 // The first time through the loop, we just consume the root element of
4878 // the heap (the one with smallest distance).
4879 first = false;
4880 } else {
4881 // Previous iterations consumed the root element of the heap.
4882 // Pop root element off of the heap (sift down).
4883 heapSize -= 1;
Jeff Brownb6110c22011-04-01 16:15:13 -07004884 LOG_ASSERT(heapSize > 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004885
4886 // Sift down.
4887 heap[0] = heap[heapSize];
4888 for (uint32_t parentIndex = 0; ;) {
4889 uint32_t childIndex = parentIndex * 2 + 1;
4890 if (childIndex >= heapSize) {
4891 break;
4892 }
4893
4894 if (childIndex + 1 < heapSize
4895 && heap[childIndex + 1].distance < heap[childIndex].distance) {
4896 childIndex += 1;
4897 }
4898
4899 if (heap[parentIndex].distance <= heap[childIndex].distance) {
4900 break;
4901 }
4902
4903 swap(heap[parentIndex], heap[childIndex]);
4904 parentIndex = childIndex;
4905 }
4906
4907#if DEBUG_POINTER_ASSIGNMENT
4908 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
4909 for (size_t i = 0; i < heapSize; i++) {
4910 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
4911 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4912 heap[i].distance);
4913 }
4914#endif
4915 }
4916
4917 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
4918 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
4919
4920 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
4921 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
4922
4923 matchedCurrentBits.markBit(currentPointerIndex);
4924 matchedLastBits.markBit(lastPointerIndex);
4925
4926 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
4927 mCurrentTouch.pointers[currentPointerIndex].id = id;
4928 mCurrentTouch.idToIndex[id] = currentPointerIndex;
4929 usedIdBits.markBit(id);
4930
4931#if DEBUG_POINTER_ASSIGNMENT
4932 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
4933 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
4934#endif
4935 break;
4936 }
4937 }
4938
4939 // Assign fresh ids to new pointers.
4940 if (currentPointerCount > lastPointerCount) {
4941 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
4942 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
4943 uint32_t id = usedIdBits.firstUnmarkedBit();
4944
4945 mCurrentTouch.pointers[currentPointerIndex].id = id;
4946 mCurrentTouch.idToIndex[id] = currentPointerIndex;
4947 usedIdBits.markBit(id);
4948
4949#if DEBUG_POINTER_ASSIGNMENT
4950 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
4951 currentPointerIndex, id);
4952#endif
4953
4954 if (--i == 0) break; // done
4955 matchedCurrentBits.markBit(currentPointerIndex);
4956 }
4957 }
4958
4959 // Fix id bits.
4960 mCurrentTouch.idBits = usedIdBits;
4961 }
4962}
4963
Jeff Brown6d0fec22010-07-23 21:28:06 -07004964int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004965 { // acquire lock
4966 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004967
Jeff Brown6328cdc2010-07-29 18:18:33 -07004968 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004969 return AKEY_STATE_VIRTUAL;
4970 }
4971
Jeff Brown6328cdc2010-07-29 18:18:33 -07004972 size_t numVirtualKeys = mLocked.virtualKeys.size();
4973 for (size_t i = 0; i < numVirtualKeys; i++) {
4974 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004975 if (virtualKey.keyCode == keyCode) {
4976 return AKEY_STATE_UP;
4977 }
4978 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004979 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004980
4981 return AKEY_STATE_UNKNOWN;
4982}
4983
4984int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004985 { // acquire lock
4986 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004987
Jeff Brown6328cdc2010-07-29 18:18:33 -07004988 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004989 return AKEY_STATE_VIRTUAL;
4990 }
4991
Jeff Brown6328cdc2010-07-29 18:18:33 -07004992 size_t numVirtualKeys = mLocked.virtualKeys.size();
4993 for (size_t i = 0; i < numVirtualKeys; i++) {
4994 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004995 if (virtualKey.scanCode == scanCode) {
4996 return AKEY_STATE_UP;
4997 }
4998 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004999 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07005000
5001 return AKEY_STATE_UNKNOWN;
5002}
5003
5004bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
5005 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07005006 { // acquire lock
5007 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005008
Jeff Brown6328cdc2010-07-29 18:18:33 -07005009 size_t numVirtualKeys = mLocked.virtualKeys.size();
5010 for (size_t i = 0; i < numVirtualKeys; i++) {
5011 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07005012
5013 for (size_t i = 0; i < numCodes; i++) {
5014 if (virtualKey.keyCode == keyCodes[i]) {
5015 outFlags[i] = 1;
5016 }
5017 }
5018 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07005019 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07005020
5021 return true;
5022}
5023
5024
5025// --- SingleTouchInputMapper ---
5026
Jeff Brown47e6b1b2010-11-29 17:37:49 -08005027SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
5028 TouchInputMapper(device) {
Jeff Brown80fd47c2011-05-24 01:07:44 -07005029 clearState();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005030}
5031
5032SingleTouchInputMapper::~SingleTouchInputMapper() {
5033}
5034
Jeff Brown80fd47c2011-05-24 01:07:44 -07005035void SingleTouchInputMapper::clearState() {
Jeff Brown49754db2011-07-01 17:37:58 -07005036 mCursorButtonAccumulator.clearButtons();
5037 mTouchButtonAccumulator.clearButtons();
5038 mSingleTouchMotionAccumulator.clearAbsoluteAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005039}
5040
5041void SingleTouchInputMapper::reset() {
5042 TouchInputMapper::reset();
5043
Jeff Brown80fd47c2011-05-24 01:07:44 -07005044 clearState();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005045 }
5046
5047void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown49754db2011-07-01 17:37:58 -07005048 mCursorButtonAccumulator.process(rawEvent);
5049 mTouchButtonAccumulator.process(rawEvent);
5050 mSingleTouchMotionAccumulator.process(rawEvent);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005051
Jeff Brown49754db2011-07-01 17:37:58 -07005052 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
5053 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005054 }
5055}
5056
5057void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005058 mCurrentTouch.clear();
5059
Jeff Brown49754db2011-07-01 17:37:58 -07005060 if (mTouchButtonAccumulator.isActive()) {
5061 uint32_t buttonState = mTouchButtonAccumulator.getButtonState();
5062 bool isHovering = mTouchButtonAccumulator.isHovering();
5063 if (mSingleTouchMotionAccumulator.getAbsoluteDistance() > 0) {
5064 isHovering = true;
5065 }
5066
Jeff Brown6d0fec22010-07-23 21:28:06 -07005067 mCurrentTouch.pointerCount = 1;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005068 mCurrentTouch.idToIndex[0] = 0;
5069 mCurrentTouch.idBits.markBit(0);
Jeff Brown49754db2011-07-01 17:37:58 -07005070 mCurrentTouch.buttonState = buttonState;
5071
5072 PointerData& outPointer = mCurrentTouch.pointers[0];
5073 outPointer.id = 0;
5074 outPointer.x = mSingleTouchMotionAccumulator.getAbsoluteX();
5075 outPointer.y = mSingleTouchMotionAccumulator.getAbsoluteY();
5076 outPointer.pressure = mSingleTouchMotionAccumulator.getAbsolutePressure();
5077 outPointer.touchMajor = 0;
5078 outPointer.touchMinor = 0;
5079 outPointer.toolMajor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5080 outPointer.toolMinor = mSingleTouchMotionAccumulator.getAbsoluteToolWidth();
5081 outPointer.orientation = 0;
5082 outPointer.distance = mSingleTouchMotionAccumulator.getAbsoluteDistance();
5083 outPointer.toolType = mTouchButtonAccumulator.getToolType();
5084 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5085 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5086 }
5087 outPointer.isHovering = isHovering;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005088 }
5089
5090 syncTouch(when, true);
5091}
5092
Jeff Brown8d608662010-08-30 03:02:23 -07005093void SingleTouchInputMapper::configureRawAxes() {
5094 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005095
Jeff Brown49754db2011-07-01 17:37:58 -07005096 mTouchButtonAccumulator.configure(getDevice());
5097
Jeff Brown8d608662010-08-30 03:02:23 -07005098 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
5099 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
5100 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
5101 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown49754db2011-07-01 17:37:58 -07005102 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_DISTANCE, & mRawAxes.distance);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005103}
5104
5105
5106// --- MultiTouchInputMapper ---
5107
Jeff Brown47e6b1b2010-11-29 17:37:49 -08005108MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
Jeff Brown49754db2011-07-01 17:37:58 -07005109 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005110}
5111
5112MultiTouchInputMapper::~MultiTouchInputMapper() {
5113}
5114
Jeff Brown80fd47c2011-05-24 01:07:44 -07005115void MultiTouchInputMapper::clearState() {
Jeff Brown49754db2011-07-01 17:37:58 -07005116 mCursorButtonAccumulator.clearButtons();
5117 mTouchButtonAccumulator.clearButtons();
Jeff Brown6894a292011-07-01 17:59:27 -07005118 mPointerIdBits.clear();
Jeff Brown2717eff2011-06-30 23:53:07 -07005119
Jeff Brown49754db2011-07-01 17:37:58 -07005120 if (mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
Jeff Brown2717eff2011-06-30 23:53:07 -07005121 // Query the driver for the current slot index and use it as the initial slot
5122 // before we start reading events from the device. It is possible that the
5123 // current slot index will not be the same as it was when the first event was
5124 // written into the evdev buffer, which means the input mapper could start
5125 // out of sync with the initial state of the events in the evdev buffer.
5126 // In the extremely unlikely case that this happens, the data from
5127 // two slots will be confused until the next ABS_MT_SLOT event is received.
5128 // This can cause the touch point to "jump", but at least there will be
5129 // no stuck touches.
Jeff Brown49754db2011-07-01 17:37:58 -07005130 int32_t initialSlot;
Jeff Brown2717eff2011-06-30 23:53:07 -07005131 status_t status = getEventHub()->getAbsoluteAxisValue(getDeviceId(), ABS_MT_SLOT,
Jeff Brown49754db2011-07-01 17:37:58 -07005132 &initialSlot);
Jeff Brown2717eff2011-06-30 23:53:07 -07005133 if (status) {
5134 LOGW("Could not retrieve current multitouch slot index. status=%d", status);
Jeff Brown49754db2011-07-01 17:37:58 -07005135 initialSlot = -1;
Jeff Brown2717eff2011-06-30 23:53:07 -07005136 }
Jeff Brown49754db2011-07-01 17:37:58 -07005137 mMultiTouchMotionAccumulator.clearSlots(initialSlot);
5138 } else {
5139 mMultiTouchMotionAccumulator.clearSlots(-1);
Jeff Brown2717eff2011-06-30 23:53:07 -07005140 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07005141}
5142
5143void MultiTouchInputMapper::reset() {
5144 TouchInputMapper::reset();
5145
Jeff Brown80fd47c2011-05-24 01:07:44 -07005146 clearState();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005147}
5148
5149void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown49754db2011-07-01 17:37:58 -07005150 mCursorButtonAccumulator.process(rawEvent);
5151 mTouchButtonAccumulator.process(rawEvent);
5152 mMultiTouchMotionAccumulator.process(rawEvent);
Jeff Brownace13b12011-03-09 17:39:48 -08005153
Jeff Brown49754db2011-07-01 17:37:58 -07005154 if (rawEvent->type == EV_SYN && rawEvent->scanCode == SYN_REPORT) {
5155 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005156 }
5157}
5158
5159void MultiTouchInputMapper::sync(nsecs_t when) {
Jeff Brown49754db2011-07-01 17:37:58 -07005160 size_t inCount = mMultiTouchMotionAccumulator.getSlotCount();
Jeff Brown80fd47c2011-05-24 01:07:44 -07005161 size_t outCount = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005162 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005163
Jeff Brown6d0fec22010-07-23 21:28:06 -07005164 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005165
Jeff Brown80fd47c2011-05-24 01:07:44 -07005166 for (size_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown49754db2011-07-01 17:37:58 -07005167 const MultiTouchMotionAccumulator::Slot* inSlot =
5168 mMultiTouchMotionAccumulator.getSlot(inIndex);
5169 if (!inSlot->isInUse()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005170 continue;
5171 }
5172
Jeff Brown80fd47c2011-05-24 01:07:44 -07005173 if (outCount >= MAX_POINTERS) {
5174#if DEBUG_POINTERS
5175 LOGD("MultiTouch device %s emitted more than maximum of %d pointers; "
5176 "ignoring the rest.",
5177 getDeviceName().string(), MAX_POINTERS);
5178#endif
5179 break; // too many fingers!
5180 }
5181
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005182 PointerData& outPointer = mCurrentTouch.pointers[outCount];
Jeff Brown49754db2011-07-01 17:37:58 -07005183 outPointer.x = inSlot->getX();
5184 outPointer.y = inSlot->getY();
5185 outPointer.pressure = inSlot->getPressure();
5186 outPointer.touchMajor = inSlot->getTouchMajor();
5187 outPointer.touchMinor = inSlot->getTouchMinor();
5188 outPointer.toolMajor = inSlot->getToolMajor();
5189 outPointer.toolMinor = inSlot->getToolMinor();
5190 outPointer.orientation = inSlot->getOrientation();
5191 outPointer.distance = inSlot->getDistance();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005192
Jeff Brown49754db2011-07-01 17:37:58 -07005193 outPointer.toolType = inSlot->getToolType();
5194 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5195 outPointer.toolType = mTouchButtonAccumulator.getToolType();
5196 if (outPointer.toolType == AMOTION_EVENT_TOOL_TYPE_UNKNOWN) {
5197 outPointer.toolType = AMOTION_EVENT_TOOL_TYPE_FINGER;
5198 }
Jeff Brown8d608662010-08-30 03:02:23 -07005199 }
5200
Jeff Brown49754db2011-07-01 17:37:58 -07005201 outPointer.isHovering = mTouchButtonAccumulator.isHovering()
5202 || inSlot->getDistance() > 0;
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005203
Jeff Brown8d608662010-08-30 03:02:23 -07005204 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07005205 if (havePointerIds) {
Jeff Brown49754db2011-07-01 17:37:58 -07005206 int32_t trackingId = inSlot->getTrackingId();
Jeff Brown6894a292011-07-01 17:59:27 -07005207 int32_t id = -1;
Jeff Brown49754db2011-07-01 17:37:58 -07005208 if (trackingId >= 0) {
Jeff Brown6894a292011-07-01 17:59:27 -07005209 for (BitSet32 idBits(mPointerIdBits); !idBits.isEmpty(); ) {
5210 uint32_t n = idBits.firstMarkedBit();
5211 idBits.clearBit(n);
5212
5213 if (mPointerTrackingIdMap[n] == trackingId) {
5214 id = n;
5215 }
5216 }
5217
5218 if (id < 0 && !mPointerIdBits.isFull()) {
5219 id = mPointerIdBits.firstUnmarkedBit();
5220 mPointerIdBits.markBit(id);
5221 mPointerTrackingIdMap[id] = trackingId;
5222 }
5223 }
5224 if (id < 0) {
5225 havePointerIds = false;
5226 mCurrentTouch.idBits.clear();
5227 } else {
Jeff Brown80fd47c2011-05-24 01:07:44 -07005228 outPointer.id = id;
5229 mCurrentTouch.idToIndex[id] = outCount;
5230 mCurrentTouch.idBits.markBit(id);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005231 }
5232 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005233
Jeff Brown6d0fec22010-07-23 21:28:06 -07005234 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005235 }
5236
Jeff Brown6d0fec22010-07-23 21:28:06 -07005237 mCurrentTouch.pointerCount = outCount;
Jeff Brown49754db2011-07-01 17:37:58 -07005238 mCurrentTouch.buttonState = mTouchButtonAccumulator.getButtonState();
Jeff Brownace13b12011-03-09 17:39:48 -08005239
Jeff Brown6894a292011-07-01 17:59:27 -07005240 mPointerIdBits = mCurrentTouch.idBits;
5241
Jeff Brown6d0fec22010-07-23 21:28:06 -07005242 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005243
Jeff Brown49754db2011-07-01 17:37:58 -07005244 if (!mMultiTouchMotionAccumulator.isUsingSlotsProtocol()) {
5245 mMultiTouchMotionAccumulator.clearSlots(-1);
Jeff Brown441a9c22011-06-02 18:22:25 -07005246 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005247}
5248
Jeff Brown8d608662010-08-30 03:02:23 -07005249void MultiTouchInputMapper::configureRawAxes() {
5250 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005251
Jeff Brown49754db2011-07-01 17:37:58 -07005252 mTouchButtonAccumulator.configure(getDevice());
5253
Jeff Brown80fd47c2011-05-24 01:07:44 -07005254 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_X, &mRawAxes.x);
5255 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_POSITION_Y, &mRawAxes.y);
5256 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MAJOR, &mRawAxes.touchMajor);
5257 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TOUCH_MINOR, &mRawAxes.touchMinor);
5258 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MAJOR, &mRawAxes.toolMajor);
5259 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_WIDTH_MINOR, &mRawAxes.toolMinor);
5260 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_ORIENTATION, &mRawAxes.orientation);
5261 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_PRESSURE, &mRawAxes.pressure);
5262 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_DISTANCE, &mRawAxes.distance);
5263 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_TRACKING_ID, &mRawAxes.trackingId);
5264 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_MT_SLOT, &mRawAxes.slot);
5265
5266 if (mRawAxes.trackingId.valid
5267 && mRawAxes.slot.valid && mRawAxes.slot.minValue == 0 && mRawAxes.slot.maxValue > 0) {
Jeff Brown49754db2011-07-01 17:37:58 -07005268 size_t slotCount = mRawAxes.slot.maxValue + 1;
5269 if (slotCount > MAX_SLOTS) {
Jeff Brown80fd47c2011-05-24 01:07:44 -07005270 LOGW("MultiTouch Device %s reported %d slots but the framework "
5271 "only supports a maximum of %d slots at this time.",
Jeff Brown49754db2011-07-01 17:37:58 -07005272 getDeviceName().string(), slotCount, MAX_SLOTS);
5273 slotCount = MAX_SLOTS;
Jeff Brown80fd47c2011-05-24 01:07:44 -07005274 }
Jeff Brown49754db2011-07-01 17:37:58 -07005275 mMultiTouchMotionAccumulator.configure(slotCount, true /*usingSlotsProtocol*/);
Jeff Brown80fd47c2011-05-24 01:07:44 -07005276 } else {
Jeff Brown49754db2011-07-01 17:37:58 -07005277 mMultiTouchMotionAccumulator.configure(MAX_POINTERS, false /*usingSlotsProtocol*/);
Jeff Brown80fd47c2011-05-24 01:07:44 -07005278 }
5279
Jeff Brown2717eff2011-06-30 23:53:07 -07005280 clearState();
Jeff Brown9c3cda02010-06-15 01:31:58 -07005281}
5282
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005283
Jeff Browncb1404e2011-01-15 18:14:15 -08005284// --- JoystickInputMapper ---
5285
5286JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5287 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08005288}
5289
5290JoystickInputMapper::~JoystickInputMapper() {
5291}
5292
5293uint32_t JoystickInputMapper::getSources() {
5294 return AINPUT_SOURCE_JOYSTICK;
5295}
5296
5297void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5298 InputMapper::populateDeviceInfo(info);
5299
Jeff Brown6f2fba42011-02-19 01:08:02 -08005300 for (size_t i = 0; i < mAxes.size(); i++) {
5301 const Axis& axis = mAxes.valueAt(i);
Jeff Brownefd32662011-03-08 15:13:06 -08005302 info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5303 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005304 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
Jeff Brownefd32662011-03-08 15:13:06 -08005305 info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5306 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005307 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005308 }
5309}
5310
5311void JoystickInputMapper::dump(String8& dump) {
5312 dump.append(INDENT2 "Joystick Input Mapper:\n");
5313
Jeff Brown6f2fba42011-02-19 01:08:02 -08005314 dump.append(INDENT3 "Axes:\n");
5315 size_t numAxes = mAxes.size();
5316 for (size_t i = 0; i < numAxes; i++) {
5317 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005318 const char* label = getAxisLabel(axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005319 if (label) {
Jeff Brown85297452011-03-04 13:07:49 -08005320 dump.appendFormat(INDENT4 "%s", label);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005321 } else {
Jeff Brown85297452011-03-04 13:07:49 -08005322 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005323 }
Jeff Brown85297452011-03-04 13:07:49 -08005324 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5325 label = getAxisLabel(axis.axisInfo.highAxis);
5326 if (label) {
5327 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5328 } else {
5329 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5330 axis.axisInfo.splitValue);
5331 }
5332 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5333 dump.append(" (invert)");
5334 }
5335
5336 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5337 axis.min, axis.max, axis.flat, axis.fuzz);
5338 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
5339 "highScale=%0.5f, highOffset=%0.5f\n",
5340 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Jeff Brownb3a2d132011-06-12 18:14:50 -07005341 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, "
5342 "rawFlat=%d, rawFuzz=%d, rawResolution=%d\n",
Jeff Brown6f2fba42011-02-19 01:08:02 -08005343 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
Jeff Brownb3a2d132011-06-12 18:14:50 -07005344 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz, axis.rawAxisInfo.resolution);
Jeff Browncb1404e2011-01-15 18:14:15 -08005345 }
5346}
5347
Jeff Brown474dcb52011-06-14 20:22:50 -07005348void JoystickInputMapper::configure(const InputReaderConfiguration* config, uint32_t changes) {
5349 InputMapper::configure(config, changes);
Jeff Browncb1404e2011-01-15 18:14:15 -08005350
Jeff Brown474dcb52011-06-14 20:22:50 -07005351 if (!changes) { // first time only
5352 // Collect all axes.
5353 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
5354 RawAbsoluteAxisInfo rawAxisInfo;
5355 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
5356 if (rawAxisInfo.valid) {
5357 // Map axis.
5358 AxisInfo axisInfo;
5359 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
5360 if (!explicitlyMapped) {
5361 // Axis is not explicitly mapped, will choose a generic axis later.
5362 axisInfo.mode = AxisInfo::MODE_NORMAL;
5363 axisInfo.axis = -1;
5364 }
5365
5366 // Apply flat override.
5367 int32_t rawFlat = axisInfo.flatOverride < 0
5368 ? rawAxisInfo.flat : axisInfo.flatOverride;
5369
5370 // Calculate scaling factors and limits.
5371 Axis axis;
5372 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5373 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5374 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5375 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5376 scale, 0.0f, highScale, 0.0f,
5377 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5378 } else if (isCenteredAxis(axisInfo.axis)) {
5379 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5380 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
5381 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5382 scale, offset, scale, offset,
5383 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5384 } else {
5385 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5386 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5387 scale, 0.0f, scale, 0.0f,
5388 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5389 }
5390
5391 // To eliminate noise while the joystick is at rest, filter out small variations
5392 // in axis values up front.
5393 axis.filter = axis.flat * 0.25f;
5394
5395 mAxes.add(abs, axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005396 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005397 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005398
Jeff Brown474dcb52011-06-14 20:22:50 -07005399 // If there are too many axes, start dropping them.
5400 // Prefer to keep explicitly mapped axes.
5401 if (mAxes.size() > PointerCoords::MAX_AXES) {
5402 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
5403 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5404 pruneAxes(true);
5405 pruneAxes(false);
5406 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005407
Jeff Brown474dcb52011-06-14 20:22:50 -07005408 // Assign generic axis ids to remaining axes.
5409 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5410 size_t numAxes = mAxes.size();
5411 for (size_t i = 0; i < numAxes; i++) {
5412 Axis& axis = mAxes.editValueAt(i);
5413 if (axis.axisInfo.axis < 0) {
5414 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5415 && haveAxis(nextGenericAxisId)) {
5416 nextGenericAxisId += 1;
5417 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005418
Jeff Brown474dcb52011-06-14 20:22:50 -07005419 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
5420 axis.axisInfo.axis = nextGenericAxisId;
5421 nextGenericAxisId += 1;
5422 } else {
5423 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
5424 "have already been assigned to other axes.",
5425 getDeviceName().string(), mAxes.keyAt(i));
5426 mAxes.removeItemsAt(i--);
5427 numAxes -= 1;
5428 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005429 }
5430 }
5431 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005432}
5433
Jeff Brown85297452011-03-04 13:07:49 -08005434bool JoystickInputMapper::haveAxis(int32_t axisId) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005435 size_t numAxes = mAxes.size();
5436 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005437 const Axis& axis = mAxes.valueAt(i);
5438 if (axis.axisInfo.axis == axisId
5439 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5440 && axis.axisInfo.highAxis == axisId)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005441 return true;
5442 }
5443 }
5444 return false;
5445}
Jeff Browncb1404e2011-01-15 18:14:15 -08005446
Jeff Brown6f2fba42011-02-19 01:08:02 -08005447void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5448 size_t i = mAxes.size();
5449 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5450 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5451 continue;
5452 }
5453 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
5454 getDeviceName().string(), mAxes.keyAt(i));
5455 mAxes.removeItemsAt(i);
5456 }
5457}
5458
5459bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5460 switch (axis) {
5461 case AMOTION_EVENT_AXIS_X:
5462 case AMOTION_EVENT_AXIS_Y:
5463 case AMOTION_EVENT_AXIS_Z:
5464 case AMOTION_EVENT_AXIS_RX:
5465 case AMOTION_EVENT_AXIS_RY:
5466 case AMOTION_EVENT_AXIS_RZ:
5467 case AMOTION_EVENT_AXIS_HAT_X:
5468 case AMOTION_EVENT_AXIS_HAT_Y:
5469 case AMOTION_EVENT_AXIS_ORIENTATION:
Jeff Brown85297452011-03-04 13:07:49 -08005470 case AMOTION_EVENT_AXIS_RUDDER:
5471 case AMOTION_EVENT_AXIS_WHEEL:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005472 return true;
5473 default:
5474 return false;
5475 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005476}
5477
5478void JoystickInputMapper::reset() {
5479 // Recenter all axes.
5480 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08005481
Jeff Brown6f2fba42011-02-19 01:08:02 -08005482 size_t numAxes = mAxes.size();
5483 for (size_t i = 0; i < numAxes; i++) {
5484 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005485 axis.resetValue();
Jeff Brown6f2fba42011-02-19 01:08:02 -08005486 }
5487
5488 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005489
5490 InputMapper::reset();
5491}
5492
5493void JoystickInputMapper::process(const RawEvent* rawEvent) {
5494 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005495 case EV_ABS: {
5496 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5497 if (index >= 0) {
5498 Axis& axis = mAxes.editValueAt(index);
Jeff Brown85297452011-03-04 13:07:49 -08005499 float newValue, highNewValue;
5500 switch (axis.axisInfo.mode) {
5501 case AxisInfo::MODE_INVERT:
5502 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5503 * axis.scale + axis.offset;
5504 highNewValue = 0.0f;
5505 break;
5506 case AxisInfo::MODE_SPLIT:
5507 if (rawEvent->value < axis.axisInfo.splitValue) {
5508 newValue = (axis.axisInfo.splitValue - rawEvent->value)
5509 * axis.scale + axis.offset;
5510 highNewValue = 0.0f;
5511 } else if (rawEvent->value > axis.axisInfo.splitValue) {
5512 newValue = 0.0f;
5513 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5514 * axis.highScale + axis.highOffset;
5515 } else {
5516 newValue = 0.0f;
5517 highNewValue = 0.0f;
5518 }
5519 break;
5520 default:
5521 newValue = rawEvent->value * axis.scale + axis.offset;
5522 highNewValue = 0.0f;
5523 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005524 }
Jeff Brown85297452011-03-04 13:07:49 -08005525 axis.newValue = newValue;
5526 axis.highNewValue = highNewValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08005527 }
5528 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005529 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005530
5531 case EV_SYN:
5532 switch (rawEvent->scanCode) {
5533 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005534 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005535 break;
5536 }
5537 break;
5538 }
5539}
5540
Jeff Brown6f2fba42011-02-19 01:08:02 -08005541void JoystickInputMapper::sync(nsecs_t when, bool force) {
Jeff Brown85297452011-03-04 13:07:49 -08005542 if (!filterAxes(force)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005543 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08005544 }
5545
5546 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005547 int32_t buttonState = 0;
5548
5549 PointerProperties pointerProperties;
5550 pointerProperties.clear();
5551 pointerProperties.id = 0;
5552 pointerProperties.toolType = AMOTION_EVENT_TOOL_TYPE_UNKNOWN;
Jeff Browncb1404e2011-01-15 18:14:15 -08005553
Jeff Brown6f2fba42011-02-19 01:08:02 -08005554 PointerCoords pointerCoords;
5555 pointerCoords.clear();
5556
5557 size_t numAxes = mAxes.size();
5558 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005559 const Axis& axis = mAxes.valueAt(i);
5560 pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5561 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5562 pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5563 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005564 }
5565
Jeff Brown56194eb2011-03-02 19:23:13 -08005566 // Moving a joystick axis should not wake the devide because joysticks can
5567 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
5568 // button will likely wake the device.
5569 // TODO: Use the input device configuration to control this behavior more finely.
5570 uint32_t policyFlags = 0;
5571
Jeff Brown56194eb2011-03-02 19:23:13 -08005572 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brownfe9f8ab2011-05-06 18:20:01 -07005573 AMOTION_EVENT_ACTION_MOVE, 0, metaState, buttonState, AMOTION_EVENT_EDGE_FLAG_NONE,
5574 1, &pointerProperties, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08005575}
5576
Jeff Brown85297452011-03-04 13:07:49 -08005577bool JoystickInputMapper::filterAxes(bool force) {
5578 bool atLeastOneSignificantChange = force;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005579 size_t numAxes = mAxes.size();
5580 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005581 Axis& axis = mAxes.editValueAt(i);
5582 if (force || hasValueChangedSignificantly(axis.filter,
5583 axis.newValue, axis.currentValue, axis.min, axis.max)) {
5584 axis.currentValue = axis.newValue;
5585 atLeastOneSignificantChange = true;
5586 }
5587 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5588 if (force || hasValueChangedSignificantly(axis.filter,
5589 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
5590 axis.highCurrentValue = axis.highNewValue;
5591 atLeastOneSignificantChange = true;
5592 }
5593 }
5594 }
5595 return atLeastOneSignificantChange;
5596}
5597
5598bool JoystickInputMapper::hasValueChangedSignificantly(
5599 float filter, float newValue, float currentValue, float min, float max) {
5600 if (newValue != currentValue) {
5601 // Filter out small changes in value unless the value is converging on the axis
5602 // bounds or center point. This is intended to reduce the amount of information
5603 // sent to applications by particularly noisy joysticks (such as PS3).
5604 if (fabs(newValue - currentValue) > filter
5605 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
5606 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
5607 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
5608 return true;
5609 }
5610 }
5611 return false;
5612}
5613
5614bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
5615 float filter, float newValue, float currentValue, float thresholdValue) {
5616 float newDistance = fabs(newValue - thresholdValue);
5617 if (newDistance < filter) {
5618 float oldDistance = fabs(currentValue - thresholdValue);
5619 if (newDistance < oldDistance) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005620 return true;
5621 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005622 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005623 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08005624}
5625
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005626} // namespace android