blob: 5e1161f17609ae5401f954e68334585c9175d153 [file] [log] [blame]
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070017#define LOG_TAG "InputReader"
18
19//#define LOG_NDEBUG 0
20
21// Log debug messages for each raw event received from the EventHub.
22#define DEBUG_RAW_EVENTS 0
23
24// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070025#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070026
27// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070028#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070029
30// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070031#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070032
Jeff Brown5c225b12010-06-16 01:53:36 -070033// Log debug messages about pointer assignment calculations.
34#define DEBUG_POINTER_ASSIGNMENT 0
35
Jeff Brown96ad3972011-03-09 17:39:48 -080036// Log debug messages about gesture detection.
37#define DEBUG_GESTURES 0
38
Jeff Brownb4ff35d2011-01-02 16:37:43 -080039#include "InputReader.h"
40
Jeff 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 Brown8d608662010-08-30 03:02:23 -070056
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070057namespace android {
58
Jeff Brown96ad3972011-03-09 17:39:48 -080059// --- Constants ---
60
61// Quiet time between certain gesture transitions.
62// Time to allow for all fingers or buttons to settle into a stable state before
63// starting a new gesture.
64static const nsecs_t QUIET_INTERVAL = 100 * 1000000; // 100 ms
65
66// The minimum speed that a pointer must travel for us to consider switching the active
67// touch pointer to it during a drag. This threshold is set to avoid switching due
68// to noise from a finger resting on the touch pad (perhaps just pressing it down).
69static const float DRAG_MIN_SWITCH_SPEED = 50.0f; // pixels per second
70
71// Tap gesture delay time.
72// The time between down and up must be less than this to be considered a tap.
Jeff Brown86ea1f52011-04-12 22:39:53 -070073static const nsecs_t TAP_INTERVAL = 150 * 1000000; // 150 ms
Jeff Brown96ad3972011-03-09 17:39:48 -080074
Jeff Brown325bd072011-04-19 21:20:10 -070075// Tap drag gesture delay time.
76// The time between up and the next up must be greater than this to be considered a
77// drag. Otherwise, the previous tap is finished and a new tap begins.
78static const nsecs_t TAP_DRAG_INTERVAL = 150 * 1000000; // 150 ms
79
Jeff Brown96ad3972011-03-09 17:39:48 -080080// The distance in pixels that the pointer is allowed to move from initial down
81// to up and still be called a tap.
Jeff Brown325bd072011-04-19 21:20:10 -070082static const float TAP_SLOP = 10.0f; // 10 pixels
Jeff Brown96ad3972011-03-09 17:39:48 -080083
Jeff Brown86ea1f52011-04-12 22:39:53 -070084// Time after the first touch points go down to settle on an initial centroid.
85// This is intended to be enough time to handle cases where the user puts down two
86// fingers at almost but not quite exactly the same time.
87static const nsecs_t MULTITOUCH_SETTLE_INTERVAL = 100 * 1000000; // 100ms
Jeff Brown96ad3972011-03-09 17:39:48 -080088
Jeff Brown86ea1f52011-04-12 22:39:53 -070089// The transition from PRESS to SWIPE or FREEFORM gesture mode is made when
90// both of the pointers are moving at least this fast.
91static const float MULTITOUCH_MIN_SPEED = 150.0f; // pixels per second
92
93// The transition from PRESS to SWIPE gesture mode can only occur when the
Jeff Brown96ad3972011-03-09 17:39:48 -080094// cosine of the angle between the two vectors is greater than or equal to than this value
95// which indicates that the vectors are oriented in the same direction.
96// When the vectors are oriented in the exactly same direction, the cosine is 1.0.
97// (In exactly opposite directions, the cosine is -1.0.)
98static const float SWIPE_TRANSITION_ANGLE_COSINE = 0.5f; // cosine of 45 degrees
99
Jeff Brown86ea1f52011-04-12 22:39:53 -0700100// The transition from PRESS to SWIPE gesture mode can only occur when the
101// fingers are no more than this far apart relative to the diagonal size of
102// the touch pad. For example, a ratio of 0.5 means that the fingers must be
103// no more than half the diagonal size of the touch pad apart.
104static const float SWIPE_MAX_WIDTH_RATIO = 0.333f; // 1/3
105
106// The gesture movement speed factor relative to the size of the display.
107// Movement speed applies when the fingers are moving in the same direction.
108// Without acceleration, a full swipe of the touch pad diagonal in movement mode
109// will cover this portion of the display diagonal.
110static const float GESTURE_MOVEMENT_SPEED_RATIO = 0.8f;
111
112// The gesture zoom speed factor relative to the size of the display.
113// Zoom speed applies when the fingers are mostly moving relative to each other
114// to execute a scale gesture or similar.
115// Without acceleration, a full swipe of the touch pad diagonal in zoom mode
116// will cover this portion of the display diagonal.
117static const float GESTURE_ZOOM_SPEED_RATIO = 0.3f;
118
Jeff Brown96ad3972011-03-09 17:39:48 -0800119
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700120// --- Static Functions ---
121
122template<typename T>
123inline static T abs(const T& value) {
124 return value < 0 ? - value : value;
125}
126
127template<typename T>
128inline static T min(const T& a, const T& b) {
129 return a < b ? a : b;
130}
131
Jeff Brown5c225b12010-06-16 01:53:36 -0700132template<typename T>
133inline static void swap(T& a, T& b) {
134 T temp = a;
135 a = b;
136 b = temp;
137}
138
Jeff Brown8d608662010-08-30 03:02:23 -0700139inline static float avg(float x, float y) {
140 return (x + y) / 2;
141}
142
Jeff Brown86ea1f52011-04-12 22:39:53 -0700143inline static float distance(float x1, float y1, float x2, float y2) {
144 return hypotf(x1 - x2, y1 - y2);
Jeff Brown96ad3972011-03-09 17:39:48 -0800145}
146
Jeff Brown517bb4c2011-01-14 19:09:23 -0800147inline static int32_t signExtendNybble(int32_t value) {
148 return value >= 8 ? value - 16 : value;
149}
150
Jeff Brownef3d7e82010-09-30 14:33:04 -0700151static inline const char* toString(bool value) {
152 return value ? "true" : "false";
153}
154
Jeff Brown9626b142011-03-03 02:09:54 -0800155static int32_t rotateValueUsingRotationMap(int32_t value, int32_t orientation,
156 const int32_t map[][4], size_t mapSize) {
157 if (orientation != DISPLAY_ORIENTATION_0) {
158 for (size_t i = 0; i < mapSize; i++) {
159 if (value == map[i][0]) {
160 return map[i][orientation];
161 }
162 }
163 }
164 return value;
165}
166
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700167static const int32_t keyCodeRotationMap[][4] = {
168 // key codes enumerated counter-clockwise with the original (unrotated) key first
169 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -0700170 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
171 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
172 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
173 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700174};
Jeff Brown9626b142011-03-03 02:09:54 -0800175static const size_t keyCodeRotationMapSize =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700176 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
177
178int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9626b142011-03-03 02:09:54 -0800179 return rotateValueUsingRotationMap(keyCode, orientation,
180 keyCodeRotationMap, keyCodeRotationMapSize);
181}
182
183static const int32_t edgeFlagRotationMap[][4] = {
184 // edge flags enumerated counter-clockwise with the original (unrotated) edge flag first
185 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
186 { AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT,
187 AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT },
188 { AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP,
189 AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM },
190 { AMOTION_EVENT_EDGE_FLAG_TOP, AMOTION_EVENT_EDGE_FLAG_LEFT,
191 AMOTION_EVENT_EDGE_FLAG_BOTTOM, AMOTION_EVENT_EDGE_FLAG_RIGHT },
192 { AMOTION_EVENT_EDGE_FLAG_LEFT, AMOTION_EVENT_EDGE_FLAG_BOTTOM,
193 AMOTION_EVENT_EDGE_FLAG_RIGHT, AMOTION_EVENT_EDGE_FLAG_TOP },
194};
195static const size_t edgeFlagRotationMapSize =
196 sizeof(edgeFlagRotationMap) / sizeof(edgeFlagRotationMap[0]);
197
198static int32_t rotateEdgeFlag(int32_t edgeFlag, int32_t orientation) {
199 return rotateValueUsingRotationMap(edgeFlag, orientation,
200 edgeFlagRotationMap, edgeFlagRotationMapSize);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700201}
202
Jeff Brown6d0fec22010-07-23 21:28:06 -0700203static inline bool sourcesMatchMask(uint32_t sources, uint32_t sourceMask) {
204 return (sources & sourceMask & ~ AINPUT_SOURCE_CLASS_MASK) != 0;
205}
206
Jeff Brownefd32662011-03-08 15:13:06 -0800207static uint32_t getButtonStateForScanCode(int32_t scanCode) {
208 // Currently all buttons are mapped to the primary button.
209 switch (scanCode) {
210 case BTN_LEFT:
211 case BTN_RIGHT:
212 case BTN_MIDDLE:
213 case BTN_SIDE:
214 case BTN_EXTRA:
215 case BTN_FORWARD:
216 case BTN_BACK:
217 case BTN_TASK:
218 return BUTTON_STATE_PRIMARY;
219 default:
220 return 0;
221 }
222}
223
224// Returns true if the pointer should be reported as being down given the specified
225// button states.
226static bool isPointerDown(uint32_t buttonState) {
227 return buttonState & BUTTON_STATE_PRIMARY;
228}
229
230static int32_t calculateEdgeFlagsUsingPointerBounds(
231 const sp<PointerControllerInterface>& pointerController, float x, float y) {
232 int32_t edgeFlags = 0;
233 float minX, minY, maxX, maxY;
234 if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
235 if (x <= minX) {
236 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
237 } else if (x >= maxX) {
238 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
239 }
240 if (y <= minY) {
241 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
242 } else if (y >= maxY) {
243 edgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
244 }
245 }
246 return edgeFlags;
247}
248
Jeff Brown86ea1f52011-04-12 22:39:53 -0700249static void clampPositionUsingPointerBounds(
250 const sp<PointerControllerInterface>& pointerController, float* x, float* y) {
251 float minX, minY, maxX, maxY;
252 if (pointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
253 if (*x < minX) {
254 *x = minX;
255 } else if (*x > maxX) {
256 *x = maxX;
257 }
258 if (*y < minY) {
259 *y = minY;
260 } else if (*y > maxY) {
261 *y = maxY;
262 }
263 }
264}
265
266static float calculateCommonVector(float a, float b) {
267 if (a > 0 && b > 0) {
268 return a < b ? a : b;
269 } else if (a < 0 && b < 0) {
270 return a > b ? a : b;
271 } else {
272 return 0;
273 }
274}
275
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700276
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700277// --- InputReader ---
278
279InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700280 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700281 const sp<InputDispatcherInterface>& dispatcher) :
Jeff Brown6d0fec22010-07-23 21:28:06 -0700282 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher),
Jeff Brown68d60752011-03-17 01:34:19 -0700283 mGlobalMetaState(0), mDisableVirtualKeysTimeout(LLONG_MIN), mNextTimeout(LLONG_MAX) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700284 configureExcludedDevices();
Jeff Brown6d0fec22010-07-23 21:28:06 -0700285 updateGlobalMetaState();
286 updateInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700287}
288
289InputReader::~InputReader() {
290 for (size_t i = 0; i < mDevices.size(); i++) {
291 delete mDevices.valueAt(i);
292 }
293}
294
295void InputReader::loopOnce() {
Jeff Brown68d60752011-03-17 01:34:19 -0700296 int32_t timeoutMillis = -1;
297 if (mNextTimeout != LLONG_MAX) {
298 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
299 timeoutMillis = toMillisecondTimeoutDelay(now, mNextTimeout);
300 }
301
Jeff Browndbf8d272011-03-18 18:14:26 -0700302 size_t count = mEventHub->getEvents(timeoutMillis, mEventBuffer, EVENT_BUFFER_SIZE);
303 if (count) {
304 processEvents(mEventBuffer, count);
305 }
306 if (!count || timeoutMillis == 0) {
Jeff Brown68d60752011-03-17 01:34:19 -0700307 nsecs_t now = systemTime(SYSTEM_TIME_MONOTONIC);
308#if DEBUG_RAW_EVENTS
309 LOGD("Timeout expired, latency=%0.3fms", (now - mNextTimeout) * 0.000001f);
310#endif
311 mNextTimeout = LLONG_MAX;
312 timeoutExpired(now);
313 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700314}
315
Jeff Browndbf8d272011-03-18 18:14:26 -0700316void InputReader::processEvents(const RawEvent* rawEvents, size_t count) {
317 for (const RawEvent* rawEvent = rawEvents; count;) {
318 int32_t type = rawEvent->type;
319 size_t batchSize = 1;
320 if (type < EventHubInterface::FIRST_SYNTHETIC_EVENT) {
321 int32_t deviceId = rawEvent->deviceId;
322 while (batchSize < count) {
323 if (rawEvent[batchSize].type >= EventHubInterface::FIRST_SYNTHETIC_EVENT
324 || rawEvent[batchSize].deviceId != deviceId) {
325 break;
326 }
327 batchSize += 1;
328 }
329#if DEBUG_RAW_EVENTS
330 LOGD("BatchSize: %d Count: %d", batchSize, count);
331#endif
332 processEventsForDevice(deviceId, rawEvent, batchSize);
333 } else {
334 switch (rawEvent->type) {
335 case EventHubInterface::DEVICE_ADDED:
336 addDevice(rawEvent->deviceId);
337 break;
338 case EventHubInterface::DEVICE_REMOVED:
339 removeDevice(rawEvent->deviceId);
340 break;
341 case EventHubInterface::FINISHED_DEVICE_SCAN:
342 handleConfigurationChanged(rawEvent->when);
343 break;
344 default:
345 assert(false); // can't happen
346 break;
347 }
348 }
349 count -= batchSize;
350 rawEvent += batchSize;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700351 }
352}
353
Jeff Brown7342bb92010-10-01 18:55:43 -0700354void InputReader::addDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700355 String8 name = mEventHub->getDeviceName(deviceId);
356 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
357
358 InputDevice* device = createDevice(deviceId, name, classes);
359 device->configure();
360
Jeff Brown8d608662010-08-30 03:02:23 -0700361 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800362 LOGI("Device added: id=%d, name='%s' (ignored non-input device)", deviceId, name.string());
Jeff Brown8d608662010-08-30 03:02:23 -0700363 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800364 LOGI("Device added: id=%d, name='%s', sources=0x%08x", deviceId, name.string(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700365 device->getSources());
Jeff Brown8d608662010-08-30 03:02:23 -0700366 }
367
Jeff Brown6d0fec22010-07-23 21:28:06 -0700368 bool added = false;
369 { // acquire device registry writer lock
370 RWLock::AutoWLock _wl(mDeviceRegistryLock);
371
372 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
373 if (deviceIndex < 0) {
374 mDevices.add(deviceId, device);
375 added = true;
376 }
377 } // release device registry writer lock
378
379 if (! added) {
380 LOGW("Ignoring spurious device added event for deviceId %d.", deviceId);
381 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700382 return;
383 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700384}
385
Jeff Brown7342bb92010-10-01 18:55:43 -0700386void InputReader::removeDevice(int32_t deviceId) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700387 bool removed = false;
388 InputDevice* device = NULL;
389 { // acquire device registry writer lock
390 RWLock::AutoWLock _wl(mDeviceRegistryLock);
391
392 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
393 if (deviceIndex >= 0) {
394 device = mDevices.valueAt(deviceIndex);
395 mDevices.removeItemsAt(deviceIndex, 1);
396 removed = true;
397 }
398 } // release device registry writer lock
399
400 if (! removed) {
401 LOGW("Ignoring spurious device removed event for deviceId %d.", deviceId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700402 return;
403 }
404
Jeff Brown6d0fec22010-07-23 21:28:06 -0700405 if (device->isIgnored()) {
Jeff Brown90655042010-12-02 13:50:46 -0800406 LOGI("Device removed: id=%d, name='%s' (ignored non-input device)",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700407 device->getId(), device->getName().string());
408 } else {
Jeff Brown90655042010-12-02 13:50:46 -0800409 LOGI("Device removed: id=%d, name='%s', sources=0x%08x",
Jeff Brown6d0fec22010-07-23 21:28:06 -0700410 device->getId(), device->getName().string(), device->getSources());
411 }
412
Jeff Brown8d608662010-08-30 03:02:23 -0700413 device->reset();
414
Jeff Brown6d0fec22010-07-23 21:28:06 -0700415 delete device;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700416}
417
Jeff Brown6d0fec22010-07-23 21:28:06 -0700418InputDevice* InputReader::createDevice(int32_t deviceId, const String8& name, uint32_t classes) {
419 InputDevice* device = new InputDevice(this, deviceId, name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700420
Jeff Brown56194eb2011-03-02 19:23:13 -0800421 // External devices.
422 if (classes & INPUT_DEVICE_CLASS_EXTERNAL) {
423 device->setExternal(true);
424 }
425
Jeff Brown6d0fec22010-07-23 21:28:06 -0700426 // Switch-like devices.
427 if (classes & INPUT_DEVICE_CLASS_SWITCH) {
428 device->addMapper(new SwitchInputMapper(device));
429 }
430
431 // Keyboard-like devices.
Jeff Brownefd32662011-03-08 15:13:06 -0800432 uint32_t keyboardSource = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700433 int32_t keyboardType = AINPUT_KEYBOARD_TYPE_NON_ALPHABETIC;
434 if (classes & INPUT_DEVICE_CLASS_KEYBOARD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800435 keyboardSource |= AINPUT_SOURCE_KEYBOARD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700436 }
437 if (classes & INPUT_DEVICE_CLASS_ALPHAKEY) {
438 keyboardType = AINPUT_KEYBOARD_TYPE_ALPHABETIC;
439 }
440 if (classes & INPUT_DEVICE_CLASS_DPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800441 keyboardSource |= AINPUT_SOURCE_DPAD;
Jeff Brown6d0fec22010-07-23 21:28:06 -0700442 }
Jeff Browncb1404e2011-01-15 18:14:15 -0800443 if (classes & INPUT_DEVICE_CLASS_GAMEPAD) {
Jeff Brownefd32662011-03-08 15:13:06 -0800444 keyboardSource |= AINPUT_SOURCE_GAMEPAD;
Jeff Browncb1404e2011-01-15 18:14:15 -0800445 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700446
Jeff Brownefd32662011-03-08 15:13:06 -0800447 if (keyboardSource != 0) {
448 device->addMapper(new KeyboardInputMapper(device, keyboardSource, keyboardType));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700449 }
450
Jeff Brown83c09682010-12-23 17:50:18 -0800451 // Cursor-like devices.
452 if (classes & INPUT_DEVICE_CLASS_CURSOR) {
453 device->addMapper(new CursorInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700454 }
455
Jeff Brown58a2da82011-01-25 16:02:22 -0800456 // Touchscreens and touchpad devices.
457 if (classes & INPUT_DEVICE_CLASS_TOUCH_MT) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800458 device->addMapper(new MultiTouchInputMapper(device));
Jeff Brown58a2da82011-01-25 16:02:22 -0800459 } else if (classes & INPUT_DEVICE_CLASS_TOUCH) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800460 device->addMapper(new SingleTouchInputMapper(device));
Jeff Brown6d0fec22010-07-23 21:28:06 -0700461 }
462
Jeff Browncb1404e2011-01-15 18:14:15 -0800463 // Joystick-like devices.
464 if (classes & INPUT_DEVICE_CLASS_JOYSTICK) {
465 device->addMapper(new JoystickInputMapper(device));
466 }
467
Jeff Brown6d0fec22010-07-23 21:28:06 -0700468 return device;
469}
470
Jeff Browndbf8d272011-03-18 18:14:26 -0700471void InputReader::processEventsForDevice(int32_t deviceId,
472 const RawEvent* rawEvents, size_t count) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700473 { // acquire device registry reader lock
474 RWLock::AutoRLock _rl(mDeviceRegistryLock);
475
476 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
477 if (deviceIndex < 0) {
478 LOGW("Discarding event for unknown deviceId %d.", deviceId);
479 return;
480 }
481
482 InputDevice* device = mDevices.valueAt(deviceIndex);
483 if (device->isIgnored()) {
484 //LOGD("Discarding event for ignored deviceId %d.", deviceId);
485 return;
486 }
487
Jeff Browndbf8d272011-03-18 18:14:26 -0700488 device->process(rawEvents, count);
Jeff Brown6d0fec22010-07-23 21:28:06 -0700489 } // release device registry reader lock
490}
491
Jeff Brown68d60752011-03-17 01:34:19 -0700492void InputReader::timeoutExpired(nsecs_t when) {
493 { // acquire device registry reader lock
494 RWLock::AutoRLock _rl(mDeviceRegistryLock);
495
496 for (size_t i = 0; i < mDevices.size(); i++) {
497 InputDevice* device = mDevices.valueAt(i);
498 if (!device->isIgnored()) {
499 device->timeoutExpired(when);
500 }
501 }
502 } // release device registry reader lock
503}
504
Jeff Brownc3db8582010-10-20 15:33:38 -0700505void InputReader::handleConfigurationChanged(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700506 // Reset global meta state because it depends on the list of all configured devices.
507 updateGlobalMetaState();
508
509 // Update input configuration.
510 updateInputConfiguration();
511
512 // Enqueue configuration changed.
513 mDispatcher->notifyConfigurationChanged(when);
514}
515
516void InputReader::configureExcludedDevices() {
517 Vector<String8> excludedDeviceNames;
518 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
519
520 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
521 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
522 }
523}
524
525void InputReader::updateGlobalMetaState() {
526 { // acquire state lock
527 AutoMutex _l(mStateLock);
528
529 mGlobalMetaState = 0;
530
531 { // acquire device registry reader lock
532 RWLock::AutoRLock _rl(mDeviceRegistryLock);
533
534 for (size_t i = 0; i < mDevices.size(); i++) {
535 InputDevice* device = mDevices.valueAt(i);
536 mGlobalMetaState |= device->getMetaState();
537 }
538 } // release device registry reader lock
539 } // release state lock
540}
541
542int32_t InputReader::getGlobalMetaState() {
543 { // acquire state lock
544 AutoMutex _l(mStateLock);
545
546 return mGlobalMetaState;
547 } // release state lock
548}
549
550void InputReader::updateInputConfiguration() {
551 { // acquire state lock
552 AutoMutex _l(mStateLock);
553
554 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
555 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
556 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
557 { // acquire device registry reader lock
558 RWLock::AutoRLock _rl(mDeviceRegistryLock);
559
560 InputDeviceInfo deviceInfo;
561 for (size_t i = 0; i < mDevices.size(); i++) {
562 InputDevice* device = mDevices.valueAt(i);
563 device->getDeviceInfo(& deviceInfo);
564 uint32_t sources = deviceInfo.getSources();
565
566 if ((sources & AINPUT_SOURCE_TOUCHSCREEN) == AINPUT_SOURCE_TOUCHSCREEN) {
567 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
568 }
569 if ((sources & AINPUT_SOURCE_TRACKBALL) == AINPUT_SOURCE_TRACKBALL) {
570 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
571 } else if ((sources & AINPUT_SOURCE_DPAD) == AINPUT_SOURCE_DPAD) {
572 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
573 }
574 if (deviceInfo.getKeyboardType() == AINPUT_KEYBOARD_TYPE_ALPHABETIC) {
575 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700576 }
577 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700578 } // release device registry reader lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700579
Jeff Brown6d0fec22010-07-23 21:28:06 -0700580 mInputConfiguration.touchScreen = touchScreenConfig;
581 mInputConfiguration.keyboard = keyboardConfig;
582 mInputConfiguration.navigation = navigationConfig;
583 } // release state lock
584}
585
Jeff Brownfe508922011-01-18 15:10:10 -0800586void InputReader::disableVirtualKeysUntil(nsecs_t time) {
587 mDisableVirtualKeysTimeout = time;
588}
589
590bool InputReader::shouldDropVirtualKey(nsecs_t now,
591 InputDevice* device, int32_t keyCode, int32_t scanCode) {
592 if (now < mDisableVirtualKeysTimeout) {
593 LOGI("Dropping virtual key from device %s because virtual keys are "
594 "temporarily disabled for the next %0.3fms. keyCode=%d, scanCode=%d",
595 device->getName().string(),
596 (mDisableVirtualKeysTimeout - now) * 0.000001,
597 keyCode, scanCode);
598 return true;
599 } else {
600 return false;
601 }
602}
603
Jeff Brown05dc66a2011-03-02 14:41:58 -0800604void InputReader::fadePointer() {
605 { // acquire device registry reader lock
606 RWLock::AutoRLock _rl(mDeviceRegistryLock);
607
608 for (size_t i = 0; i < mDevices.size(); i++) {
609 InputDevice* device = mDevices.valueAt(i);
610 device->fadePointer();
611 }
612 } // release device registry reader lock
613}
614
Jeff Brown68d60752011-03-17 01:34:19 -0700615void InputReader::requestTimeoutAtTime(nsecs_t when) {
616 if (when < mNextTimeout) {
617 mNextTimeout = when;
618 }
619}
620
Jeff Brown6d0fec22010-07-23 21:28:06 -0700621void InputReader::getInputConfiguration(InputConfiguration* outConfiguration) {
622 { // acquire state lock
623 AutoMutex _l(mStateLock);
624
625 *outConfiguration = mInputConfiguration;
626 } // release state lock
627}
628
629status_t InputReader::getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) {
630 { // acquire device registry reader lock
631 RWLock::AutoRLock _rl(mDeviceRegistryLock);
632
633 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
634 if (deviceIndex < 0) {
635 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700636 }
637
Jeff Brown6d0fec22010-07-23 21:28:06 -0700638 InputDevice* device = mDevices.valueAt(deviceIndex);
639 if (device->isIgnored()) {
640 return NAME_NOT_FOUND;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700641 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700642
643 device->getDeviceInfo(outDeviceInfo);
644 return OK;
645 } // release device registy reader lock
646}
647
648void InputReader::getInputDeviceIds(Vector<int32_t>& outDeviceIds) {
649 outDeviceIds.clear();
650
651 { // acquire device registry reader lock
652 RWLock::AutoRLock _rl(mDeviceRegistryLock);
653
654 size_t numDevices = mDevices.size();
655 for (size_t i = 0; i < numDevices; i++) {
656 InputDevice* device = mDevices.valueAt(i);
657 if (! device->isIgnored()) {
658 outDeviceIds.add(device->getId());
659 }
660 }
661 } // release device registy reader lock
662}
663
664int32_t InputReader::getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
665 int32_t keyCode) {
666 return getState(deviceId, sourceMask, keyCode, & InputDevice::getKeyCodeState);
667}
668
669int32_t InputReader::getScanCodeState(int32_t deviceId, uint32_t sourceMask,
670 int32_t scanCode) {
671 return getState(deviceId, sourceMask, scanCode, & InputDevice::getScanCodeState);
672}
673
674int32_t InputReader::getSwitchState(int32_t deviceId, uint32_t sourceMask, int32_t switchCode) {
675 return getState(deviceId, sourceMask, switchCode, & InputDevice::getSwitchState);
676}
677
678int32_t InputReader::getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
679 GetStateFunc getStateFunc) {
680 { // acquire device registry reader lock
681 RWLock::AutoRLock _rl(mDeviceRegistryLock);
682
683 int32_t result = AKEY_STATE_UNKNOWN;
684 if (deviceId >= 0) {
685 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
686 if (deviceIndex >= 0) {
687 InputDevice* device = mDevices.valueAt(deviceIndex);
688 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
689 result = (device->*getStateFunc)(sourceMask, code);
690 }
691 }
692 } else {
693 size_t numDevices = mDevices.size();
694 for (size_t i = 0; i < numDevices; i++) {
695 InputDevice* device = mDevices.valueAt(i);
696 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
697 result = (device->*getStateFunc)(sourceMask, code);
698 if (result >= AKEY_STATE_DOWN) {
699 return result;
700 }
701 }
702 }
703 }
704 return result;
705 } // release device registy reader lock
706}
707
708bool InputReader::hasKeys(int32_t deviceId, uint32_t sourceMask,
709 size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) {
710 memset(outFlags, 0, numCodes);
711 return markSupportedKeyCodes(deviceId, sourceMask, numCodes, keyCodes, outFlags);
712}
713
714bool InputReader::markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
715 const int32_t* keyCodes, uint8_t* outFlags) {
716 { // acquire device registry reader lock
717 RWLock::AutoRLock _rl(mDeviceRegistryLock);
718 bool result = false;
719 if (deviceId >= 0) {
720 ssize_t deviceIndex = mDevices.indexOfKey(deviceId);
721 if (deviceIndex >= 0) {
722 InputDevice* device = mDevices.valueAt(deviceIndex);
723 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
724 result = device->markSupportedKeyCodes(sourceMask,
725 numCodes, keyCodes, outFlags);
726 }
727 }
728 } else {
729 size_t numDevices = mDevices.size();
730 for (size_t i = 0; i < numDevices; i++) {
731 InputDevice* device = mDevices.valueAt(i);
732 if (! device->isIgnored() && sourcesMatchMask(device->getSources(), sourceMask)) {
733 result |= device->markSupportedKeyCodes(sourceMask,
734 numCodes, keyCodes, outFlags);
735 }
736 }
737 }
738 return result;
739 } // release device registy reader lock
740}
741
Jeff Brownb88102f2010-09-08 11:49:43 -0700742void InputReader::dump(String8& dump) {
Jeff Brownf2f487182010-10-01 17:46:21 -0700743 mEventHub->dump(dump);
744 dump.append("\n");
745
746 dump.append("Input Reader State:\n");
747
Jeff Brownef3d7e82010-09-30 14:33:04 -0700748 { // acquire device registry reader lock
749 RWLock::AutoRLock _rl(mDeviceRegistryLock);
Jeff Brownb88102f2010-09-08 11:49:43 -0700750
Jeff Brownef3d7e82010-09-30 14:33:04 -0700751 for (size_t i = 0; i < mDevices.size(); i++) {
752 mDevices.valueAt(i)->dump(dump);
Jeff Brownb88102f2010-09-08 11:49:43 -0700753 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700754 } // release device registy reader lock
Jeff Brownb88102f2010-09-08 11:49:43 -0700755}
756
Jeff Brown6d0fec22010-07-23 21:28:06 -0700757
758// --- InputReaderThread ---
759
760InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
761 Thread(/*canCallJava*/ true), mReader(reader) {
762}
763
764InputReaderThread::~InputReaderThread() {
765}
766
767bool InputReaderThread::threadLoop() {
768 mReader->loopOnce();
769 return true;
770}
771
772
773// --- InputDevice ---
774
775InputDevice::InputDevice(InputReaderContext* context, int32_t id, const String8& name) :
Jeff Brown56194eb2011-03-02 19:23:13 -0800776 mContext(context), mId(id), mName(name), mSources(0), mIsExternal(false) {
Jeff Brown6d0fec22010-07-23 21:28:06 -0700777}
778
779InputDevice::~InputDevice() {
780 size_t numMappers = mMappers.size();
781 for (size_t i = 0; i < numMappers; i++) {
782 delete mMappers[i];
783 }
784 mMappers.clear();
785}
786
Jeff Brownef3d7e82010-09-30 14:33:04 -0700787void InputDevice::dump(String8& dump) {
788 InputDeviceInfo deviceInfo;
789 getDeviceInfo(& deviceInfo);
790
Jeff Brown90655042010-12-02 13:50:46 -0800791 dump.appendFormat(INDENT "Device %d: %s\n", deviceInfo.getId(),
Jeff Brownef3d7e82010-09-30 14:33:04 -0700792 deviceInfo.getName().string());
Jeff Brown56194eb2011-03-02 19:23:13 -0800793 dump.appendFormat(INDENT2 "IsExternal: %s\n", toString(mIsExternal));
Jeff Brownef3d7e82010-09-30 14:33:04 -0700794 dump.appendFormat(INDENT2 "Sources: 0x%08x\n", deviceInfo.getSources());
795 dump.appendFormat(INDENT2 "KeyboardType: %d\n", deviceInfo.getKeyboardType());
Jeff Browncc0c1592011-02-19 05:07:28 -0800796
Jeff Brownefd32662011-03-08 15:13:06 -0800797 const Vector<InputDeviceInfo::MotionRange>& ranges = deviceInfo.getMotionRanges();
Jeff Browncc0c1592011-02-19 05:07:28 -0800798 if (!ranges.isEmpty()) {
Jeff Brownef3d7e82010-09-30 14:33:04 -0700799 dump.append(INDENT2 "Motion Ranges:\n");
Jeff Browncc0c1592011-02-19 05:07:28 -0800800 for (size_t i = 0; i < ranges.size(); i++) {
Jeff Brownefd32662011-03-08 15:13:06 -0800801 const InputDeviceInfo::MotionRange& range = ranges.itemAt(i);
802 const char* label = getAxisLabel(range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800803 char name[32];
804 if (label) {
805 strncpy(name, label, sizeof(name));
806 name[sizeof(name) - 1] = '\0';
807 } else {
Jeff Brownefd32662011-03-08 15:13:06 -0800808 snprintf(name, sizeof(name), "%d", range.axis);
Jeff Browncc0c1592011-02-19 05:07:28 -0800809 }
Jeff Brownefd32662011-03-08 15:13:06 -0800810 dump.appendFormat(INDENT3 "%s: source=0x%08x, "
811 "min=%0.3f, max=%0.3f, flat=%0.3f, fuzz=%0.3f\n",
812 name, range.source, range.min, range.max, range.flat, range.fuzz);
Jeff Browncc0c1592011-02-19 05:07:28 -0800813 }
Jeff Brownef3d7e82010-09-30 14:33:04 -0700814 }
815
816 size_t numMappers = mMappers.size();
817 for (size_t i = 0; i < numMappers; i++) {
818 InputMapper* mapper = mMappers[i];
819 mapper->dump(dump);
820 }
821}
822
Jeff Brown6d0fec22010-07-23 21:28:06 -0700823void InputDevice::addMapper(InputMapper* mapper) {
824 mMappers.add(mapper);
825}
826
827void InputDevice::configure() {
Jeff Brown8d608662010-08-30 03:02:23 -0700828 if (! isIgnored()) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -0800829 mContext->getEventHub()->getConfiguration(mId, &mConfiguration);
Jeff Brown8d608662010-08-30 03:02:23 -0700830 }
831
Jeff Brown6d0fec22010-07-23 21:28:06 -0700832 mSources = 0;
833
834 size_t numMappers = mMappers.size();
835 for (size_t i = 0; i < numMappers; i++) {
836 InputMapper* mapper = mMappers[i];
837 mapper->configure();
838 mSources |= mapper->getSources();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700839 }
840}
841
Jeff Brown6d0fec22010-07-23 21:28:06 -0700842void InputDevice::reset() {
843 size_t numMappers = mMappers.size();
844 for (size_t i = 0; i < numMappers; i++) {
845 InputMapper* mapper = mMappers[i];
846 mapper->reset();
847 }
848}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700849
Jeff Browndbf8d272011-03-18 18:14:26 -0700850void InputDevice::process(const RawEvent* rawEvents, size_t count) {
851 // Process all of the events in order for each mapper.
852 // We cannot simply ask each mapper to process them in bulk because mappers may
853 // have side-effects that must be interleaved. For example, joystick movement events and
854 // gamepad button presses are handled by different mappers but they should be dispatched
855 // in the order received.
Jeff Brown6d0fec22010-07-23 21:28:06 -0700856 size_t numMappers = mMappers.size();
Jeff Browndbf8d272011-03-18 18:14:26 -0700857 for (const RawEvent* rawEvent = rawEvents; count--; rawEvent++) {
858#if DEBUG_RAW_EVENTS
859 LOGD("Input event: device=%d type=0x%04x scancode=0x%04x "
860 "keycode=0x%04x value=0x%04x flags=0x%08x",
861 rawEvent->deviceId, rawEvent->type, rawEvent->scanCode, rawEvent->keyCode,
862 rawEvent->value, rawEvent->flags);
863#endif
864
865 for (size_t i = 0; i < numMappers; i++) {
866 InputMapper* mapper = mMappers[i];
867 mapper->process(rawEvent);
868 }
Jeff Brown6d0fec22010-07-23 21:28:06 -0700869 }
870}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700871
Jeff Brown68d60752011-03-17 01:34:19 -0700872void InputDevice::timeoutExpired(nsecs_t when) {
873 size_t numMappers = mMappers.size();
874 for (size_t i = 0; i < numMappers; i++) {
875 InputMapper* mapper = mMappers[i];
876 mapper->timeoutExpired(when);
877 }
878}
879
Jeff Brown6d0fec22010-07-23 21:28:06 -0700880void InputDevice::getDeviceInfo(InputDeviceInfo* outDeviceInfo) {
881 outDeviceInfo->initialize(mId, mName);
882
883 size_t numMappers = mMappers.size();
884 for (size_t i = 0; i < numMappers; i++) {
885 InputMapper* mapper = mMappers[i];
886 mapper->populateDeviceInfo(outDeviceInfo);
887 }
888}
889
890int32_t InputDevice::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
891 return getState(sourceMask, keyCode, & InputMapper::getKeyCodeState);
892}
893
894int32_t InputDevice::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
895 return getState(sourceMask, scanCode, & InputMapper::getScanCodeState);
896}
897
898int32_t InputDevice::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
899 return getState(sourceMask, switchCode, & InputMapper::getSwitchState);
900}
901
902int32_t InputDevice::getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc) {
903 int32_t result = AKEY_STATE_UNKNOWN;
904 size_t numMappers = mMappers.size();
905 for (size_t i = 0; i < numMappers; i++) {
906 InputMapper* mapper = mMappers[i];
907 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
908 result = (mapper->*getStateFunc)(sourceMask, code);
909 if (result >= AKEY_STATE_DOWN) {
910 return result;
911 }
912 }
913 }
914 return result;
915}
916
917bool InputDevice::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
918 const int32_t* keyCodes, uint8_t* outFlags) {
919 bool result = false;
920 size_t numMappers = mMappers.size();
921 for (size_t i = 0; i < numMappers; i++) {
922 InputMapper* mapper = mMappers[i];
923 if (sourcesMatchMask(mapper->getSources(), sourceMask)) {
924 result |= mapper->markSupportedKeyCodes(sourceMask, numCodes, keyCodes, outFlags);
925 }
926 }
927 return result;
928}
929
930int32_t InputDevice::getMetaState() {
931 int32_t result = 0;
932 size_t numMappers = mMappers.size();
933 for (size_t i = 0; i < numMappers; i++) {
934 InputMapper* mapper = mMappers[i];
935 result |= mapper->getMetaState();
936 }
937 return result;
938}
939
Jeff Brown05dc66a2011-03-02 14:41:58 -0800940void InputDevice::fadePointer() {
941 size_t numMappers = mMappers.size();
942 for (size_t i = 0; i < numMappers; i++) {
943 InputMapper* mapper = mMappers[i];
944 mapper->fadePointer();
945 }
946}
947
Jeff Brown6d0fec22010-07-23 21:28:06 -0700948
949// --- InputMapper ---
950
951InputMapper::InputMapper(InputDevice* device) :
952 mDevice(device), mContext(device->getContext()) {
953}
954
955InputMapper::~InputMapper() {
956}
957
958void InputMapper::populateDeviceInfo(InputDeviceInfo* info) {
959 info->addSource(getSources());
960}
961
Jeff Brownef3d7e82010-09-30 14:33:04 -0700962void InputMapper::dump(String8& dump) {
963}
964
Jeff Brown6d0fec22010-07-23 21:28:06 -0700965void InputMapper::configure() {
966}
967
968void InputMapper::reset() {
969}
970
Jeff Brown68d60752011-03-17 01:34:19 -0700971void InputMapper::timeoutExpired(nsecs_t when) {
972}
973
Jeff Brown6d0fec22010-07-23 21:28:06 -0700974int32_t InputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
975 return AKEY_STATE_UNKNOWN;
976}
977
978int32_t InputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
979 return AKEY_STATE_UNKNOWN;
980}
981
982int32_t InputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
983 return AKEY_STATE_UNKNOWN;
984}
985
986bool InputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
987 const int32_t* keyCodes, uint8_t* outFlags) {
988 return false;
989}
990
991int32_t InputMapper::getMetaState() {
992 return 0;
993}
994
Jeff Brown05dc66a2011-03-02 14:41:58 -0800995void InputMapper::fadePointer() {
996}
997
Jeff Browncb1404e2011-01-15 18:14:15 -0800998void InputMapper::dumpRawAbsoluteAxisInfo(String8& dump,
999 const RawAbsoluteAxisInfo& axis, const char* name) {
1000 if (axis.valid) {
1001 dump.appendFormat(INDENT4 "%s: min=%d, max=%d, flat=%d, fuzz=%d\n",
1002 name, axis.minValue, axis.maxValue, axis.flat, axis.fuzz);
1003 } else {
1004 dump.appendFormat(INDENT4 "%s: unknown range\n", name);
1005 }
1006}
1007
Jeff Brown6d0fec22010-07-23 21:28:06 -07001008
1009// --- SwitchInputMapper ---
1010
1011SwitchInputMapper::SwitchInputMapper(InputDevice* device) :
1012 InputMapper(device) {
1013}
1014
1015SwitchInputMapper::~SwitchInputMapper() {
1016}
1017
1018uint32_t SwitchInputMapper::getSources() {
Jeff Brown89de57a2011-01-19 18:41:38 -08001019 return AINPUT_SOURCE_SWITCH;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001020}
1021
1022void SwitchInputMapper::process(const RawEvent* rawEvent) {
1023 switch (rawEvent->type) {
1024 case EV_SW:
1025 processSwitch(rawEvent->when, rawEvent->scanCode, rawEvent->value);
1026 break;
1027 }
1028}
1029
1030void SwitchInputMapper::processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) {
Jeff Brownb6997262010-10-08 22:31:17 -07001031 getDispatcher()->notifySwitch(when, switchCode, switchValue, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001032}
1033
1034int32_t SwitchInputMapper::getSwitchState(uint32_t sourceMask, int32_t switchCode) {
1035 return getEventHub()->getSwitchState(getDeviceId(), switchCode);
1036}
1037
1038
1039// --- KeyboardInputMapper ---
1040
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001041KeyboardInputMapper::KeyboardInputMapper(InputDevice* device,
Jeff Brownefd32662011-03-08 15:13:06 -08001042 uint32_t source, int32_t keyboardType) :
1043 InputMapper(device), mSource(source),
Jeff Brown6d0fec22010-07-23 21:28:06 -07001044 mKeyboardType(keyboardType) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001045 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001046}
1047
1048KeyboardInputMapper::~KeyboardInputMapper() {
1049}
1050
Jeff Brown6328cdc2010-07-29 18:18:33 -07001051void KeyboardInputMapper::initializeLocked() {
1052 mLocked.metaState = AMETA_NONE;
1053 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001054}
1055
1056uint32_t KeyboardInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001057 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001058}
1059
1060void KeyboardInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1061 InputMapper::populateDeviceInfo(info);
1062
1063 info->setKeyboardType(mKeyboardType);
1064}
1065
Jeff Brownef3d7e82010-09-30 14:33:04 -07001066void KeyboardInputMapper::dump(String8& dump) {
1067 { // acquire lock
1068 AutoMutex _l(mLock);
1069 dump.append(INDENT2 "Keyboard Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001070 dumpParameters(dump);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001071 dump.appendFormat(INDENT3 "KeyboardType: %d\n", mKeyboardType);
1072 dump.appendFormat(INDENT3 "KeyDowns: %d keys currently down\n", mLocked.keyDowns.size());
1073 dump.appendFormat(INDENT3 "MetaState: 0x%0x\n", mLocked.metaState);
1074 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1075 } // release lock
1076}
1077
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001078
1079void KeyboardInputMapper::configure() {
1080 InputMapper::configure();
1081
1082 // Configure basic parameters.
1083 configureParameters();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001084
1085 // Reset LEDs.
1086 {
1087 AutoMutex _l(mLock);
1088 resetLedStateLocked();
1089 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001090}
1091
1092void KeyboardInputMapper::configureParameters() {
1093 mParameters.orientationAware = false;
1094 getDevice()->getConfiguration().tryGetProperty(String8("keyboard.orientationAware"),
1095 mParameters.orientationAware);
1096
1097 mParameters.associatedDisplayId = mParameters.orientationAware ? 0 : -1;
1098}
1099
1100void KeyboardInputMapper::dumpParameters(String8& dump) {
1101 dump.append(INDENT3 "Parameters:\n");
1102 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1103 mParameters.associatedDisplayId);
1104 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1105 toString(mParameters.orientationAware));
1106}
1107
Jeff Brown6d0fec22010-07-23 21:28:06 -07001108void KeyboardInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001109 for (;;) {
1110 int32_t keyCode, scanCode;
1111 { // acquire lock
1112 AutoMutex _l(mLock);
1113
1114 // Synthesize key up event on reset if keys are currently down.
1115 if (mLocked.keyDowns.isEmpty()) {
1116 initializeLocked();
Jeff Brown49ed71d2010-12-06 17:13:33 -08001117 resetLedStateLocked();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001118 break; // done
1119 }
1120
1121 const KeyDown& keyDown = mLocked.keyDowns.top();
1122 keyCode = keyDown.keyCode;
1123 scanCode = keyDown.scanCode;
1124 } // release lock
1125
Jeff Brown6d0fec22010-07-23 21:28:06 -07001126 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001127 processKey(when, false, keyCode, scanCode, 0);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001128 }
1129
1130 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001131 getContext()->updateGlobalMetaState();
1132}
1133
1134void KeyboardInputMapper::process(const RawEvent* rawEvent) {
1135 switch (rawEvent->type) {
1136 case EV_KEY: {
1137 int32_t scanCode = rawEvent->scanCode;
1138 if (isKeyboardOrGamepadKey(scanCode)) {
1139 processKey(rawEvent->when, rawEvent->value != 0, rawEvent->keyCode, scanCode,
1140 rawEvent->flags);
1141 }
1142 break;
1143 }
1144 }
1145}
1146
1147bool KeyboardInputMapper::isKeyboardOrGamepadKey(int32_t scanCode) {
1148 return scanCode < BTN_MOUSE
1149 || scanCode >= KEY_OK
Jeff Brown9e8e40c2011-03-03 03:39:29 -08001150 || (scanCode >= BTN_MISC && scanCode < BTN_MOUSE)
Jeff Browncb1404e2011-01-15 18:14:15 -08001151 || (scanCode >= BTN_JOYSTICK && scanCode < BTN_DIGI);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001152}
1153
Jeff Brown6328cdc2010-07-29 18:18:33 -07001154void KeyboardInputMapper::processKey(nsecs_t when, bool down, int32_t keyCode,
1155 int32_t scanCode, uint32_t policyFlags) {
1156 int32_t newMetaState;
1157 nsecs_t downTime;
1158 bool metaStateChanged = false;
1159
1160 { // acquire lock
1161 AutoMutex _l(mLock);
1162
1163 if (down) {
1164 // Rotate key codes according to orientation if needed.
1165 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001166 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001167 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001168 if (!getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1169 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001170 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001171 }
1172
1173 keyCode = rotateKeyCode(keyCode, orientation);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001174 }
1175
Jeff Brown6328cdc2010-07-29 18:18:33 -07001176 // Add key down.
1177 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1178 if (keyDownIndex >= 0) {
1179 // key repeat, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001180 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001181 } else {
1182 // key down
Jeff Brownfe508922011-01-18 15:10:10 -08001183 if ((policyFlags & POLICY_FLAG_VIRTUAL)
1184 && mContext->shouldDropVirtualKey(when,
1185 getDevice(), keyCode, scanCode)) {
1186 return;
1187 }
1188
Jeff Brown6328cdc2010-07-29 18:18:33 -07001189 mLocked.keyDowns.push();
1190 KeyDown& keyDown = mLocked.keyDowns.editTop();
1191 keyDown.keyCode = keyCode;
1192 keyDown.scanCode = scanCode;
1193 }
1194
1195 mLocked.downTime = when;
1196 } else {
1197 // Remove key down.
1198 ssize_t keyDownIndex = findKeyDownLocked(scanCode);
1199 if (keyDownIndex >= 0) {
1200 // key up, be sure to use same keycode as before in case of rotation
Jeff Brown6b53e8d2010-11-10 16:03:06 -08001201 keyCode = mLocked.keyDowns.itemAt(keyDownIndex).keyCode;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001202 mLocked.keyDowns.removeAt(size_t(keyDownIndex));
1203 } else {
1204 // key was not actually down
1205 LOGI("Dropping key up from device %s because the key was not down. "
1206 "keyCode=%d, scanCode=%d",
1207 getDeviceName().string(), keyCode, scanCode);
1208 return;
1209 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001210 }
1211
Jeff Brown6328cdc2010-07-29 18:18:33 -07001212 int32_t oldMetaState = mLocked.metaState;
1213 newMetaState = updateMetaState(keyCode, down, oldMetaState);
1214 if (oldMetaState != newMetaState) {
1215 mLocked.metaState = newMetaState;
1216 metaStateChanged = true;
Jeff Brown497a92c2010-09-12 17:55:08 -07001217 updateLedStateLocked(false);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001218 }
Jeff Brownfd0358292010-06-30 16:10:35 -07001219
Jeff Brown6328cdc2010-07-29 18:18:33 -07001220 downTime = mLocked.downTime;
1221 } // release lock
1222
Jeff Brown56194eb2011-03-02 19:23:13 -08001223 // Key down on external an keyboard should wake the device.
1224 // We don't do this for internal keyboards to prevent them from waking up in your pocket.
1225 // For internal keyboards, the key layout file should specify the policy flags for
1226 // each wake key individually.
1227 // TODO: Use the input device configuration to control this behavior more finely.
1228 if (down && getDevice()->isExternal()
1229 && !(policyFlags & (POLICY_FLAG_WAKE | POLICY_FLAG_WAKE_DROPPED))) {
1230 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1231 }
1232
Jeff Brown6328cdc2010-07-29 18:18:33 -07001233 if (metaStateChanged) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001234 getContext()->updateGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001235 }
1236
Jeff Brown05dc66a2011-03-02 14:41:58 -08001237 if (down && !isMetaKey(keyCode)) {
1238 getContext()->fadePointer();
1239 }
1240
Jeff Brownefd32662011-03-08 15:13:06 -08001241 getDispatcher()->notifyKey(when, getDeviceId(), mSource, policyFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001242 down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
1243 AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001244}
1245
Jeff Brown6328cdc2010-07-29 18:18:33 -07001246ssize_t KeyboardInputMapper::findKeyDownLocked(int32_t scanCode) {
1247 size_t n = mLocked.keyDowns.size();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001248 for (size_t i = 0; i < n; i++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001249 if (mLocked.keyDowns[i].scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001250 return i;
1251 }
1252 }
1253 return -1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001254}
1255
Jeff Brown6d0fec22010-07-23 21:28:06 -07001256int32_t KeyboardInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
1257 return getEventHub()->getKeyCodeState(getDeviceId(), keyCode);
1258}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001259
Jeff Brown6d0fec22010-07-23 21:28:06 -07001260int32_t KeyboardInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
1261 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1262}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001263
Jeff Brown6d0fec22010-07-23 21:28:06 -07001264bool KeyboardInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
1265 const int32_t* keyCodes, uint8_t* outFlags) {
1266 return getEventHub()->markSupportedKeyCodes(getDeviceId(), numCodes, keyCodes, outFlags);
1267}
1268
1269int32_t KeyboardInputMapper::getMetaState() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001270 { // acquire lock
1271 AutoMutex _l(mLock);
1272 return mLocked.metaState;
1273 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001274}
1275
Jeff Brown49ed71d2010-12-06 17:13:33 -08001276void KeyboardInputMapper::resetLedStateLocked() {
1277 initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
1278 initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
1279 initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
1280
1281 updateLedStateLocked(true);
1282}
1283
1284void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
1285 ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
1286 ledState.on = false;
1287}
1288
Jeff Brown497a92c2010-09-12 17:55:08 -07001289void KeyboardInputMapper::updateLedStateLocked(bool reset) {
1290 updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001291 AMETA_CAPS_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001292 updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001293 AMETA_NUM_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001294 updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
Jeff Brown51e7fe752010-10-29 22:19:53 -07001295 AMETA_SCROLL_LOCK_ON, reset);
Jeff Brown497a92c2010-09-12 17:55:08 -07001296}
1297
1298void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
1299 int32_t led, int32_t modifier, bool reset) {
1300 if (ledState.avail) {
1301 bool desiredState = (mLocked.metaState & modifier) != 0;
Jeff Brown49ed71d2010-12-06 17:13:33 -08001302 if (reset || ledState.on != desiredState) {
Jeff Brown497a92c2010-09-12 17:55:08 -07001303 getEventHub()->setLedState(getDeviceId(), led, desiredState);
1304 ledState.on = desiredState;
1305 }
1306 }
1307}
1308
Jeff Brown6d0fec22010-07-23 21:28:06 -07001309
Jeff Brown83c09682010-12-23 17:50:18 -08001310// --- CursorInputMapper ---
Jeff Brown6d0fec22010-07-23 21:28:06 -07001311
Jeff Brown83c09682010-12-23 17:50:18 -08001312CursorInputMapper::CursorInputMapper(InputDevice* device) :
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001313 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001314 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001315}
1316
Jeff Brown83c09682010-12-23 17:50:18 -08001317CursorInputMapper::~CursorInputMapper() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001318}
1319
Jeff Brown83c09682010-12-23 17:50:18 -08001320uint32_t CursorInputMapper::getSources() {
Jeff Brownefd32662011-03-08 15:13:06 -08001321 return mSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001322}
1323
Jeff Brown83c09682010-12-23 17:50:18 -08001324void CursorInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001325 InputMapper::populateDeviceInfo(info);
1326
Jeff Brown83c09682010-12-23 17:50:18 -08001327 if (mParameters.mode == Parameters::MODE_POINTER) {
1328 float minX, minY, maxX, maxY;
1329 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
Jeff Brownefd32662011-03-08 15:13:06 -08001330 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, minX, maxX, 0.0f, 0.0f);
1331 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, minY, maxY, 0.0f, 0.0f);
Jeff Brown83c09682010-12-23 17:50:18 -08001332 }
1333 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001334 info->addMotionRange(AMOTION_EVENT_AXIS_X, mSource, -1.0f, 1.0f, 0.0f, mXScale);
1335 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mSource, -1.0f, 1.0f, 0.0f, mYScale);
Jeff Brown83c09682010-12-23 17:50:18 -08001336 }
Jeff Brownefd32662011-03-08 15:13:06 -08001337 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mSource, 0.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001338
1339 if (mHaveVWheel) {
Jeff Brownefd32662011-03-08 15:13:06 -08001340 info->addMotionRange(AMOTION_EVENT_AXIS_VSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001341 }
1342 if (mHaveHWheel) {
Jeff Brownefd32662011-03-08 15:13:06 -08001343 info->addMotionRange(AMOTION_EVENT_AXIS_HSCROLL, mSource, -1.0f, 1.0f, 0.0f, 0.0f);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001344 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001345}
1346
Jeff Brown83c09682010-12-23 17:50:18 -08001347void CursorInputMapper::dump(String8& dump) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07001348 { // acquire lock
1349 AutoMutex _l(mLock);
Jeff Brown83c09682010-12-23 17:50:18 -08001350 dump.append(INDENT2 "Cursor Input Mapper:\n");
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001351 dumpParameters(dump);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001352 dump.appendFormat(INDENT3 "XScale: %0.3f\n", mXScale);
1353 dump.appendFormat(INDENT3 "YScale: %0.3f\n", mYScale);
Jeff Brownef3d7e82010-09-30 14:33:04 -07001354 dump.appendFormat(INDENT3 "XPrecision: %0.3f\n", mXPrecision);
1355 dump.appendFormat(INDENT3 "YPrecision: %0.3f\n", mYPrecision);
Jeff Brown6f2fba42011-02-19 01:08:02 -08001356 dump.appendFormat(INDENT3 "HaveVWheel: %s\n", toString(mHaveVWheel));
1357 dump.appendFormat(INDENT3 "HaveHWheel: %s\n", toString(mHaveHWheel));
1358 dump.appendFormat(INDENT3 "VWheelScale: %0.3f\n", mVWheelScale);
1359 dump.appendFormat(INDENT3 "HWheelScale: %0.3f\n", mHWheelScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001360 dump.appendFormat(INDENT3 "ButtonState: 0x%08x\n", mLocked.buttonState);
1361 dump.appendFormat(INDENT3 "Down: %s\n", toString(isPointerDown(mLocked.buttonState)));
Jeff Brownef3d7e82010-09-30 14:33:04 -07001362 dump.appendFormat(INDENT3 "DownTime: %lld\n", mLocked.downTime);
1363 } // release lock
1364}
1365
Jeff Brown83c09682010-12-23 17:50:18 -08001366void CursorInputMapper::configure() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001367 InputMapper::configure();
1368
1369 // Configure basic parameters.
1370 configureParameters();
Jeff Brown83c09682010-12-23 17:50:18 -08001371
1372 // Configure device mode.
1373 switch (mParameters.mode) {
1374 case Parameters::MODE_POINTER:
Jeff Brownefd32662011-03-08 15:13:06 -08001375 mSource = AINPUT_SOURCE_MOUSE;
Jeff Brown83c09682010-12-23 17:50:18 -08001376 mXPrecision = 1.0f;
1377 mYPrecision = 1.0f;
1378 mXScale = 1.0f;
1379 mYScale = 1.0f;
1380 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
1381 break;
1382 case Parameters::MODE_NAVIGATION:
Jeff Brownefd32662011-03-08 15:13:06 -08001383 mSource = AINPUT_SOURCE_TRACKBALL;
Jeff Brown83c09682010-12-23 17:50:18 -08001384 mXPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1385 mYPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1386 mXScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1387 mYScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1388 break;
1389 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08001390
1391 mVWheelScale = 1.0f;
1392 mHWheelScale = 1.0f;
Jeff Browncc0c1592011-02-19 05:07:28 -08001393
1394 mHaveVWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_WHEEL);
1395 mHaveHWheel = getEventHub()->hasRelativeAxis(getDeviceId(), REL_HWHEEL);
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001396}
1397
Jeff Brown83c09682010-12-23 17:50:18 -08001398void CursorInputMapper::configureParameters() {
1399 mParameters.mode = Parameters::MODE_POINTER;
1400 String8 cursorModeString;
1401 if (getDevice()->getConfiguration().tryGetProperty(String8("cursor.mode"), cursorModeString)) {
1402 if (cursorModeString == "navigation") {
1403 mParameters.mode = Parameters::MODE_NAVIGATION;
1404 } else if (cursorModeString != "pointer" && cursorModeString != "default") {
1405 LOGW("Invalid value for cursor.mode: '%s'", cursorModeString.string());
1406 }
1407 }
1408
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001409 mParameters.orientationAware = false;
Jeff Brown83c09682010-12-23 17:50:18 -08001410 getDevice()->getConfiguration().tryGetProperty(String8("cursor.orientationAware"),
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001411 mParameters.orientationAware);
1412
Jeff Brown83c09682010-12-23 17:50:18 -08001413 mParameters.associatedDisplayId = mParameters.mode == Parameters::MODE_POINTER
1414 || mParameters.orientationAware ? 0 : -1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001415}
1416
Jeff Brown83c09682010-12-23 17:50:18 -08001417void CursorInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001418 dump.append(INDENT3 "Parameters:\n");
1419 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1420 mParameters.associatedDisplayId);
Jeff Brown83c09682010-12-23 17:50:18 -08001421
1422 switch (mParameters.mode) {
1423 case Parameters::MODE_POINTER:
1424 dump.append(INDENT4 "Mode: pointer\n");
1425 break;
1426 case Parameters::MODE_NAVIGATION:
1427 dump.append(INDENT4 "Mode: navigation\n");
1428 break;
1429 default:
1430 assert(false);
1431 }
1432
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001433 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1434 toString(mParameters.orientationAware));
1435}
1436
Jeff Brown83c09682010-12-23 17:50:18 -08001437void CursorInputMapper::initializeLocked() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001438 mAccumulator.clear();
1439
Jeff Brownefd32662011-03-08 15:13:06 -08001440 mLocked.buttonState = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001441 mLocked.downTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001442}
1443
Jeff Brown83c09682010-12-23 17:50:18 -08001444void CursorInputMapper::reset() {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001445 for (;;) {
Jeff Brownefd32662011-03-08 15:13:06 -08001446 uint32_t buttonState;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001447 { // acquire lock
1448 AutoMutex _l(mLock);
1449
Jeff Brownefd32662011-03-08 15:13:06 -08001450 buttonState = mLocked.buttonState;
1451 if (!buttonState) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001452 initializeLocked();
1453 break; // done
1454 }
1455 } // release lock
1456
Jeff Brown83c09682010-12-23 17:50:18 -08001457 // Synthesize button up event on reset.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001458 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Brownefd32662011-03-08 15:13:06 -08001459 mAccumulator.clear();
1460 mAccumulator.buttonDown = 0;
1461 mAccumulator.buttonUp = buttonState;
1462 mAccumulator.fields = Accumulator::FIELD_BUTTONS;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001463 sync(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001464 }
1465
Jeff Brown6d0fec22010-07-23 21:28:06 -07001466 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001467}
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001468
Jeff Brown83c09682010-12-23 17:50:18 -08001469void CursorInputMapper::process(const RawEvent* rawEvent) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001470 switch (rawEvent->type) {
Jeff Brownefd32662011-03-08 15:13:06 -08001471 case EV_KEY: {
1472 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
1473 if (buttonState) {
1474 if (rawEvent->value) {
1475 mAccumulator.buttonDown = buttonState;
1476 mAccumulator.buttonUp = 0;
1477 } else {
1478 mAccumulator.buttonDown = 0;
1479 mAccumulator.buttonUp = buttonState;
1480 }
1481 mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
1482
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001483 // Sync now since BTN_MOUSE is not necessarily followed by SYN_REPORT and
1484 // we need to ensure that we report the up/down promptly.
Jeff Brown6d0fec22010-07-23 21:28:06 -07001485 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001486 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001487 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001488 break;
Jeff Brownefd32662011-03-08 15:13:06 -08001489 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001490
Jeff Brown6d0fec22010-07-23 21:28:06 -07001491 case EV_REL:
1492 switch (rawEvent->scanCode) {
1493 case REL_X:
1494 mAccumulator.fields |= Accumulator::FIELD_REL_X;
1495 mAccumulator.relX = rawEvent->value;
1496 break;
1497 case REL_Y:
1498 mAccumulator.fields |= Accumulator::FIELD_REL_Y;
1499 mAccumulator.relY = rawEvent->value;
1500 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08001501 case REL_WHEEL:
1502 mAccumulator.fields |= Accumulator::FIELD_REL_WHEEL;
1503 mAccumulator.relWheel = rawEvent->value;
1504 break;
1505 case REL_HWHEEL:
1506 mAccumulator.fields |= Accumulator::FIELD_REL_HWHEEL;
1507 mAccumulator.relHWheel = rawEvent->value;
1508 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001509 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001510 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001511
Jeff Brown6d0fec22010-07-23 21:28:06 -07001512 case EV_SYN:
1513 switch (rawEvent->scanCode) {
1514 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001515 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001516 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001517 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001518 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001519 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001520}
1521
Jeff Brown83c09682010-12-23 17:50:18 -08001522void CursorInputMapper::sync(nsecs_t when) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07001523 uint32_t fields = mAccumulator.fields;
1524 if (fields == 0) {
1525 return; // no new state changes, so nothing to do
1526 }
1527
Jeff Brown9626b142011-03-03 02:09:54 -08001528 int32_t motionEventAction;
1529 int32_t motionEventEdgeFlags;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001530 PointerCoords pointerCoords;
1531 nsecs_t downTime;
Jeff Brown33bbfd22011-02-24 20:55:35 -08001532 float vscroll, hscroll;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001533 { // acquire lock
1534 AutoMutex _l(mLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001535
Jeff Brownefd32662011-03-08 15:13:06 -08001536 bool down, downChanged;
1537 bool wasDown = isPointerDown(mLocked.buttonState);
1538 bool buttonsChanged = fields & Accumulator::FIELD_BUTTONS;
1539 if (buttonsChanged) {
1540 mLocked.buttonState = (mLocked.buttonState | mAccumulator.buttonDown)
1541 & ~mAccumulator.buttonUp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001542
Jeff Brownefd32662011-03-08 15:13:06 -08001543 down = isPointerDown(mLocked.buttonState);
1544
1545 if (!wasDown && down) {
1546 mLocked.downTime = when;
1547 downChanged = true;
1548 } else if (wasDown && !down) {
1549 downChanged = true;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001550 } else {
Jeff Brownefd32662011-03-08 15:13:06 -08001551 downChanged = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001552 }
Jeff Brownefd32662011-03-08 15:13:06 -08001553 } else {
1554 down = wasDown;
1555 downChanged = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001556 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001557
Jeff Brown6328cdc2010-07-29 18:18:33 -07001558 downTime = mLocked.downTime;
Jeff Brown83c09682010-12-23 17:50:18 -08001559 float deltaX = fields & Accumulator::FIELD_REL_X ? mAccumulator.relX * mXScale : 0.0f;
1560 float deltaY = fields & Accumulator::FIELD_REL_Y ? mAccumulator.relY * mYScale : 0.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001561
Jeff Brown6328cdc2010-07-29 18:18:33 -07001562 if (downChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08001563 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
1564 } else if (down || mPointerController == NULL) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001565 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Browncc0c1592011-02-19 05:07:28 -08001566 } else {
1567 motionEventAction = AMOTION_EVENT_ACTION_HOVER_MOVE;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001568 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001569
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001570 if (mParameters.orientationAware && mParameters.associatedDisplayId >= 0
Jeff Brown83c09682010-12-23 17:50:18 -08001571 && (deltaX != 0.0f || deltaY != 0.0f)) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001572 // Rotate motion based on display orientation if needed.
1573 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
1574 int32_t orientation;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001575 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
1576 NULL, NULL, & orientation)) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001577 orientation = DISPLAY_ORIENTATION_0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001578 }
1579
1580 float temp;
1581 switch (orientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001582 case DISPLAY_ORIENTATION_90:
Jeff Brown83c09682010-12-23 17:50:18 -08001583 temp = deltaX;
1584 deltaX = deltaY;
1585 deltaY = -temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001586 break;
1587
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001588 case DISPLAY_ORIENTATION_180:
Jeff Brown83c09682010-12-23 17:50:18 -08001589 deltaX = -deltaX;
1590 deltaY = -deltaY;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001591 break;
1592
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001593 case DISPLAY_ORIENTATION_270:
Jeff Brown83c09682010-12-23 17:50:18 -08001594 temp = deltaX;
1595 deltaX = -deltaY;
1596 deltaY = temp;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001597 break;
1598 }
1599 }
Jeff Brown83c09682010-12-23 17:50:18 -08001600
Jeff Brown91c69ab2011-02-14 17:03:18 -08001601 pointerCoords.clear();
1602
Jeff Brown9626b142011-03-03 02:09:54 -08001603 motionEventEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
1604
Jeff Brown86ea1f52011-04-12 22:39:53 -07001605 if (mHaveVWheel && (fields & Accumulator::FIELD_REL_WHEEL)) {
1606 vscroll = mAccumulator.relWheel;
1607 } else {
1608 vscroll = 0;
1609 }
1610 if (mHaveHWheel && (fields & Accumulator::FIELD_REL_HWHEEL)) {
1611 hscroll = mAccumulator.relHWheel;
1612 } else {
1613 hscroll = 0;
1614 }
1615
Jeff Brown83c09682010-12-23 17:50:18 -08001616 if (mPointerController != NULL) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07001617 if (deltaX != 0 || deltaY != 0 || vscroll != 0 || hscroll != 0
1618 || buttonsChanged) {
1619 mPointerController->setPresentation(
1620 PointerControllerInterface::PRESENTATION_POINTER);
1621
1622 if (deltaX != 0 || deltaY != 0) {
1623 mPointerController->move(deltaX, deltaY);
1624 }
1625
1626 if (buttonsChanged) {
1627 mPointerController->setButtonState(mLocked.buttonState);
1628 }
1629
1630 mPointerController->unfade();
Jeff Brown83c09682010-12-23 17:50:18 -08001631 }
Jeff Brownefd32662011-03-08 15:13:06 -08001632
Jeff Brown91c69ab2011-02-14 17:03:18 -08001633 float x, y;
1634 mPointerController->getPosition(&x, &y);
Jeff Brownebbd5d12011-02-17 13:01:34 -08001635 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, x);
1636 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown9626b142011-03-03 02:09:54 -08001637
1638 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brownefd32662011-03-08 15:13:06 -08001639 motionEventEdgeFlags = calculateEdgeFlagsUsingPointerBounds(
1640 mPointerController, x, y);
Jeff Brown9626b142011-03-03 02:09:54 -08001641 }
Jeff Brown83c09682010-12-23 17:50:18 -08001642 } else {
Jeff Brownebbd5d12011-02-17 13:01:34 -08001643 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_X, deltaX);
1644 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_Y, deltaY);
Jeff Brown83c09682010-12-23 17:50:18 -08001645 }
1646
Jeff Brownefd32662011-03-08 15:13:06 -08001647 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, down ? 1.0f : 0.0f);
Jeff Brown6328cdc2010-07-29 18:18:33 -07001648 } // release lock
1649
Jeff Brown56194eb2011-03-02 19:23:13 -08001650 // Moving an external trackball or mouse should wake the device.
1651 // We don't do this for internal cursor devices to prevent them from waking up
1652 // the device in your pocket.
1653 // TODO: Use the input device configuration to control this behavior more finely.
1654 uint32_t policyFlags = 0;
1655 if (getDevice()->isExternal()) {
1656 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
1657 }
1658
Jeff Brown6d0fec22010-07-23 21:28:06 -07001659 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown6328cdc2010-07-29 18:18:33 -07001660 int32_t pointerId = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08001661 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brown9626b142011-03-03 02:09:54 -08001662 motionEventAction, 0, metaState, motionEventEdgeFlags,
Jeff Brownb6997262010-10-08 22:31:17 -07001663 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1664
1665 mAccumulator.clear();
Jeff Brown33bbfd22011-02-24 20:55:35 -08001666
1667 if (vscroll != 0 || hscroll != 0) {
1668 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_VSCROLL, vscroll);
1669 pointerCoords.setAxisValue(AMOTION_EVENT_AXIS_HSCROLL, hscroll);
1670
Jeff Brownefd32662011-03-08 15:13:06 -08001671 getDispatcher()->notifyMotion(when, getDeviceId(), mSource, policyFlags,
Jeff Brown33bbfd22011-02-24 20:55:35 -08001672 AMOTION_EVENT_ACTION_SCROLL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
1673 1, &pointerId, &pointerCoords, mXPrecision, mYPrecision, downTime);
1674 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001675}
1676
Jeff Brown83c09682010-12-23 17:50:18 -08001677int32_t CursorInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brownc3fc2d02010-08-10 15:47:53 -07001678 if (scanCode >= BTN_MOUSE && scanCode < BTN_JOYSTICK) {
1679 return getEventHub()->getScanCodeState(getDeviceId(), scanCode);
1680 } else {
1681 return AKEY_STATE_UNKNOWN;
1682 }
1683}
1684
Jeff Brown05dc66a2011-03-02 14:41:58 -08001685void CursorInputMapper::fadePointer() {
1686 { // acquire lock
1687 AutoMutex _l(mLock);
Jeff Brownefd32662011-03-08 15:13:06 -08001688 if (mPointerController != NULL) {
1689 mPointerController->fade();
1690 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08001691 } // release lock
1692}
1693
Jeff Brown6d0fec22010-07-23 21:28:06 -07001694
1695// --- TouchInputMapper ---
1696
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001697TouchInputMapper::TouchInputMapper(InputDevice* device) :
1698 InputMapper(device) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001699 mLocked.surfaceOrientation = -1;
1700 mLocked.surfaceWidth = -1;
1701 mLocked.surfaceHeight = -1;
1702
1703 initializeLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001704}
1705
1706TouchInputMapper::~TouchInputMapper() {
1707}
1708
1709uint32_t TouchInputMapper::getSources() {
Jeff Brown96ad3972011-03-09 17:39:48 -08001710 return mTouchSource | mPointerSource;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001711}
1712
1713void TouchInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
1714 InputMapper::populateDeviceInfo(info);
1715
Jeff Brown6328cdc2010-07-29 18:18:33 -07001716 { // acquire lock
1717 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001718
Jeff Brown6328cdc2010-07-29 18:18:33 -07001719 // Ensure surface information is up to date so that orientation changes are
1720 // noticed immediately.
Jeff Brownefd32662011-03-08 15:13:06 -08001721 if (!configureSurfaceLocked()) {
1722 return;
1723 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001724
Jeff Brownefd32662011-03-08 15:13:06 -08001725 info->addMotionRange(mLocked.orientedRanges.x);
1726 info->addMotionRange(mLocked.orientedRanges.y);
Jeff Brown8d608662010-08-30 03:02:23 -07001727
1728 if (mLocked.orientedRanges.havePressure) {
Jeff Brownefd32662011-03-08 15:13:06 -08001729 info->addMotionRange(mLocked.orientedRanges.pressure);
Jeff Brown8d608662010-08-30 03:02:23 -07001730 }
1731
1732 if (mLocked.orientedRanges.haveSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001733 info->addMotionRange(mLocked.orientedRanges.size);
Jeff Brown8d608662010-08-30 03:02:23 -07001734 }
1735
Jeff Brownc6d282b2010-10-14 21:42:15 -07001736 if (mLocked.orientedRanges.haveTouchSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001737 info->addMotionRange(mLocked.orientedRanges.touchMajor);
1738 info->addMotionRange(mLocked.orientedRanges.touchMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07001739 }
1740
Jeff Brownc6d282b2010-10-14 21:42:15 -07001741 if (mLocked.orientedRanges.haveToolSize) {
Jeff Brownefd32662011-03-08 15:13:06 -08001742 info->addMotionRange(mLocked.orientedRanges.toolMajor);
1743 info->addMotionRange(mLocked.orientedRanges.toolMinor);
Jeff Brown8d608662010-08-30 03:02:23 -07001744 }
1745
1746 if (mLocked.orientedRanges.haveOrientation) {
Jeff Brownefd32662011-03-08 15:13:06 -08001747 info->addMotionRange(mLocked.orientedRanges.orientation);
Jeff Brown8d608662010-08-30 03:02:23 -07001748 }
Jeff Brown96ad3972011-03-09 17:39:48 -08001749
1750 if (mPointerController != NULL) {
1751 float minX, minY, maxX, maxY;
1752 if (mPointerController->getBounds(&minX, &minY, &maxX, &maxY)) {
1753 info->addMotionRange(AMOTION_EVENT_AXIS_X, mPointerSource,
1754 minX, maxX, 0.0f, 0.0f);
1755 info->addMotionRange(AMOTION_EVENT_AXIS_Y, mPointerSource,
1756 minY, maxY, 0.0f, 0.0f);
1757 }
1758 info->addMotionRange(AMOTION_EVENT_AXIS_PRESSURE, mPointerSource,
1759 0.0f, 1.0f, 0.0f, 0.0f);
1760 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07001761 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001762}
1763
Jeff Brownef3d7e82010-09-30 14:33:04 -07001764void TouchInputMapper::dump(String8& dump) {
1765 { // acquire lock
1766 AutoMutex _l(mLock);
1767 dump.append(INDENT2 "Touch Input Mapper:\n");
Jeff Brownef3d7e82010-09-30 14:33:04 -07001768 dumpParameters(dump);
1769 dumpVirtualKeysLocked(dump);
1770 dumpRawAxes(dump);
1771 dumpCalibration(dump);
1772 dumpSurfaceLocked(dump);
Jeff Brownefd32662011-03-08 15:13:06 -08001773
Jeff Brown511ee5f2010-10-18 13:32:20 -07001774 dump.appendFormat(INDENT3 "Translation and Scaling Factors:\n");
Jeff Brownc6d282b2010-10-14 21:42:15 -07001775 dump.appendFormat(INDENT4 "XScale: %0.3f\n", mLocked.xScale);
1776 dump.appendFormat(INDENT4 "YScale: %0.3f\n", mLocked.yScale);
1777 dump.appendFormat(INDENT4 "XPrecision: %0.3f\n", mLocked.xPrecision);
1778 dump.appendFormat(INDENT4 "YPrecision: %0.3f\n", mLocked.yPrecision);
1779 dump.appendFormat(INDENT4 "GeometricScale: %0.3f\n", mLocked.geometricScale);
1780 dump.appendFormat(INDENT4 "ToolSizeLinearScale: %0.3f\n", mLocked.toolSizeLinearScale);
1781 dump.appendFormat(INDENT4 "ToolSizeLinearBias: %0.3f\n", mLocked.toolSizeLinearBias);
1782 dump.appendFormat(INDENT4 "ToolSizeAreaScale: %0.3f\n", mLocked.toolSizeAreaScale);
1783 dump.appendFormat(INDENT4 "ToolSizeAreaBias: %0.3f\n", mLocked.toolSizeAreaBias);
1784 dump.appendFormat(INDENT4 "PressureScale: %0.3f\n", mLocked.pressureScale);
1785 dump.appendFormat(INDENT4 "SizeScale: %0.3f\n", mLocked.sizeScale);
Jeff Brownefd32662011-03-08 15:13:06 -08001786 dump.appendFormat(INDENT4 "OrientationScale: %0.3f\n", mLocked.orientationScale);
1787
1788 dump.appendFormat(INDENT3 "Last Touch:\n");
1789 dump.appendFormat(INDENT4 "Pointer Count: %d\n", mLastTouch.pointerCount);
Jeff Brown96ad3972011-03-09 17:39:48 -08001790 dump.appendFormat(INDENT4 "Button State: 0x%08x\n", mLastTouch.buttonState);
1791
1792 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
1793 dump.appendFormat(INDENT3 "Pointer Gesture Detector:\n");
1794 dump.appendFormat(INDENT4 "XMovementScale: %0.3f\n",
1795 mLocked.pointerGestureXMovementScale);
1796 dump.appendFormat(INDENT4 "YMovementScale: %0.3f\n",
1797 mLocked.pointerGestureYMovementScale);
1798 dump.appendFormat(INDENT4 "XZoomScale: %0.3f\n",
1799 mLocked.pointerGestureXZoomScale);
1800 dump.appendFormat(INDENT4 "YZoomScale: %0.3f\n",
1801 mLocked.pointerGestureYZoomScale);
Jeff Brown86ea1f52011-04-12 22:39:53 -07001802 dump.appendFormat(INDENT4 "MaxSwipeWidth: %f\n",
1803 mLocked.pointerGestureMaxSwipeWidth);
Jeff Brown96ad3972011-03-09 17:39:48 -08001804 }
Jeff Brownef3d7e82010-09-30 14:33:04 -07001805 } // release lock
1806}
1807
Jeff Brown6328cdc2010-07-29 18:18:33 -07001808void TouchInputMapper::initializeLocked() {
1809 mCurrentTouch.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001810 mLastTouch.clear();
1811 mDownTime = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07001812
1813 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
1814 mAveragingTouchFilter.historyStart[i] = 0;
1815 mAveragingTouchFilter.historyEnd[i] = 0;
1816 }
1817
1818 mJumpyTouchFilter.jumpyPointsDropped = 0;
Jeff Brown6328cdc2010-07-29 18:18:33 -07001819
1820 mLocked.currentVirtualKey.down = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001821
1822 mLocked.orientedRanges.havePressure = false;
1823 mLocked.orientedRanges.haveSize = false;
Jeff Brownc6d282b2010-10-14 21:42:15 -07001824 mLocked.orientedRanges.haveTouchSize = false;
1825 mLocked.orientedRanges.haveToolSize = false;
Jeff Brown8d608662010-08-30 03:02:23 -07001826 mLocked.orientedRanges.haveOrientation = false;
Jeff Brown96ad3972011-03-09 17:39:48 -08001827
1828 mPointerGesture.reset();
Jeff Brown8d608662010-08-30 03:02:23 -07001829}
1830
Jeff Brown6d0fec22010-07-23 21:28:06 -07001831void TouchInputMapper::configure() {
1832 InputMapper::configure();
1833
1834 // Configure basic parameters.
Jeff Brown8d608662010-08-30 03:02:23 -07001835 configureParameters();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001836
Jeff Brown83c09682010-12-23 17:50:18 -08001837 // Configure sources.
1838 switch (mParameters.deviceType) {
1839 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
Jeff Brownefd32662011-03-08 15:13:06 -08001840 mTouchSource = AINPUT_SOURCE_TOUCHSCREEN;
Jeff Brown96ad3972011-03-09 17:39:48 -08001841 mPointerSource = 0;
Jeff Brown83c09682010-12-23 17:50:18 -08001842 break;
1843 case Parameters::DEVICE_TYPE_TOUCH_PAD:
Jeff Brownefd32662011-03-08 15:13:06 -08001844 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
Jeff Brown96ad3972011-03-09 17:39:48 -08001845 mPointerSource = 0;
1846 break;
1847 case Parameters::DEVICE_TYPE_POINTER:
1848 mTouchSource = AINPUT_SOURCE_TOUCHPAD;
1849 mPointerSource = AINPUT_SOURCE_MOUSE;
Jeff Brown83c09682010-12-23 17:50:18 -08001850 break;
1851 default:
1852 assert(false);
1853 }
1854
Jeff Brown6d0fec22010-07-23 21:28:06 -07001855 // Configure absolute axis information.
Jeff Brown8d608662010-08-30 03:02:23 -07001856 configureRawAxes();
Jeff Brown8d608662010-08-30 03:02:23 -07001857
1858 // Prepare input device calibration.
1859 parseCalibration();
1860 resolveCalibration();
Jeff Brown6d0fec22010-07-23 21:28:06 -07001861
Jeff Brown6328cdc2010-07-29 18:18:33 -07001862 { // acquire lock
1863 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07001864
Jeff Brown8d608662010-08-30 03:02:23 -07001865 // Configure surface dimensions and orientation.
Jeff Brown6328cdc2010-07-29 18:18:33 -07001866 configureSurfaceLocked();
1867 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07001868}
1869
Jeff Brown8d608662010-08-30 03:02:23 -07001870void TouchInputMapper::configureParameters() {
1871 mParameters.useBadTouchFilter = getPolicy()->filterTouchEvents();
1872 mParameters.useAveragingTouchFilter = getPolicy()->filterTouchEvents();
1873 mParameters.useJumpyTouchFilter = getPolicy()->filterJumpyTouchEvents();
Jeff Brownfe508922011-01-18 15:10:10 -08001874 mParameters.virtualKeyQuietTime = getPolicy()->getVirtualKeyQuietTime();
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001875
Jeff Brown86ea1f52011-04-12 22:39:53 -07001876 // TODO: Make this configurable.
1877 //mParameters.gestureMode = Parameters::GESTURE_MODE_POINTER;
1878 mParameters.gestureMode = Parameters::GESTURE_MODE_SPOTS;
1879
Jeff Brown96ad3972011-03-09 17:39:48 -08001880 if (getEventHub()->hasRelativeAxis(getDeviceId(), REL_X)
1881 || getEventHub()->hasRelativeAxis(getDeviceId(), REL_Y)) {
1882 // The device is a cursor device with a touch pad attached.
1883 // By default don't use the touch pad to move the pointer.
1884 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
1885 } else {
1886 // The device is just a touch pad.
1887 // By default use the touch pad to move the pointer and to perform related gestures.
1888 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
1889 }
1890
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001891 String8 deviceTypeString;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001892 if (getDevice()->getConfiguration().tryGetProperty(String8("touch.deviceType"),
1893 deviceTypeString)) {
Jeff Brown58a2da82011-01-25 16:02:22 -08001894 if (deviceTypeString == "touchScreen") {
1895 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brownefd32662011-03-08 15:13:06 -08001896 } else if (deviceTypeString == "touchPad") {
1897 mParameters.deviceType = Parameters::DEVICE_TYPE_TOUCH_PAD;
Jeff Brown96ad3972011-03-09 17:39:48 -08001898 } else if (deviceTypeString == "pointer") {
1899 mParameters.deviceType = Parameters::DEVICE_TYPE_POINTER;
Jeff Brownefd32662011-03-08 15:13:06 -08001900 } else {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001901 LOGW("Invalid value for touch.deviceType: '%s'", deviceTypeString.string());
1902 }
1903 }
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001904
Jeff Brownefd32662011-03-08 15:13:06 -08001905 mParameters.orientationAware = mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001906 getDevice()->getConfiguration().tryGetProperty(String8("touch.orientationAware"),
1907 mParameters.orientationAware);
1908
Jeff Brownefd32662011-03-08 15:13:06 -08001909 mParameters.associatedDisplayId = mParameters.orientationAware
1910 || mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN
Jeff Brown96ad3972011-03-09 17:39:48 -08001911 || mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
Jeff Brownefd32662011-03-08 15:13:06 -08001912 ? 0 : -1;
Jeff Brown8d608662010-08-30 03:02:23 -07001913}
1914
Jeff Brownef3d7e82010-09-30 14:33:04 -07001915void TouchInputMapper::dumpParameters(String8& dump) {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001916 dump.append(INDENT3 "Parameters:\n");
1917
1918 switch (mParameters.deviceType) {
1919 case Parameters::DEVICE_TYPE_TOUCH_SCREEN:
1920 dump.append(INDENT4 "DeviceType: touchScreen\n");
1921 break;
1922 case Parameters::DEVICE_TYPE_TOUCH_PAD:
1923 dump.append(INDENT4 "DeviceType: touchPad\n");
1924 break;
Jeff Brown96ad3972011-03-09 17:39:48 -08001925 case Parameters::DEVICE_TYPE_POINTER:
1926 dump.append(INDENT4 "DeviceType: pointer\n");
1927 break;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001928 default:
1929 assert(false);
1930 }
1931
1932 dump.appendFormat(INDENT4 "AssociatedDisplayId: %d\n",
1933 mParameters.associatedDisplayId);
1934 dump.appendFormat(INDENT4 "OrientationAware: %s\n",
1935 toString(mParameters.orientationAware));
1936
1937 dump.appendFormat(INDENT4 "UseBadTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001938 toString(mParameters.useBadTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001939 dump.appendFormat(INDENT4 "UseAveragingTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001940 toString(mParameters.useAveragingTouchFilter));
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001941 dump.appendFormat(INDENT4 "UseJumpyTouchFilter: %s\n",
Jeff Brownef3d7e82010-09-30 14:33:04 -07001942 toString(mParameters.useJumpyTouchFilter));
Jeff Brownb88102f2010-09-08 11:49:43 -07001943}
1944
Jeff Brown8d608662010-08-30 03:02:23 -07001945void TouchInputMapper::configureRawAxes() {
1946 mRawAxes.x.clear();
1947 mRawAxes.y.clear();
1948 mRawAxes.pressure.clear();
1949 mRawAxes.touchMajor.clear();
1950 mRawAxes.touchMinor.clear();
1951 mRawAxes.toolMajor.clear();
1952 mRawAxes.toolMinor.clear();
1953 mRawAxes.orientation.clear();
1954}
1955
Jeff Brownef3d7e82010-09-30 14:33:04 -07001956void TouchInputMapper::dumpRawAxes(String8& dump) {
1957 dump.append(INDENT3 "Raw Axes:\n");
Jeff Browncb1404e2011-01-15 18:14:15 -08001958 dumpRawAbsoluteAxisInfo(dump, mRawAxes.x, "X");
1959 dumpRawAbsoluteAxisInfo(dump, mRawAxes.y, "Y");
1960 dumpRawAbsoluteAxisInfo(dump, mRawAxes.pressure, "Pressure");
1961 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMajor, "TouchMajor");
1962 dumpRawAbsoluteAxisInfo(dump, mRawAxes.touchMinor, "TouchMinor");
1963 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMajor, "ToolMajor");
1964 dumpRawAbsoluteAxisInfo(dump, mRawAxes.toolMinor, "ToolMinor");
1965 dumpRawAbsoluteAxisInfo(dump, mRawAxes.orientation, "Orientation");
Jeff Brown6d0fec22010-07-23 21:28:06 -07001966}
1967
Jeff Brown6328cdc2010-07-29 18:18:33 -07001968bool TouchInputMapper::configureSurfaceLocked() {
Jeff Brown9626b142011-03-03 02:09:54 -08001969 // Ensure we have valid X and Y axes.
1970 if (!mRawAxes.x.valid || !mRawAxes.y.valid) {
1971 LOGW(INDENT "Touch device '%s' did not report support for X or Y axis! "
1972 "The device will be inoperable.", getDeviceName().string());
1973 return false;
1974 }
1975
Jeff Brown6d0fec22010-07-23 21:28:06 -07001976 // Update orientation and dimensions if needed.
Jeff Brownb4ff35d2011-01-02 16:37:43 -08001977 int32_t orientation = DISPLAY_ORIENTATION_0;
Jeff Brown9626b142011-03-03 02:09:54 -08001978 int32_t width = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
1979 int32_t height = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001980
1981 if (mParameters.associatedDisplayId >= 0) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07001982 // Note: getDisplayInfo is non-reentrant so we can continue holding the lock.
Jeff Brown47e6b1b2010-11-29 17:37:49 -08001983 if (! getPolicy()->getDisplayInfo(mParameters.associatedDisplayId,
Jeff Brownefd32662011-03-08 15:13:06 -08001984 &mLocked.associatedDisplayWidth, &mLocked.associatedDisplayHeight,
1985 &mLocked.associatedDisplayOrientation)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07001986 return false;
1987 }
Jeff Brownefd32662011-03-08 15:13:06 -08001988
1989 // A touch screen inherits the dimensions of the display.
1990 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
1991 width = mLocked.associatedDisplayWidth;
1992 height = mLocked.associatedDisplayHeight;
1993 }
1994
1995 // The device inherits the orientation of the display if it is orientation aware.
1996 if (mParameters.orientationAware) {
1997 orientation = mLocked.associatedDisplayOrientation;
1998 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07001999 }
2000
Jeff Brown96ad3972011-03-09 17:39:48 -08002001 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER
2002 && mPointerController == NULL) {
2003 mPointerController = getPolicy()->obtainPointerController(getDeviceId());
2004 }
2005
Jeff Brown6328cdc2010-07-29 18:18:33 -07002006 bool orientationChanged = mLocked.surfaceOrientation != orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002007 if (orientationChanged) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002008 mLocked.surfaceOrientation = orientation;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002009 }
2010
Jeff Brown6328cdc2010-07-29 18:18:33 -07002011 bool sizeChanged = mLocked.surfaceWidth != width || mLocked.surfaceHeight != height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002012 if (sizeChanged) {
Jeff Brownefd32662011-03-08 15:13:06 -08002013 LOGI("Device reconfigured: id=%d, name='%s', surface size is now %dx%d",
Jeff Brownef3d7e82010-09-30 14:33:04 -07002014 getDeviceId(), getDeviceName().string(), width, height);
Jeff Brown8d608662010-08-30 03:02:23 -07002015
Jeff Brown6328cdc2010-07-29 18:18:33 -07002016 mLocked.surfaceWidth = width;
2017 mLocked.surfaceHeight = height;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002018
Jeff Brown8d608662010-08-30 03:02:23 -07002019 // Configure X and Y factors.
Jeff Brown9626b142011-03-03 02:09:54 -08002020 mLocked.xScale = float(width) / (mRawAxes.x.maxValue - mRawAxes.x.minValue + 1);
2021 mLocked.yScale = float(height) / (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1);
2022 mLocked.xPrecision = 1.0f / mLocked.xScale;
2023 mLocked.yPrecision = 1.0f / mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002024
Jeff Brownefd32662011-03-08 15:13:06 -08002025 mLocked.orientedRanges.x.axis = AMOTION_EVENT_AXIS_X;
2026 mLocked.orientedRanges.x.source = mTouchSource;
2027 mLocked.orientedRanges.y.axis = AMOTION_EVENT_AXIS_Y;
2028 mLocked.orientedRanges.y.source = mTouchSource;
2029
Jeff Brown9626b142011-03-03 02:09:54 -08002030 configureVirtualKeysLocked();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002031
Jeff Brown8d608662010-08-30 03:02:23 -07002032 // Scale factor for terms that are not oriented in a particular axis.
2033 // If the pixels are square then xScale == yScale otherwise we fake it
2034 // by choosing an average.
2035 mLocked.geometricScale = avg(mLocked.xScale, mLocked.yScale);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002036
Jeff Brown8d608662010-08-30 03:02:23 -07002037 // Size of diagonal axis.
Jeff Brown86ea1f52011-04-12 22:39:53 -07002038 float diagonalSize = hypotf(width, height);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002039
Jeff Brown8d608662010-08-30 03:02:23 -07002040 // TouchMajor and TouchMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002041 if (mCalibration.touchSizeCalibration != Calibration::TOUCH_SIZE_CALIBRATION_NONE) {
2042 mLocked.orientedRanges.haveTouchSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002043
2044 mLocked.orientedRanges.touchMajor.axis = AMOTION_EVENT_AXIS_TOUCH_MAJOR;
2045 mLocked.orientedRanges.touchMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002046 mLocked.orientedRanges.touchMajor.min = 0;
2047 mLocked.orientedRanges.touchMajor.max = diagonalSize;
2048 mLocked.orientedRanges.touchMajor.flat = 0;
2049 mLocked.orientedRanges.touchMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002050
Jeff Brown8d608662010-08-30 03:02:23 -07002051 mLocked.orientedRanges.touchMinor = mLocked.orientedRanges.touchMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08002052 mLocked.orientedRanges.touchMinor.axis = AMOTION_EVENT_AXIS_TOUCH_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002053 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002054
Jeff Brown8d608662010-08-30 03:02:23 -07002055 // ToolMajor and ToolMinor factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002056 mLocked.toolSizeLinearScale = 0;
2057 mLocked.toolSizeLinearBias = 0;
2058 mLocked.toolSizeAreaScale = 0;
2059 mLocked.toolSizeAreaBias = 0;
2060 if (mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2061 if (mCalibration.toolSizeCalibration == Calibration::TOOL_SIZE_CALIBRATION_LINEAR) {
2062 if (mCalibration.haveToolSizeLinearScale) {
2063 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
Jeff Brown8d608662010-08-30 03:02:23 -07002064 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002065 mLocked.toolSizeLinearScale = float(min(width, height))
Jeff Brown8d608662010-08-30 03:02:23 -07002066 / mRawAxes.toolMajor.maxValue;
2067 }
2068
Jeff Brownc6d282b2010-10-14 21:42:15 -07002069 if (mCalibration.haveToolSizeLinearBias) {
2070 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2071 }
2072 } else if (mCalibration.toolSizeCalibration ==
2073 Calibration::TOOL_SIZE_CALIBRATION_AREA) {
2074 if (mCalibration.haveToolSizeLinearScale) {
2075 mLocked.toolSizeLinearScale = mCalibration.toolSizeLinearScale;
2076 } else {
2077 mLocked.toolSizeLinearScale = min(width, height);
2078 }
2079
2080 if (mCalibration.haveToolSizeLinearBias) {
2081 mLocked.toolSizeLinearBias = mCalibration.toolSizeLinearBias;
2082 }
2083
2084 if (mCalibration.haveToolSizeAreaScale) {
2085 mLocked.toolSizeAreaScale = mCalibration.toolSizeAreaScale;
2086 } else if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2087 mLocked.toolSizeAreaScale = 1.0f / mRawAxes.toolMajor.maxValue;
2088 }
2089
2090 if (mCalibration.haveToolSizeAreaBias) {
2091 mLocked.toolSizeAreaBias = mCalibration.toolSizeAreaBias;
Jeff Brown8d608662010-08-30 03:02:23 -07002092 }
2093 }
2094
Jeff Brownc6d282b2010-10-14 21:42:15 -07002095 mLocked.orientedRanges.haveToolSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002096
2097 mLocked.orientedRanges.toolMajor.axis = AMOTION_EVENT_AXIS_TOOL_MAJOR;
2098 mLocked.orientedRanges.toolMajor.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002099 mLocked.orientedRanges.toolMajor.min = 0;
2100 mLocked.orientedRanges.toolMajor.max = diagonalSize;
2101 mLocked.orientedRanges.toolMajor.flat = 0;
2102 mLocked.orientedRanges.toolMajor.fuzz = 0;
Jeff Brownefd32662011-03-08 15:13:06 -08002103
Jeff Brown8d608662010-08-30 03:02:23 -07002104 mLocked.orientedRanges.toolMinor = mLocked.orientedRanges.toolMajor;
Jeff Brownefd32662011-03-08 15:13:06 -08002105 mLocked.orientedRanges.toolMinor.axis = AMOTION_EVENT_AXIS_TOOL_MINOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002106 }
2107
2108 // Pressure factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002109 mLocked.pressureScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002110 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE) {
2111 RawAbsoluteAxisInfo rawPressureAxis;
2112 switch (mCalibration.pressureSource) {
2113 case Calibration::PRESSURE_SOURCE_PRESSURE:
2114 rawPressureAxis = mRawAxes.pressure;
2115 break;
2116 case Calibration::PRESSURE_SOURCE_TOUCH:
2117 rawPressureAxis = mRawAxes.touchMajor;
2118 break;
2119 default:
2120 rawPressureAxis.clear();
2121 }
2122
Jeff Brown8d608662010-08-30 03:02:23 -07002123 if (mCalibration.pressureCalibration == Calibration::PRESSURE_CALIBRATION_PHYSICAL
2124 || mCalibration.pressureCalibration
2125 == Calibration::PRESSURE_CALIBRATION_AMPLITUDE) {
2126 if (mCalibration.havePressureScale) {
2127 mLocked.pressureScale = mCalibration.pressureScale;
2128 } else if (rawPressureAxis.valid && rawPressureAxis.maxValue != 0) {
2129 mLocked.pressureScale = 1.0f / rawPressureAxis.maxValue;
2130 }
2131 }
2132
2133 mLocked.orientedRanges.havePressure = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002134
2135 mLocked.orientedRanges.pressure.axis = AMOTION_EVENT_AXIS_PRESSURE;
2136 mLocked.orientedRanges.pressure.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002137 mLocked.orientedRanges.pressure.min = 0;
2138 mLocked.orientedRanges.pressure.max = 1.0;
2139 mLocked.orientedRanges.pressure.flat = 0;
2140 mLocked.orientedRanges.pressure.fuzz = 0;
2141 }
2142
2143 // Size factors.
Jeff Brownc6d282b2010-10-14 21:42:15 -07002144 mLocked.sizeScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002145 if (mCalibration.sizeCalibration != Calibration::SIZE_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002146 if (mCalibration.sizeCalibration == Calibration::SIZE_CALIBRATION_NORMALIZED) {
2147 if (mRawAxes.toolMajor.valid && mRawAxes.toolMajor.maxValue != 0) {
2148 mLocked.sizeScale = 1.0f / mRawAxes.toolMajor.maxValue;
2149 }
2150 }
2151
2152 mLocked.orientedRanges.haveSize = true;
Jeff Brownefd32662011-03-08 15:13:06 -08002153
2154 mLocked.orientedRanges.size.axis = AMOTION_EVENT_AXIS_SIZE;
2155 mLocked.orientedRanges.size.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002156 mLocked.orientedRanges.size.min = 0;
2157 mLocked.orientedRanges.size.max = 1.0;
2158 mLocked.orientedRanges.size.flat = 0;
2159 mLocked.orientedRanges.size.fuzz = 0;
2160 }
2161
2162 // Orientation
Jeff Brownc6d282b2010-10-14 21:42:15 -07002163 mLocked.orientationScale = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07002164 if (mCalibration.orientationCalibration != Calibration::ORIENTATION_CALIBRATION_NONE) {
Jeff Brown8d608662010-08-30 03:02:23 -07002165 if (mCalibration.orientationCalibration
2166 == Calibration::ORIENTATION_CALIBRATION_INTERPOLATED) {
2167 if (mRawAxes.orientation.valid && mRawAxes.orientation.maxValue != 0) {
2168 mLocked.orientationScale = float(M_PI_2) / mRawAxes.orientation.maxValue;
2169 }
2170 }
2171
Jeff Brownefd32662011-03-08 15:13:06 -08002172 mLocked.orientedRanges.orientation.axis = AMOTION_EVENT_AXIS_ORIENTATION;
2173 mLocked.orientedRanges.orientation.source = mTouchSource;
Jeff Brown8d608662010-08-30 03:02:23 -07002174 mLocked.orientedRanges.orientation.min = - M_PI_2;
2175 mLocked.orientedRanges.orientation.max = M_PI_2;
2176 mLocked.orientedRanges.orientation.flat = 0;
2177 mLocked.orientedRanges.orientation.fuzz = 0;
2178 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002179 }
2180
2181 if (orientationChanged || sizeChanged) {
Jeff Brown9626b142011-03-03 02:09:54 -08002182 // Compute oriented surface dimensions, precision, scales and ranges.
2183 // Note that the maximum value reported is an inclusive maximum value so it is one
2184 // unit less than the total width or height of surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002185 switch (mLocked.surfaceOrientation) {
Jeff Brownb4ff35d2011-01-02 16:37:43 -08002186 case DISPLAY_ORIENTATION_90:
2187 case DISPLAY_ORIENTATION_270:
Jeff Brown6328cdc2010-07-29 18:18:33 -07002188 mLocked.orientedSurfaceWidth = mLocked.surfaceHeight;
2189 mLocked.orientedSurfaceHeight = mLocked.surfaceWidth;
Jeff Brown9626b142011-03-03 02:09:54 -08002190
Jeff Brown6328cdc2010-07-29 18:18:33 -07002191 mLocked.orientedXPrecision = mLocked.yPrecision;
2192 mLocked.orientedYPrecision = mLocked.xPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002193
2194 mLocked.orientedRanges.x.min = 0;
2195 mLocked.orientedRanges.x.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2196 * mLocked.yScale;
2197 mLocked.orientedRanges.x.flat = 0;
2198 mLocked.orientedRanges.x.fuzz = mLocked.yScale;
2199
2200 mLocked.orientedRanges.y.min = 0;
2201 mLocked.orientedRanges.y.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2202 * mLocked.xScale;
2203 mLocked.orientedRanges.y.flat = 0;
2204 mLocked.orientedRanges.y.fuzz = mLocked.xScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002205 break;
Jeff Brown9626b142011-03-03 02:09:54 -08002206
Jeff Brown6d0fec22010-07-23 21:28:06 -07002207 default:
Jeff Brown6328cdc2010-07-29 18:18:33 -07002208 mLocked.orientedSurfaceWidth = mLocked.surfaceWidth;
2209 mLocked.orientedSurfaceHeight = mLocked.surfaceHeight;
Jeff Brown9626b142011-03-03 02:09:54 -08002210
Jeff Brown6328cdc2010-07-29 18:18:33 -07002211 mLocked.orientedXPrecision = mLocked.xPrecision;
2212 mLocked.orientedYPrecision = mLocked.yPrecision;
Jeff Brown9626b142011-03-03 02:09:54 -08002213
2214 mLocked.orientedRanges.x.min = 0;
2215 mLocked.orientedRanges.x.max = (mRawAxes.x.maxValue - mRawAxes.x.minValue)
2216 * mLocked.xScale;
2217 mLocked.orientedRanges.x.flat = 0;
2218 mLocked.orientedRanges.x.fuzz = mLocked.xScale;
2219
2220 mLocked.orientedRanges.y.min = 0;
2221 mLocked.orientedRanges.y.max = (mRawAxes.y.maxValue - mRawAxes.y.minValue)
2222 * mLocked.yScale;
2223 mLocked.orientedRanges.y.flat = 0;
2224 mLocked.orientedRanges.y.fuzz = mLocked.yScale;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002225 break;
2226 }
Jeff Brown96ad3972011-03-09 17:39:48 -08002227
2228 // Compute pointer gesture detection parameters.
2229 // TODO: These factors should not be hardcoded.
2230 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
2231 int32_t rawWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2232 int32_t rawHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown86ea1f52011-04-12 22:39:53 -07002233 float rawDiagonal = hypotf(rawWidth, rawHeight);
2234 float displayDiagonal = hypotf(mLocked.associatedDisplayWidth,
2235 mLocked.associatedDisplayHeight);
Jeff Brown96ad3972011-03-09 17:39:48 -08002236
Jeff Brown86ea1f52011-04-12 22:39:53 -07002237 // Scale movements such that one whole swipe of the touch pad covers a
2238 // given area relative to the diagonal size of the display.
Jeff Brown96ad3972011-03-09 17:39:48 -08002239 // Assume that the touch pad has a square aspect ratio such that movements in
2240 // X and Y of the same number of raw units cover the same physical distance.
2241 const float scaleFactor = 0.8f;
2242
Jeff Brown86ea1f52011-04-12 22:39:53 -07002243 mLocked.pointerGestureXMovementScale = GESTURE_MOVEMENT_SPEED_RATIO
2244 * displayDiagonal / rawDiagonal;
Jeff Brown96ad3972011-03-09 17:39:48 -08002245 mLocked.pointerGestureYMovementScale = mLocked.pointerGestureXMovementScale;
2246
2247 // Scale zooms to cover a smaller range of the display than movements do.
2248 // This value determines the area around the pointer that is affected by freeform
2249 // pointer gestures.
Jeff Brown86ea1f52011-04-12 22:39:53 -07002250 mLocked.pointerGestureXZoomScale = GESTURE_ZOOM_SPEED_RATIO
2251 * displayDiagonal / rawDiagonal;
2252 mLocked.pointerGestureYZoomScale = mLocked.pointerGestureXZoomScale;
Jeff Brown96ad3972011-03-09 17:39:48 -08002253
Jeff Brown86ea1f52011-04-12 22:39:53 -07002254 // Max width between pointers to detect a swipe gesture is more than some fraction
2255 // of the diagonal axis of the touch pad. Touches that are wider than this are
2256 // translated into freeform gestures.
2257 mLocked.pointerGestureMaxSwipeWidth = SWIPE_MAX_WIDTH_RATIO * rawDiagonal;
2258
2259 // Reset the current pointer gesture.
2260 mPointerGesture.reset();
2261
2262 // Remove any current spots.
2263 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2264 mPointerController->clearSpots();
2265 }
Jeff Brown96ad3972011-03-09 17:39:48 -08002266 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002267 }
2268
2269 return true;
2270}
2271
Jeff Brownef3d7e82010-09-30 14:33:04 -07002272void TouchInputMapper::dumpSurfaceLocked(String8& dump) {
2273 dump.appendFormat(INDENT3 "SurfaceWidth: %dpx\n", mLocked.surfaceWidth);
2274 dump.appendFormat(INDENT3 "SurfaceHeight: %dpx\n", mLocked.surfaceHeight);
2275 dump.appendFormat(INDENT3 "SurfaceOrientation: %d\n", mLocked.surfaceOrientation);
Jeff Brownb88102f2010-09-08 11:49:43 -07002276}
2277
Jeff Brown6328cdc2010-07-29 18:18:33 -07002278void TouchInputMapper::configureVirtualKeysLocked() {
Jeff Brown8d608662010-08-30 03:02:23 -07002279 Vector<VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown90655042010-12-02 13:50:46 -08002280 getEventHub()->getVirtualKeyDefinitions(getDeviceId(), virtualKeyDefinitions);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002281
Jeff Brown6328cdc2010-07-29 18:18:33 -07002282 mLocked.virtualKeys.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002283
Jeff Brown6328cdc2010-07-29 18:18:33 -07002284 if (virtualKeyDefinitions.size() == 0) {
2285 return;
2286 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002287
Jeff Brown6328cdc2010-07-29 18:18:33 -07002288 mLocked.virtualKeys.setCapacity(virtualKeyDefinitions.size());
2289
Jeff Brown8d608662010-08-30 03:02:23 -07002290 int32_t touchScreenLeft = mRawAxes.x.minValue;
2291 int32_t touchScreenTop = mRawAxes.y.minValue;
Jeff Brown9626b142011-03-03 02:09:54 -08002292 int32_t touchScreenWidth = mRawAxes.x.maxValue - mRawAxes.x.minValue + 1;
2293 int32_t touchScreenHeight = mRawAxes.y.maxValue - mRawAxes.y.minValue + 1;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002294
2295 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown8d608662010-08-30 03:02:23 -07002296 const VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown6328cdc2010-07-29 18:18:33 -07002297 virtualKeyDefinitions[i];
2298
2299 mLocked.virtualKeys.add();
2300 VirtualKey& virtualKey = mLocked.virtualKeys.editTop();
2301
2302 virtualKey.scanCode = virtualKeyDefinition.scanCode;
2303 int32_t keyCode;
2304 uint32_t flags;
Jeff Brown6f2fba42011-02-19 01:08:02 -08002305 if (getEventHub()->mapKey(getDeviceId(), virtualKey.scanCode,
Jeff Brown6328cdc2010-07-29 18:18:33 -07002306 & keyCode, & flags)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002307 LOGW(INDENT "VirtualKey %d: could not obtain key code, ignoring",
2308 virtualKey.scanCode);
Jeff Brown6328cdc2010-07-29 18:18:33 -07002309 mLocked.virtualKeys.pop(); // drop the key
2310 continue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002311 }
2312
Jeff Brown6328cdc2010-07-29 18:18:33 -07002313 virtualKey.keyCode = keyCode;
2314 virtualKey.flags = flags;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002315
Jeff Brown6328cdc2010-07-29 18:18:33 -07002316 // convert the key definition's display coordinates into touch coordinates for a hit box
2317 int32_t halfWidth = virtualKeyDefinition.width / 2;
2318 int32_t halfHeight = virtualKeyDefinition.height / 2;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002319
Jeff Brown6328cdc2010-07-29 18:18:33 -07002320 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
2321 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2322 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
2323 * touchScreenWidth / mLocked.surfaceWidth + touchScreenLeft;
2324 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
2325 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
2326 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
2327 * touchScreenHeight / mLocked.surfaceHeight + touchScreenTop;
Jeff Brownef3d7e82010-09-30 14:33:04 -07002328 }
2329}
2330
2331void TouchInputMapper::dumpVirtualKeysLocked(String8& dump) {
2332 if (!mLocked.virtualKeys.isEmpty()) {
2333 dump.append(INDENT3 "Virtual Keys:\n");
2334
2335 for (size_t i = 0; i < mLocked.virtualKeys.size(); i++) {
2336 const VirtualKey& virtualKey = mLocked.virtualKeys.itemAt(i);
2337 dump.appendFormat(INDENT4 "%d: scanCode=%d, keyCode=%d, "
2338 "hitLeft=%d, hitRight=%d, hitTop=%d, hitBottom=%d\n",
2339 i, virtualKey.scanCode, virtualKey.keyCode,
2340 virtualKey.hitLeft, virtualKey.hitRight,
2341 virtualKey.hitTop, virtualKey.hitBottom);
2342 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002343 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002344}
2345
Jeff Brown8d608662010-08-30 03:02:23 -07002346void TouchInputMapper::parseCalibration() {
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002347 const PropertyMap& in = getDevice()->getConfiguration();
Jeff Brown8d608662010-08-30 03:02:23 -07002348 Calibration& out = mCalibration;
2349
Jeff Brownc6d282b2010-10-14 21:42:15 -07002350 // Touch Size
2351 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT;
2352 String8 touchSizeCalibrationString;
2353 if (in.tryGetProperty(String8("touch.touchSize.calibration"), touchSizeCalibrationString)) {
2354 if (touchSizeCalibrationString == "none") {
2355 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
2356 } else if (touchSizeCalibrationString == "geometric") {
2357 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC;
2358 } else if (touchSizeCalibrationString == "pressure") {
2359 out.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
2360 } else if (touchSizeCalibrationString != "default") {
2361 LOGW("Invalid value for touch.touchSize.calibration: '%s'",
2362 touchSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002363 }
2364 }
2365
Jeff Brownc6d282b2010-10-14 21:42:15 -07002366 // Tool Size
2367 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_DEFAULT;
2368 String8 toolSizeCalibrationString;
2369 if (in.tryGetProperty(String8("touch.toolSize.calibration"), toolSizeCalibrationString)) {
2370 if (toolSizeCalibrationString == "none") {
2371 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
2372 } else if (toolSizeCalibrationString == "geometric") {
2373 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC;
2374 } else if (toolSizeCalibrationString == "linear") {
2375 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
2376 } else if (toolSizeCalibrationString == "area") {
2377 out.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_AREA;
2378 } else if (toolSizeCalibrationString != "default") {
2379 LOGW("Invalid value for touch.toolSize.calibration: '%s'",
2380 toolSizeCalibrationString.string());
Jeff Brown8d608662010-08-30 03:02:23 -07002381 }
2382 }
2383
Jeff Brownc6d282b2010-10-14 21:42:15 -07002384 out.haveToolSizeLinearScale = in.tryGetProperty(String8("touch.toolSize.linearScale"),
2385 out.toolSizeLinearScale);
2386 out.haveToolSizeLinearBias = in.tryGetProperty(String8("touch.toolSize.linearBias"),
2387 out.toolSizeLinearBias);
2388 out.haveToolSizeAreaScale = in.tryGetProperty(String8("touch.toolSize.areaScale"),
2389 out.toolSizeAreaScale);
2390 out.haveToolSizeAreaBias = in.tryGetProperty(String8("touch.toolSize.areaBias"),
2391 out.toolSizeAreaBias);
2392 out.haveToolSizeIsSummed = in.tryGetProperty(String8("touch.toolSize.isSummed"),
2393 out.toolSizeIsSummed);
Jeff Brown8d608662010-08-30 03:02:23 -07002394
2395 // Pressure
2396 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_DEFAULT;
2397 String8 pressureCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002398 if (in.tryGetProperty(String8("touch.pressure.calibration"), pressureCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002399 if (pressureCalibrationString == "none") {
2400 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2401 } else if (pressureCalibrationString == "physical") {
2402 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_PHYSICAL;
2403 } else if (pressureCalibrationString == "amplitude") {
2404 out.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2405 } else if (pressureCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002406 LOGW("Invalid value for touch.pressure.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002407 pressureCalibrationString.string());
2408 }
2409 }
2410
2411 out.pressureSource = Calibration::PRESSURE_SOURCE_DEFAULT;
2412 String8 pressureSourceString;
2413 if (in.tryGetProperty(String8("touch.pressure.source"), pressureSourceString)) {
2414 if (pressureSourceString == "pressure") {
2415 out.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2416 } else if (pressureSourceString == "touch") {
2417 out.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2418 } else if (pressureSourceString != "default") {
2419 LOGW("Invalid value for touch.pressure.source: '%s'",
2420 pressureSourceString.string());
2421 }
2422 }
2423
2424 out.havePressureScale = in.tryGetProperty(String8("touch.pressure.scale"),
2425 out.pressureScale);
2426
2427 // Size
2428 out.sizeCalibration = Calibration::SIZE_CALIBRATION_DEFAULT;
2429 String8 sizeCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002430 if (in.tryGetProperty(String8("touch.size.calibration"), sizeCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002431 if (sizeCalibrationString == "none") {
2432 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2433 } else if (sizeCalibrationString == "normalized") {
2434 out.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2435 } else if (sizeCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002436 LOGW("Invalid value for touch.size.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002437 sizeCalibrationString.string());
2438 }
2439 }
2440
2441 // Orientation
2442 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_DEFAULT;
2443 String8 orientationCalibrationString;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002444 if (in.tryGetProperty(String8("touch.orientation.calibration"), orientationCalibrationString)) {
Jeff Brown8d608662010-08-30 03:02:23 -07002445 if (orientationCalibrationString == "none") {
2446 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2447 } else if (orientationCalibrationString == "interpolated") {
2448 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002449 } else if (orientationCalibrationString == "vector") {
2450 out.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_VECTOR;
Jeff Brown8d608662010-08-30 03:02:23 -07002451 } else if (orientationCalibrationString != "default") {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002452 LOGW("Invalid value for touch.orientation.calibration: '%s'",
Jeff Brown8d608662010-08-30 03:02:23 -07002453 orientationCalibrationString.string());
2454 }
2455 }
2456}
2457
2458void TouchInputMapper::resolveCalibration() {
2459 // Pressure
2460 switch (mCalibration.pressureSource) {
2461 case Calibration::PRESSURE_SOURCE_DEFAULT:
2462 if (mRawAxes.pressure.valid) {
2463 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_PRESSURE;
2464 } else if (mRawAxes.touchMajor.valid) {
2465 mCalibration.pressureSource = Calibration::PRESSURE_SOURCE_TOUCH;
2466 }
2467 break;
2468
2469 case Calibration::PRESSURE_SOURCE_PRESSURE:
2470 if (! mRawAxes.pressure.valid) {
2471 LOGW("Calibration property touch.pressure.source is 'pressure' but "
2472 "the pressure axis is not available.");
2473 }
2474 break;
2475
2476 case Calibration::PRESSURE_SOURCE_TOUCH:
2477 if (! mRawAxes.touchMajor.valid) {
2478 LOGW("Calibration property touch.pressure.source is 'touch' but "
2479 "the touchMajor axis is not available.");
2480 }
2481 break;
2482
2483 default:
2484 break;
2485 }
2486
2487 switch (mCalibration.pressureCalibration) {
2488 case Calibration::PRESSURE_CALIBRATION_DEFAULT:
2489 if (mCalibration.pressureSource != Calibration::PRESSURE_SOURCE_DEFAULT) {
2490 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_AMPLITUDE;
2491 } else {
2492 mCalibration.pressureCalibration = Calibration::PRESSURE_CALIBRATION_NONE;
2493 }
2494 break;
2495
2496 default:
2497 break;
2498 }
2499
Jeff Brownc6d282b2010-10-14 21:42:15 -07002500 // Tool Size
2501 switch (mCalibration.toolSizeCalibration) {
2502 case Calibration::TOOL_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002503 if (mRawAxes.toolMajor.valid) {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002504 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_LINEAR;
Jeff Brown8d608662010-08-30 03:02:23 -07002505 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002506 mCalibration.toolSizeCalibration = Calibration::TOOL_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002507 }
2508 break;
2509
2510 default:
2511 break;
2512 }
2513
Jeff Brownc6d282b2010-10-14 21:42:15 -07002514 // Touch Size
2515 switch (mCalibration.touchSizeCalibration) {
2516 case Calibration::TOUCH_SIZE_CALIBRATION_DEFAULT:
Jeff Brown8d608662010-08-30 03:02:23 -07002517 if (mCalibration.pressureCalibration != Calibration::PRESSURE_CALIBRATION_NONE
Jeff Brownc6d282b2010-10-14 21:42:15 -07002518 && mCalibration.toolSizeCalibration != Calibration::TOOL_SIZE_CALIBRATION_NONE) {
2519 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE;
Jeff Brown8d608662010-08-30 03:02:23 -07002520 } else {
Jeff Brownc6d282b2010-10-14 21:42:15 -07002521 mCalibration.touchSizeCalibration = Calibration::TOUCH_SIZE_CALIBRATION_NONE;
Jeff Brown8d608662010-08-30 03:02:23 -07002522 }
2523 break;
2524
2525 default:
2526 break;
2527 }
2528
2529 // Size
2530 switch (mCalibration.sizeCalibration) {
2531 case Calibration::SIZE_CALIBRATION_DEFAULT:
2532 if (mRawAxes.toolMajor.valid) {
2533 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NORMALIZED;
2534 } else {
2535 mCalibration.sizeCalibration = Calibration::SIZE_CALIBRATION_NONE;
2536 }
2537 break;
2538
2539 default:
2540 break;
2541 }
2542
2543 // Orientation
2544 switch (mCalibration.orientationCalibration) {
2545 case Calibration::ORIENTATION_CALIBRATION_DEFAULT:
2546 if (mRawAxes.orientation.valid) {
2547 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_INTERPOLATED;
2548 } else {
2549 mCalibration.orientationCalibration = Calibration::ORIENTATION_CALIBRATION_NONE;
2550 }
2551 break;
2552
2553 default:
2554 break;
2555 }
2556}
2557
Jeff Brownef3d7e82010-09-30 14:33:04 -07002558void TouchInputMapper::dumpCalibration(String8& dump) {
2559 dump.append(INDENT3 "Calibration:\n");
Jeff Brownb88102f2010-09-08 11:49:43 -07002560
Jeff Brownc6d282b2010-10-14 21:42:15 -07002561 // Touch Size
2562 switch (mCalibration.touchSizeCalibration) {
2563 case Calibration::TOUCH_SIZE_CALIBRATION_NONE:
2564 dump.append(INDENT4 "touch.touchSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002565 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002566 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
2567 dump.append(INDENT4 "touch.touchSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002568 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002569 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
2570 dump.append(INDENT4 "touch.touchSize.calibration: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002571 break;
2572 default:
2573 assert(false);
2574 }
2575
Jeff Brownc6d282b2010-10-14 21:42:15 -07002576 // Tool Size
2577 switch (mCalibration.toolSizeCalibration) {
2578 case Calibration::TOOL_SIZE_CALIBRATION_NONE:
2579 dump.append(INDENT4 "touch.toolSize.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002580 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002581 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
2582 dump.append(INDENT4 "touch.toolSize.calibration: geometric\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002583 break;
Jeff Brownc6d282b2010-10-14 21:42:15 -07002584 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
2585 dump.append(INDENT4 "touch.toolSize.calibration: linear\n");
2586 break;
2587 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
2588 dump.append(INDENT4 "touch.toolSize.calibration: area\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002589 break;
2590 default:
2591 assert(false);
2592 }
2593
Jeff Brownc6d282b2010-10-14 21:42:15 -07002594 if (mCalibration.haveToolSizeLinearScale) {
2595 dump.appendFormat(INDENT4 "touch.toolSize.linearScale: %0.3f\n",
2596 mCalibration.toolSizeLinearScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002597 }
2598
Jeff Brownc6d282b2010-10-14 21:42:15 -07002599 if (mCalibration.haveToolSizeLinearBias) {
2600 dump.appendFormat(INDENT4 "touch.toolSize.linearBias: %0.3f\n",
2601 mCalibration.toolSizeLinearBias);
Jeff Brown8d608662010-08-30 03:02:23 -07002602 }
2603
Jeff Brownc6d282b2010-10-14 21:42:15 -07002604 if (mCalibration.haveToolSizeAreaScale) {
2605 dump.appendFormat(INDENT4 "touch.toolSize.areaScale: %0.3f\n",
2606 mCalibration.toolSizeAreaScale);
2607 }
2608
2609 if (mCalibration.haveToolSizeAreaBias) {
2610 dump.appendFormat(INDENT4 "touch.toolSize.areaBias: %0.3f\n",
2611 mCalibration.toolSizeAreaBias);
2612 }
2613
2614 if (mCalibration.haveToolSizeIsSummed) {
Jeff Brown1f245102010-11-18 20:53:46 -08002615 dump.appendFormat(INDENT4 "touch.toolSize.isSummed: %s\n",
Jeff Brown47e6b1b2010-11-29 17:37:49 -08002616 toString(mCalibration.toolSizeIsSummed));
Jeff Brown8d608662010-08-30 03:02:23 -07002617 }
2618
2619 // Pressure
2620 switch (mCalibration.pressureCalibration) {
2621 case Calibration::PRESSURE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002622 dump.append(INDENT4 "touch.pressure.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002623 break;
2624 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002625 dump.append(INDENT4 "touch.pressure.calibration: physical\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002626 break;
2627 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002628 dump.append(INDENT4 "touch.pressure.calibration: amplitude\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002629 break;
2630 default:
2631 assert(false);
2632 }
2633
2634 switch (mCalibration.pressureSource) {
2635 case Calibration::PRESSURE_SOURCE_PRESSURE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002636 dump.append(INDENT4 "touch.pressure.source: pressure\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002637 break;
2638 case Calibration::PRESSURE_SOURCE_TOUCH:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002639 dump.append(INDENT4 "touch.pressure.source: touch\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002640 break;
2641 case Calibration::PRESSURE_SOURCE_DEFAULT:
2642 break;
2643 default:
2644 assert(false);
2645 }
2646
2647 if (mCalibration.havePressureScale) {
Jeff Brownef3d7e82010-09-30 14:33:04 -07002648 dump.appendFormat(INDENT4 "touch.pressure.scale: %0.3f\n",
2649 mCalibration.pressureScale);
Jeff Brown8d608662010-08-30 03:02:23 -07002650 }
2651
2652 // Size
2653 switch (mCalibration.sizeCalibration) {
2654 case Calibration::SIZE_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002655 dump.append(INDENT4 "touch.size.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002656 break;
2657 case Calibration::SIZE_CALIBRATION_NORMALIZED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002658 dump.append(INDENT4 "touch.size.calibration: normalized\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002659 break;
2660 default:
2661 assert(false);
2662 }
2663
2664 // Orientation
2665 switch (mCalibration.orientationCalibration) {
2666 case Calibration::ORIENTATION_CALIBRATION_NONE:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002667 dump.append(INDENT4 "touch.orientation.calibration: none\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002668 break;
2669 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
Jeff Brownef3d7e82010-09-30 14:33:04 -07002670 dump.append(INDENT4 "touch.orientation.calibration: interpolated\n");
Jeff Brown8d608662010-08-30 03:02:23 -07002671 break;
Jeff Brown517bb4c2011-01-14 19:09:23 -08002672 case Calibration::ORIENTATION_CALIBRATION_VECTOR:
2673 dump.append(INDENT4 "touch.orientation.calibration: vector\n");
2674 break;
Jeff Brown8d608662010-08-30 03:02:23 -07002675 default:
2676 assert(false);
2677 }
2678}
2679
Jeff Brown6d0fec22010-07-23 21:28:06 -07002680void TouchInputMapper::reset() {
2681 // Synthesize touch up event if touch is currently down.
2682 // This will also take care of finishing virtual key processing if needed.
2683 if (mLastTouch.pointerCount != 0) {
2684 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
2685 mCurrentTouch.clear();
2686 syncTouch(when, true);
2687 }
2688
Jeff Brown6328cdc2010-07-29 18:18:33 -07002689 { // acquire lock
2690 AutoMutex _l(mLock);
2691 initializeLocked();
Jeff Brown86ea1f52011-04-12 22:39:53 -07002692
2693 if (mPointerController != NULL
2694 && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
2695 mPointerController->clearSpots();
2696 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07002697 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002698
Jeff Brown6328cdc2010-07-29 18:18:33 -07002699 InputMapper::reset();
Jeff Brown6d0fec22010-07-23 21:28:06 -07002700}
2701
2702void TouchInputMapper::syncTouch(nsecs_t when, bool havePointerIds) {
Jeff Brown68d60752011-03-17 01:34:19 -07002703#if DEBUG_RAW_EVENTS
2704 if (!havePointerIds) {
2705 LOGD("syncTouch: pointerCount=%d, no pointer ids", mCurrentTouch.pointerCount);
2706 } else {
2707 LOGD("syncTouch: pointerCount=%d, up=0x%08x, down=0x%08x, move=0x%08x, "
2708 "last=0x%08x, current=0x%08x", mCurrentTouch.pointerCount,
2709 mLastTouch.idBits.value & ~mCurrentTouch.idBits.value,
2710 mCurrentTouch.idBits.value & ~mLastTouch.idBits.value,
2711 mLastTouch.idBits.value & mCurrentTouch.idBits.value,
2712 mLastTouch.idBits.value, mCurrentTouch.idBits.value);
2713 }
2714#endif
2715
Jeff Brown6328cdc2010-07-29 18:18:33 -07002716 // Preprocess pointer data.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002717 if (mParameters.useBadTouchFilter) {
2718 if (applyBadTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002719 havePointerIds = false;
2720 }
2721 }
2722
Jeff Brown6d0fec22010-07-23 21:28:06 -07002723 if (mParameters.useJumpyTouchFilter) {
2724 if (applyJumpyTouchFilter()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002725 havePointerIds = false;
2726 }
2727 }
2728
Jeff Brown68d60752011-03-17 01:34:19 -07002729 if (!havePointerIds) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002730 calculatePointerIds();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002731 }
2732
Jeff Brown6d0fec22010-07-23 21:28:06 -07002733 TouchData temp;
2734 TouchData* savedTouch;
2735 if (mParameters.useAveragingTouchFilter) {
2736 temp.copyFrom(mCurrentTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002737 savedTouch = & temp;
2738
Jeff Brown6d0fec22010-07-23 21:28:06 -07002739 applyAveragingTouchFilter();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002740 } else {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002741 savedTouch = & mCurrentTouch;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002742 }
2743
Jeff Brown56194eb2011-03-02 19:23:13 -08002744 uint32_t policyFlags = 0;
Jeff Brown05dc66a2011-03-02 14:41:58 -08002745 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brownefd32662011-03-08 15:13:06 -08002746 if (mParameters.deviceType == Parameters::DEVICE_TYPE_TOUCH_SCREEN) {
2747 // If this is a touch screen, hide the pointer on an initial down.
2748 getContext()->fadePointer();
2749 }
Jeff Brown56194eb2011-03-02 19:23:13 -08002750
2751 // Initial downs on external touch devices should wake the device.
2752 // We don't do this for internal touch screens to prevent them from waking
2753 // up in your pocket.
2754 // TODO: Use the input device configuration to control this behavior more finely.
2755 if (getDevice()->isExternal()) {
2756 policyFlags |= POLICY_FLAG_WAKE_DROPPED;
2757 }
Jeff Brown05dc66a2011-03-02 14:41:58 -08002758 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002759
Jeff Brown325bd072011-04-19 21:20:10 -07002760 TouchResult touchResult;
2761 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount == 0
2762 && mLastTouch.buttonState == mCurrentTouch.buttonState) {
2763 // Drop spurious syncs.
2764 touchResult = DROP_STROKE;
2765 } else {
2766 // Process touches and virtual keys.
2767 touchResult = consumeOffScreenTouches(when, policyFlags);
2768 if (touchResult == DISPATCH_TOUCH) {
2769 suppressSwipeOntoVirtualKeys(when);
2770 if (mPointerController != NULL) {
2771 dispatchPointerGestures(when, policyFlags, false /*isTimeout*/);
2772 }
2773 dispatchTouches(when, policyFlags);
Jeff Brown96ad3972011-03-09 17:39:48 -08002774 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002775 }
2776
Jeff Brown6328cdc2010-07-29 18:18:33 -07002777 // Copy current touch to last touch in preparation for the next cycle.
Jeff Brown96ad3972011-03-09 17:39:48 -08002778 // Keep the button state so we can track edge-triggered button state changes.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002779 if (touchResult == DROP_STROKE) {
2780 mLastTouch.clear();
Jeff Brown96ad3972011-03-09 17:39:48 -08002781 mLastTouch.buttonState = savedTouch->buttonState;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002782 } else {
2783 mLastTouch.copyFrom(*savedTouch);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002784 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002785}
2786
Jeff Brown325bd072011-04-19 21:20:10 -07002787void TouchInputMapper::timeoutExpired(nsecs_t when) {
2788 if (mPointerController != NULL) {
2789 dispatchPointerGestures(when, 0 /*policyFlags*/, true /*isTimeout*/);
2790 }
2791}
2792
Jeff Brown6d0fec22010-07-23 21:28:06 -07002793TouchInputMapper::TouchResult TouchInputMapper::consumeOffScreenTouches(
2794 nsecs_t when, uint32_t policyFlags) {
2795 int32_t keyEventAction, keyEventFlags;
2796 int32_t keyCode, scanCode, downTime;
2797 TouchResult touchResult;
Jeff Brown349703e2010-06-22 01:27:15 -07002798
Jeff Brown6328cdc2010-07-29 18:18:33 -07002799 { // acquire lock
2800 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002801
Jeff Brown6328cdc2010-07-29 18:18:33 -07002802 // Update surface size and orientation, including virtual key positions.
2803 if (! configureSurfaceLocked()) {
2804 return DROP_STROKE;
2805 }
2806
2807 // Check for virtual key press.
2808 if (mLocked.currentVirtualKey.down) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002809 if (mCurrentTouch.pointerCount == 0) {
2810 // Pointer went up while virtual key was down.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002811 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002812#if DEBUG_VIRTUAL_KEYS
2813 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002814 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002815#endif
2816 keyEventAction = AKEY_EVENT_ACTION_UP;
2817 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2818 touchResult = SKIP_TOUCH;
2819 goto DispatchVirtualKey;
2820 }
2821
2822 if (mCurrentTouch.pointerCount == 1) {
2823 int32_t x = mCurrentTouch.pointers[0].x;
2824 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002825 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
2826 if (virtualKey && virtualKey->keyCode == mLocked.currentVirtualKey.keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002827 // Pointer is still within the space of the virtual key.
2828 return SKIP_TOUCH;
2829 }
2830 }
2831
2832 // Pointer left virtual key area or another pointer also went down.
2833 // Send key cancellation and drop the stroke so subsequent motions will be
2834 // considered fresh downs. This is useful when the user swipes away from the
2835 // virtual key area into the main display surface.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002836 mLocked.currentVirtualKey.down = false;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002837#if DEBUG_VIRTUAL_KEYS
2838 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002839 mLocked.currentVirtualKey.keyCode, mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002840#endif
2841 keyEventAction = AKEY_EVENT_ACTION_UP;
2842 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
2843 | AKEY_EVENT_FLAG_CANCELED;
Jeff Brownc3db8582010-10-20 15:33:38 -07002844
2845 // Check whether the pointer moved inside the display area where we should
2846 // start a new stroke.
2847 int32_t x = mCurrentTouch.pointers[0].x;
2848 int32_t y = mCurrentTouch.pointers[0].y;
2849 if (isPointInsideSurfaceLocked(x, y)) {
2850 mLastTouch.clear();
2851 touchResult = DISPATCH_TOUCH;
2852 } else {
2853 touchResult = DROP_STROKE;
2854 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07002855 } else {
2856 if (mCurrentTouch.pointerCount >= 1 && mLastTouch.pointerCount == 0) {
2857 // Pointer just went down. Handle off-screen touches, if needed.
2858 int32_t x = mCurrentTouch.pointers[0].x;
2859 int32_t y = mCurrentTouch.pointers[0].y;
Jeff Brown6328cdc2010-07-29 18:18:33 -07002860 if (! isPointInsideSurfaceLocked(x, y)) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07002861 // If exactly one pointer went down, check for virtual key hit.
2862 // Otherwise we will drop the entire stroke.
2863 if (mCurrentTouch.pointerCount == 1) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07002864 const VirtualKey* virtualKey = findVirtualKeyHitLocked(x, y);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002865 if (virtualKey) {
Jeff Brownfe508922011-01-18 15:10:10 -08002866 if (mContext->shouldDropVirtualKey(when, getDevice(),
2867 virtualKey->keyCode, virtualKey->scanCode)) {
2868 return DROP_STROKE;
2869 }
2870
Jeff Brown6328cdc2010-07-29 18:18:33 -07002871 mLocked.currentVirtualKey.down = true;
2872 mLocked.currentVirtualKey.downTime = when;
2873 mLocked.currentVirtualKey.keyCode = virtualKey->keyCode;
2874 mLocked.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown6d0fec22010-07-23 21:28:06 -07002875#if DEBUG_VIRTUAL_KEYS
2876 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
Jeff Brownc3db8582010-10-20 15:33:38 -07002877 mLocked.currentVirtualKey.keyCode,
2878 mLocked.currentVirtualKey.scanCode);
Jeff Brown6d0fec22010-07-23 21:28:06 -07002879#endif
2880 keyEventAction = AKEY_EVENT_ACTION_DOWN;
2881 keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM
2882 | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY;
2883 touchResult = SKIP_TOUCH;
2884 goto DispatchVirtualKey;
2885 }
2886 }
2887 return DROP_STROKE;
2888 }
2889 }
2890 return DISPATCH_TOUCH;
2891 }
2892
2893 DispatchVirtualKey:
2894 // Collect remaining state needed to dispatch virtual key.
Jeff Brown6328cdc2010-07-29 18:18:33 -07002895 keyCode = mLocked.currentVirtualKey.keyCode;
2896 scanCode = mLocked.currentVirtualKey.scanCode;
2897 downTime = mLocked.currentVirtualKey.downTime;
2898 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07002899
2900 // Dispatch virtual key.
2901 int32_t metaState = mContext->getGlobalMetaState();
Jeff Brown0eaf3932010-10-01 14:55:30 -07002902 policyFlags |= POLICY_FLAG_VIRTUAL;
Jeff Brownb6997262010-10-08 22:31:17 -07002903 getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
2904 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
2905 return touchResult;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002906}
2907
Jeff Brownefd32662011-03-08 15:13:06 -08002908void TouchInputMapper::suppressSwipeOntoVirtualKeys(nsecs_t when) {
Jeff Brownfe508922011-01-18 15:10:10 -08002909 // Disable all virtual key touches that happen within a short time interval of the
2910 // most recent touch. The idea is to filter out stray virtual key presses when
2911 // interacting with the touch screen.
2912 //
2913 // Problems we're trying to solve:
2914 //
2915 // 1. While scrolling a list or dragging the window shade, the user swipes down into a
2916 // virtual key area that is implemented by a separate touch panel and accidentally
2917 // triggers a virtual key.
2918 //
2919 // 2. While typing in the on screen keyboard, the user taps slightly outside the screen
2920 // area and accidentally triggers a virtual key. This often happens when virtual keys
2921 // are layed out below the screen near to where the on screen keyboard's space bar
2922 // is displayed.
2923 if (mParameters.virtualKeyQuietTime > 0 && mCurrentTouch.pointerCount != 0) {
2924 mContext->disableVirtualKeysUntil(when + mParameters.virtualKeyQuietTime);
2925 }
2926}
2927
Jeff Brown6d0fec22010-07-23 21:28:06 -07002928void TouchInputMapper::dispatchTouches(nsecs_t when, uint32_t policyFlags) {
2929 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
2930 uint32_t lastPointerCount = mLastTouch.pointerCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002931 if (currentPointerCount == 0 && lastPointerCount == 0) {
2932 return; // nothing to do!
2933 }
2934
Jeff Brown96ad3972011-03-09 17:39:48 -08002935 // Update current touch coordinates.
2936 int32_t edgeFlags;
2937 float xPrecision, yPrecision;
2938 prepareTouches(&edgeFlags, &xPrecision, &yPrecision);
2939
2940 // Dispatch motions.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002941 BitSet32 currentIdBits = mCurrentTouch.idBits;
2942 BitSet32 lastIdBits = mLastTouch.idBits;
Jeff Brown96ad3972011-03-09 17:39:48 -08002943 uint32_t metaState = getContext()->getGlobalMetaState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002944
2945 if (currentIdBits == lastIdBits) {
2946 // No pointer id changes so this is a move event.
2947 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brown96ad3972011-03-09 17:39:48 -08002948 dispatchMotion(when, policyFlags, mTouchSource,
2949 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
2950 mCurrentTouchCoords, mCurrentTouch.idToIndex, currentIdBits, -1,
2951 xPrecision, yPrecision, mDownTime);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002952 } else {
Jeff Brownc3db8582010-10-20 15:33:38 -07002953 // There may be pointers going up and pointers going down and pointers moving
2954 // all at the same time.
Jeff Brown96ad3972011-03-09 17:39:48 -08002955 BitSet32 upIdBits(lastIdBits.value & ~currentIdBits.value);
2956 BitSet32 downIdBits(currentIdBits.value & ~lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07002957 BitSet32 moveIdBits(lastIdBits.value & currentIdBits.value);
Jeff Brown96ad3972011-03-09 17:39:48 -08002958 BitSet32 dispatchedIdBits(lastIdBits.value);
Jeff Brownc3db8582010-10-20 15:33:38 -07002959
Jeff Brown96ad3972011-03-09 17:39:48 -08002960 // Update last coordinates of pointers that have moved so that we observe the new
2961 // pointer positions at the same time as other pointers that have just gone up.
2962 bool moveNeeded = updateMovedPointerCoords(
2963 mCurrentTouchCoords, mCurrentTouch.idToIndex,
2964 mLastTouchCoords, mLastTouch.idToIndex,
2965 moveIdBits);
Jeff Brownc3db8582010-10-20 15:33:38 -07002966
Jeff Brown96ad3972011-03-09 17:39:48 -08002967 // Dispatch pointer up events.
Jeff Brownc3db8582010-10-20 15:33:38 -07002968 while (!upIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002969 uint32_t upId = upIdBits.firstMarkedBit();
2970 upIdBits.clearBit(upId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002971
Jeff Brown96ad3972011-03-09 17:39:48 -08002972 dispatchMotion(when, policyFlags, mTouchSource,
2973 AMOTION_EVENT_ACTION_POINTER_UP, 0, metaState, 0,
2974 mLastTouchCoords, mLastTouch.idToIndex, dispatchedIdBits, upId,
2975 xPrecision, yPrecision, mDownTime);
2976 dispatchedIdBits.clearBit(upId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002977 }
2978
Jeff Brownc3db8582010-10-20 15:33:38 -07002979 // Dispatch move events if any of the remaining pointers moved from their old locations.
2980 // Although applications receive new locations as part of individual pointer up
2981 // events, they do not generally handle them except when presented in a move event.
2982 if (moveNeeded) {
Jeff Brown96ad3972011-03-09 17:39:48 -08002983 assert(moveIdBits.value == dispatchedIdBits.value);
2984 dispatchMotion(when, policyFlags, mTouchSource,
2985 AMOTION_EVENT_ACTION_MOVE, 0, metaState, 0,
2986 mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, -1,
2987 xPrecision, yPrecision, mDownTime);
Jeff Brownc3db8582010-10-20 15:33:38 -07002988 }
2989
2990 // Dispatch pointer down events using the new pointer locations.
2991 while (!downIdBits.isEmpty()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002992 uint32_t downId = downIdBits.firstMarkedBit();
2993 downIdBits.clearBit(downId);
Jeff Brown96ad3972011-03-09 17:39:48 -08002994 dispatchedIdBits.markBit(downId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002995
Jeff Brown96ad3972011-03-09 17:39:48 -08002996 if (dispatchedIdBits.count() == 1) {
2997 // First pointer is going down. Set down time.
Jeff Brown6d0fec22010-07-23 21:28:06 -07002998 mDownTime = when;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002999 } else {
Jeff Brown96ad3972011-03-09 17:39:48 -08003000 // Only send edge flags with first pointer down.
3001 edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003002 }
3003
Jeff Brown96ad3972011-03-09 17:39:48 -08003004 dispatchMotion(when, policyFlags, mTouchSource,
3005 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
3006 mCurrentTouchCoords, mCurrentTouch.idToIndex, dispatchedIdBits, downId,
3007 xPrecision, yPrecision, mDownTime);
3008 }
3009 }
3010
3011 // Update state for next time.
3012 for (uint32_t i = 0; i < currentPointerCount; i++) {
3013 mLastTouchCoords[i].copyFrom(mCurrentTouchCoords[i]);
3014 }
3015}
3016
3017void TouchInputMapper::prepareTouches(int32_t* outEdgeFlags,
3018 float* outXPrecision, float* outYPrecision) {
3019 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
3020 uint32_t lastPointerCount = mLastTouch.pointerCount;
3021
3022 AutoMutex _l(mLock);
3023
3024 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
3025 // display or surface coordinates (PointerCoords) and adjust for display orientation.
3026 for (uint32_t i = 0; i < currentPointerCount; i++) {
3027 const PointerData& in = mCurrentTouch.pointers[i];
3028
3029 // ToolMajor and ToolMinor
3030 float toolMajor, toolMinor;
3031 switch (mCalibration.toolSizeCalibration) {
3032 case Calibration::TOOL_SIZE_CALIBRATION_GEOMETRIC:
3033 toolMajor = in.toolMajor * mLocked.geometricScale;
3034 if (mRawAxes.toolMinor.valid) {
3035 toolMinor = in.toolMinor * mLocked.geometricScale;
3036 } else {
3037 toolMinor = toolMajor;
3038 }
3039 break;
3040 case Calibration::TOOL_SIZE_CALIBRATION_LINEAR:
3041 toolMajor = in.toolMajor != 0
3042 ? in.toolMajor * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias
3043 : 0;
3044 if (mRawAxes.toolMinor.valid) {
3045 toolMinor = in.toolMinor != 0
3046 ? in.toolMinor * mLocked.toolSizeLinearScale
3047 + mLocked.toolSizeLinearBias
3048 : 0;
3049 } else {
3050 toolMinor = toolMajor;
3051 }
3052 break;
3053 case Calibration::TOOL_SIZE_CALIBRATION_AREA:
3054 if (in.toolMajor != 0) {
3055 float diameter = sqrtf(in.toolMajor
3056 * mLocked.toolSizeAreaScale + mLocked.toolSizeAreaBias);
3057 toolMajor = diameter * mLocked.toolSizeLinearScale + mLocked.toolSizeLinearBias;
3058 } else {
3059 toolMajor = 0;
3060 }
3061 toolMinor = toolMajor;
3062 break;
3063 default:
3064 toolMajor = 0;
3065 toolMinor = 0;
3066 break;
3067 }
3068
3069 if (mCalibration.haveToolSizeIsSummed && mCalibration.toolSizeIsSummed) {
3070 toolMajor /= currentPointerCount;
3071 toolMinor /= currentPointerCount;
3072 }
3073
3074 // Pressure
3075 float rawPressure;
3076 switch (mCalibration.pressureSource) {
3077 case Calibration::PRESSURE_SOURCE_PRESSURE:
3078 rawPressure = in.pressure;
3079 break;
3080 case Calibration::PRESSURE_SOURCE_TOUCH:
3081 rawPressure = in.touchMajor;
3082 break;
3083 default:
3084 rawPressure = 0;
3085 }
3086
3087 float pressure;
3088 switch (mCalibration.pressureCalibration) {
3089 case Calibration::PRESSURE_CALIBRATION_PHYSICAL:
3090 case Calibration::PRESSURE_CALIBRATION_AMPLITUDE:
3091 pressure = rawPressure * mLocked.pressureScale;
3092 break;
3093 default:
3094 pressure = 1;
3095 break;
3096 }
3097
3098 // TouchMajor and TouchMinor
3099 float touchMajor, touchMinor;
3100 switch (mCalibration.touchSizeCalibration) {
3101 case Calibration::TOUCH_SIZE_CALIBRATION_GEOMETRIC:
3102 touchMajor = in.touchMajor * mLocked.geometricScale;
3103 if (mRawAxes.touchMinor.valid) {
3104 touchMinor = in.touchMinor * mLocked.geometricScale;
3105 } else {
3106 touchMinor = touchMajor;
3107 }
3108 break;
3109 case Calibration::TOUCH_SIZE_CALIBRATION_PRESSURE:
3110 touchMajor = toolMajor * pressure;
3111 touchMinor = toolMinor * pressure;
3112 break;
3113 default:
3114 touchMajor = 0;
3115 touchMinor = 0;
3116 break;
3117 }
3118
3119 if (touchMajor > toolMajor) {
3120 touchMajor = toolMajor;
3121 }
3122 if (touchMinor > toolMinor) {
3123 touchMinor = toolMinor;
3124 }
3125
3126 // Size
3127 float size;
3128 switch (mCalibration.sizeCalibration) {
3129 case Calibration::SIZE_CALIBRATION_NORMALIZED: {
3130 float rawSize = mRawAxes.toolMinor.valid
3131 ? avg(in.toolMajor, in.toolMinor)
3132 : in.toolMajor;
3133 size = rawSize * mLocked.sizeScale;
3134 break;
3135 }
3136 default:
3137 size = 0;
3138 break;
3139 }
3140
3141 // Orientation
3142 float orientation;
3143 switch (mCalibration.orientationCalibration) {
3144 case Calibration::ORIENTATION_CALIBRATION_INTERPOLATED:
3145 orientation = in.orientation * mLocked.orientationScale;
3146 break;
3147 case Calibration::ORIENTATION_CALIBRATION_VECTOR: {
3148 int32_t c1 = signExtendNybble((in.orientation & 0xf0) >> 4);
3149 int32_t c2 = signExtendNybble(in.orientation & 0x0f);
3150 if (c1 != 0 || c2 != 0) {
3151 orientation = atan2f(c1, c2) * 0.5f;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003152 float scale = 1.0f + hypotf(c1, c2) / 16.0f;
Jeff Brown96ad3972011-03-09 17:39:48 -08003153 touchMajor *= scale;
3154 touchMinor /= scale;
3155 toolMajor *= scale;
3156 toolMinor /= scale;
3157 } else {
3158 orientation = 0;
3159 }
3160 break;
3161 }
3162 default:
3163 orientation = 0;
3164 }
3165
3166 // X and Y
3167 // Adjust coords for surface orientation.
3168 float x, y;
3169 switch (mLocked.surfaceOrientation) {
3170 case DISPLAY_ORIENTATION_90:
3171 x = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3172 y = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3173 orientation -= M_PI_2;
3174 if (orientation < - M_PI_2) {
3175 orientation += M_PI;
3176 }
3177 break;
3178 case DISPLAY_ORIENTATION_180:
3179 x = float(mRawAxes.x.maxValue - in.x) * mLocked.xScale;
3180 y = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3181 break;
3182 case DISPLAY_ORIENTATION_270:
3183 x = float(mRawAxes.y.maxValue - in.y) * mLocked.yScale;
3184 y = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3185 orientation += M_PI_2;
3186 if (orientation > M_PI_2) {
3187 orientation -= M_PI;
3188 }
3189 break;
3190 default:
3191 x = float(in.x - mRawAxes.x.minValue) * mLocked.xScale;
3192 y = float(in.y - mRawAxes.y.minValue) * mLocked.yScale;
3193 break;
3194 }
3195
3196 // Write output coords.
3197 PointerCoords& out = mCurrentTouchCoords[i];
3198 out.clear();
3199 out.setAxisValue(AMOTION_EVENT_AXIS_X, x);
3200 out.setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3201 out.setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, pressure);
3202 out.setAxisValue(AMOTION_EVENT_AXIS_SIZE, size);
3203 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MAJOR, touchMajor);
3204 out.setAxisValue(AMOTION_EVENT_AXIS_TOUCH_MINOR, touchMinor);
3205 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MAJOR, toolMajor);
3206 out.setAxisValue(AMOTION_EVENT_AXIS_TOOL_MINOR, toolMinor);
3207 out.setAxisValue(AMOTION_EVENT_AXIS_ORIENTATION, orientation);
3208 }
3209
3210 // Check edge flags by looking only at the first pointer since the flags are
3211 // global to the event.
3212 *outEdgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3213 if (lastPointerCount == 0 && currentPointerCount > 0) {
3214 const PointerData& in = mCurrentTouch.pointers[0];
3215
3216 if (in.x <= mRawAxes.x.minValue) {
3217 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_LEFT,
3218 mLocked.surfaceOrientation);
3219 } else if (in.x >= mRawAxes.x.maxValue) {
3220 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_RIGHT,
3221 mLocked.surfaceOrientation);
3222 }
3223 if (in.y <= mRawAxes.y.minValue) {
3224 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_TOP,
3225 mLocked.surfaceOrientation);
3226 } else if (in.y >= mRawAxes.y.maxValue) {
3227 *outEdgeFlags |= rotateEdgeFlag(AMOTION_EVENT_EDGE_FLAG_BOTTOM,
3228 mLocked.surfaceOrientation);
3229 }
3230 }
3231
3232 *outXPrecision = mLocked.orientedXPrecision;
3233 *outYPrecision = mLocked.orientedYPrecision;
3234}
3235
Jeff Brown325bd072011-04-19 21:20:10 -07003236void TouchInputMapper::dispatchPointerGestures(nsecs_t when, uint32_t policyFlags,
3237 bool isTimeout) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003238 // Switch pointer presentation.
3239 mPointerController->setPresentation(
3240 mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3241 ? PointerControllerInterface::PRESENTATION_SPOT
3242 : PointerControllerInterface::PRESENTATION_POINTER);
3243
Jeff Brown96ad3972011-03-09 17:39:48 -08003244 // Update current gesture coordinates.
3245 bool cancelPreviousGesture, finishPreviousGesture;
Jeff Brown325bd072011-04-19 21:20:10 -07003246 bool sendEvents = preparePointerGestures(when,
3247 &cancelPreviousGesture, &finishPreviousGesture, isTimeout);
3248 if (!sendEvents) {
3249 return;
3250 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003251
Jeff Brown86ea1f52011-04-12 22:39:53 -07003252 // Show the pointer if needed.
3253 if (mPointerGesture.currentGestureMode != PointerGesture::NEUTRAL
3254 && mPointerGesture.currentGestureMode != PointerGesture::QUIET) {
3255 mPointerController->unfade();
3256 }
3257
Jeff Brown96ad3972011-03-09 17:39:48 -08003258 // Send events!
3259 uint32_t metaState = getContext()->getGlobalMetaState();
3260
3261 // Update last coordinates of pointers that have moved so that we observe the new
3262 // pointer positions at the same time as other pointers that have just gone up.
Jeff Brown325bd072011-04-19 21:20:10 -07003263 bool down = mPointerGesture.currentGestureMode == PointerGesture::TAP
3264 || mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG
3265 || mPointerGesture.currentGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown86ea1f52011-04-12 22:39:53 -07003266 || mPointerGesture.currentGestureMode == PointerGesture::PRESS
Jeff Brown96ad3972011-03-09 17:39:48 -08003267 || mPointerGesture.currentGestureMode == PointerGesture::SWIPE
3268 || mPointerGesture.currentGestureMode == PointerGesture::FREEFORM;
3269 bool moveNeeded = false;
3270 if (down && !cancelPreviousGesture && !finishPreviousGesture
Jeff Brown86ea1f52011-04-12 22:39:53 -07003271 && !mPointerGesture.lastGestureIdBits.isEmpty()
3272 && !mPointerGesture.currentGestureIdBits.isEmpty()) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003273 BitSet32 movedGestureIdBits(mPointerGesture.currentGestureIdBits.value
3274 & mPointerGesture.lastGestureIdBits.value);
3275 moveNeeded = updateMovedPointerCoords(
3276 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3277 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3278 movedGestureIdBits);
3279 }
3280
3281 // Send motion events for all pointers that went up or were canceled.
3282 BitSet32 dispatchedGestureIdBits(mPointerGesture.lastGestureIdBits);
3283 if (!dispatchedGestureIdBits.isEmpty()) {
3284 if (cancelPreviousGesture) {
3285 dispatchMotion(when, policyFlags, mPointerSource,
3286 AMOTION_EVENT_ACTION_CANCEL, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3287 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3288 dispatchedGestureIdBits, -1,
3289 0, 0, mPointerGesture.downTime);
3290
3291 dispatchedGestureIdBits.clear();
3292 } else {
3293 BitSet32 upGestureIdBits;
3294 if (finishPreviousGesture) {
3295 upGestureIdBits = dispatchedGestureIdBits;
3296 } else {
3297 upGestureIdBits.value = dispatchedGestureIdBits.value
3298 & ~mPointerGesture.currentGestureIdBits.value;
3299 }
3300 while (!upGestureIdBits.isEmpty()) {
3301 uint32_t id = upGestureIdBits.firstMarkedBit();
3302 upGestureIdBits.clearBit(id);
3303
3304 dispatchMotion(when, policyFlags, mPointerSource,
3305 AMOTION_EVENT_ACTION_POINTER_UP, 0,
3306 metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3307 mPointerGesture.lastGestureCoords, mPointerGesture.lastGestureIdToIndex,
3308 dispatchedGestureIdBits, id,
3309 0, 0, mPointerGesture.downTime);
3310
3311 dispatchedGestureIdBits.clearBit(id);
3312 }
3313 }
3314 }
3315
3316 // Send motion events for all pointers that moved.
3317 if (moveNeeded) {
3318 dispatchMotion(when, policyFlags, mPointerSource,
3319 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3320 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3321 dispatchedGestureIdBits, -1,
3322 0, 0, mPointerGesture.downTime);
3323 }
3324
3325 // Send motion events for all pointers that went down.
3326 if (down) {
3327 BitSet32 downGestureIdBits(mPointerGesture.currentGestureIdBits.value
3328 & ~dispatchedGestureIdBits.value);
3329 while (!downGestureIdBits.isEmpty()) {
3330 uint32_t id = downGestureIdBits.firstMarkedBit();
3331 downGestureIdBits.clearBit(id);
3332 dispatchedGestureIdBits.markBit(id);
3333
3334 int32_t edgeFlags = AMOTION_EVENT_EDGE_FLAG_NONE;
3335 if (dispatchedGestureIdBits.count() == 1) {
3336 // First pointer is going down. Calculate edge flags and set down time.
3337 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3338 const PointerCoords& downCoords = mPointerGesture.currentGestureCoords[index];
3339 edgeFlags = calculateEdgeFlagsUsingPointerBounds(mPointerController,
3340 downCoords.getAxisValue(AMOTION_EVENT_AXIS_X),
3341 downCoords.getAxisValue(AMOTION_EVENT_AXIS_Y));
3342 mPointerGesture.downTime = when;
3343 }
3344
3345 dispatchMotion(when, policyFlags, mPointerSource,
3346 AMOTION_EVENT_ACTION_POINTER_DOWN, 0, metaState, edgeFlags,
3347 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3348 dispatchedGestureIdBits, id,
3349 0, 0, mPointerGesture.downTime);
3350 }
3351 }
3352
Jeff Brown96ad3972011-03-09 17:39:48 -08003353 // Send motion events for hover.
3354 if (mPointerGesture.currentGestureMode == PointerGesture::HOVER) {
3355 dispatchMotion(when, policyFlags, mPointerSource,
3356 AMOTION_EVENT_ACTION_HOVER_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
3357 mPointerGesture.currentGestureCoords, mPointerGesture.currentGestureIdToIndex,
3358 mPointerGesture.currentGestureIdBits, -1,
3359 0, 0, mPointerGesture.downTime);
3360 }
3361
3362 // Update state.
3363 mPointerGesture.lastGestureMode = mPointerGesture.currentGestureMode;
3364 if (!down) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003365 mPointerGesture.lastGestureIdBits.clear();
3366 } else {
Jeff Brown96ad3972011-03-09 17:39:48 -08003367 mPointerGesture.lastGestureIdBits = mPointerGesture.currentGestureIdBits;
3368 for (BitSet32 idBits(mPointerGesture.currentGestureIdBits); !idBits.isEmpty(); ) {
3369 uint32_t id = idBits.firstMarkedBit();
3370 idBits.clearBit(id);
3371 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
3372 mPointerGesture.lastGestureCoords[index].copyFrom(
3373 mPointerGesture.currentGestureCoords[index]);
3374 mPointerGesture.lastGestureIdToIndex[id] = index;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003375 }
3376 }
3377}
3378
Jeff Brown325bd072011-04-19 21:20:10 -07003379bool TouchInputMapper::preparePointerGestures(nsecs_t when,
3380 bool* outCancelPreviousGesture, bool* outFinishPreviousGesture, bool isTimeout) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003381 *outCancelPreviousGesture = false;
3382 *outFinishPreviousGesture = false;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003383
Jeff Brown96ad3972011-03-09 17:39:48 -08003384 AutoMutex _l(mLock);
Jeff Brown6328cdc2010-07-29 18:18:33 -07003385
Jeff Brown325bd072011-04-19 21:20:10 -07003386 // Handle TAP timeout.
3387 if (isTimeout) {
3388#if DEBUG_GESTURES
3389 LOGD("Gestures: Processing timeout");
3390#endif
3391
3392 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
3393 if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
3394 // The tap/drag timeout has not yet expired.
3395 getContext()->requestTimeoutAtTime(mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL);
3396 } else {
3397 // The tap is finished.
3398#if DEBUG_GESTURES
3399 LOGD("Gestures: TAP finished");
3400#endif
3401 *outFinishPreviousGesture = true;
3402
3403 mPointerGesture.activeGestureId = -1;
3404 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
3405 mPointerGesture.currentGestureIdBits.clear();
3406
3407 mPointerController->setButtonState(0);
3408
3409 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3410 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
3411 mPointerGesture.spotIdBits.clear();
3412 moveSpotsLocked();
3413 }
3414 return true;
3415 }
3416 }
3417
3418 // We did not handle this timeout.
3419 return false;
3420 }
3421
Jeff Brown96ad3972011-03-09 17:39:48 -08003422 // Update the velocity tracker.
3423 {
3424 VelocityTracker::Position positions[MAX_POINTERS];
3425 uint32_t count = 0;
3426 for (BitSet32 idBits(mCurrentTouch.idBits); !idBits.isEmpty(); count++) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07003427 uint32_t id = idBits.firstMarkedBit();
3428 idBits.clearBit(id);
Jeff Brown96ad3972011-03-09 17:39:48 -08003429 uint32_t index = mCurrentTouch.idToIndex[id];
3430 positions[count].x = mCurrentTouch.pointers[index].x
3431 * mLocked.pointerGestureXMovementScale;
3432 positions[count].y = mCurrentTouch.pointers[index].y
3433 * mLocked.pointerGestureYMovementScale;
3434 }
3435 mPointerGesture.velocityTracker.addMovement(when, mCurrentTouch.idBits, positions);
3436 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003437
Jeff Brown96ad3972011-03-09 17:39:48 -08003438 // Pick a new active touch id if needed.
3439 // Choose an arbitrary pointer that just went down, if there is one.
3440 // Otherwise choose an arbitrary remaining pointer.
3441 // This guarantees we always have an active touch id when there is at least one pointer.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003442 // We keep the same active touch id for as long as possible.
3443 bool activeTouchChanged = false;
3444 int32_t lastActiveTouchId = mPointerGesture.activeTouchId;
3445 int32_t activeTouchId = lastActiveTouchId;
3446 if (activeTouchId < 0) {
3447 if (!mCurrentTouch.idBits.isEmpty()) {
3448 activeTouchChanged = true;
3449 activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3450 mPointerGesture.firstTouchTime = when;
Jeff Brown96ad3972011-03-09 17:39:48 -08003451 }
Jeff Brown86ea1f52011-04-12 22:39:53 -07003452 } else if (!mCurrentTouch.idBits.hasBit(activeTouchId)) {
3453 activeTouchChanged = true;
3454 if (!mCurrentTouch.idBits.isEmpty()) {
3455 activeTouchId = mPointerGesture.activeTouchId = mCurrentTouch.idBits.firstMarkedBit();
3456 } else {
3457 activeTouchId = mPointerGesture.activeTouchId = -1;
Jeff Brown96ad3972011-03-09 17:39:48 -08003458 }
3459 }
3460
3461 // Determine whether we are in quiet time.
Jeff Brown86ea1f52011-04-12 22:39:53 -07003462 bool isQuietTime = false;
3463 if (activeTouchId < 0) {
3464 mPointerGesture.resetQuietTime();
3465 } else {
3466 isQuietTime = when < mPointerGesture.quietTime + QUIET_INTERVAL;
3467 if (!isQuietTime) {
3468 if ((mPointerGesture.lastGestureMode == PointerGesture::PRESS
3469 || mPointerGesture.lastGestureMode == PointerGesture::SWIPE
3470 || mPointerGesture.lastGestureMode == PointerGesture::FREEFORM)
3471 && mCurrentTouch.pointerCount < 2) {
3472 // Enter quiet time when exiting swipe or freeform state.
3473 // This is to prevent accidentally entering the hover state and flinging the
3474 // pointer when finishing a swipe and there is still one pointer left onscreen.
3475 isQuietTime = true;
Jeff Brown325bd072011-04-19 21:20:10 -07003476 } else if (mPointerGesture.lastGestureMode == PointerGesture::BUTTON_CLICK_OR_DRAG
Jeff Brown86ea1f52011-04-12 22:39:53 -07003477 && mCurrentTouch.pointerCount >= 2
3478 && !isPointerDown(mCurrentTouch.buttonState)) {
3479 // Enter quiet time when releasing the button and there are still two or more
3480 // fingers down. This may indicate that one finger was used to press the button
3481 // but it has not gone up yet.
3482 isQuietTime = true;
3483 }
3484 if (isQuietTime) {
3485 mPointerGesture.quietTime = when;
3486 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003487 }
3488 }
3489
3490 // Switch states based on button and pointer state.
3491 if (isQuietTime) {
3492 // Case 1: Quiet time. (QUIET)
3493#if DEBUG_GESTURES
3494 LOGD("Gestures: QUIET for next %0.3fms",
3495 (mPointerGesture.quietTime + QUIET_INTERVAL - when) * 0.000001f);
3496#endif
3497 *outFinishPreviousGesture = true;
3498
3499 mPointerGesture.activeGestureId = -1;
3500 mPointerGesture.currentGestureMode = PointerGesture::QUIET;
Jeff Brown96ad3972011-03-09 17:39:48 -08003501 mPointerGesture.currentGestureIdBits.clear();
Jeff Brown86ea1f52011-04-12 22:39:53 -07003502
3503 mPointerController->setButtonState(0);
3504
3505 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3506 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
3507 mPointerGesture.spotIdBits.clear();
3508 moveSpotsLocked();
3509 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003510 } else if (isPointerDown(mCurrentTouch.buttonState)) {
Jeff Brown325bd072011-04-19 21:20:10 -07003511 // Case 2: Button is pressed. (BUTTON_CLICK_OR_DRAG)
Jeff Brown96ad3972011-03-09 17:39:48 -08003512 // The pointer follows the active touch point.
3513 // Emit DOWN, MOVE, UP events at the pointer location.
3514 //
3515 // Only the active touch matters; other fingers are ignored. This policy helps
3516 // to handle the case where the user places a second finger on the touch pad
3517 // to apply the necessary force to depress an integrated button below the surface.
3518 // We don't want the second finger to be delivered to applications.
3519 //
3520 // For this to work well, we need to make sure to track the pointer that is really
3521 // active. If the user first puts one finger down to click then adds another
3522 // finger to drag then the active pointer should switch to the finger that is
3523 // being dragged.
3524#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003525 LOGD("Gestures: BUTTON_CLICK_OR_DRAG activeTouchId=%d, "
Jeff Brown96ad3972011-03-09 17:39:48 -08003526 "currentTouchPointerCount=%d", activeTouchId, mCurrentTouch.pointerCount);
3527#endif
3528 // Reset state when just starting.
Jeff Brown325bd072011-04-19 21:20:10 -07003529 if (mPointerGesture.lastGestureMode != PointerGesture::BUTTON_CLICK_OR_DRAG) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003530 *outFinishPreviousGesture = true;
3531 mPointerGesture.activeGestureId = 0;
3532 }
3533
3534 // Switch pointers if needed.
3535 // Find the fastest pointer and follow it.
3536 if (activeTouchId >= 0) {
3537 if (mCurrentTouch.pointerCount > 1) {
3538 int32_t bestId = -1;
3539 float bestSpeed = DRAG_MIN_SWITCH_SPEED;
3540 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
3541 uint32_t id = mCurrentTouch.pointers[i].id;
3542 float vx, vy;
3543 if (mPointerGesture.velocityTracker.getVelocity(id, &vx, &vy)) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003544 float speed = hypotf(vx, vy);
Jeff Brown96ad3972011-03-09 17:39:48 -08003545 if (speed > bestSpeed) {
3546 bestId = id;
3547 bestSpeed = speed;
3548 }
3549 }
Jeff Brown8d608662010-08-30 03:02:23 -07003550 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003551 if (bestId >= 0 && bestId != activeTouchId) {
3552 mPointerGesture.activeTouchId = activeTouchId = bestId;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003553 activeTouchChanged = true;
Jeff Brown96ad3972011-03-09 17:39:48 -08003554#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003555 LOGD("Gestures: BUTTON_CLICK_OR_DRAG switched pointers, "
Jeff Brown96ad3972011-03-09 17:39:48 -08003556 "bestId=%d, bestSpeed=%0.3f", bestId, bestSpeed);
3557#endif
Jeff Brown8d608662010-08-30 03:02:23 -07003558 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003559 }
3560
Jeff Brown96ad3972011-03-09 17:39:48 -08003561 if (mLastTouch.idBits.hasBit(activeTouchId)) {
3562 const PointerData& currentPointer =
3563 mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3564 const PointerData& lastPointer =
3565 mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3566 float deltaX = (currentPointer.x - lastPointer.x)
3567 * mLocked.pointerGestureXMovementScale;
3568 float deltaY = (currentPointer.y - lastPointer.y)
3569 * mLocked.pointerGestureYMovementScale;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003570
3571 // Move the pointer using a relative motion.
3572 // When using spots, the click will occur at the position of the anchor
3573 // spot and all other spots will move there.
Jeff Brown96ad3972011-03-09 17:39:48 -08003574 mPointerController->move(deltaX, deltaY);
Jeff Brown6328cdc2010-07-29 18:18:33 -07003575 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003576 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003577
Jeff Brown96ad3972011-03-09 17:39:48 -08003578 float x, y;
3579 mPointerController->getPosition(&x, &y);
Jeff Brown91c69ab2011-02-14 17:03:18 -08003580
Jeff Brown325bd072011-04-19 21:20:10 -07003581 mPointerGesture.currentGestureMode = PointerGesture::BUTTON_CLICK_OR_DRAG;
Jeff Brown96ad3972011-03-09 17:39:48 -08003582 mPointerGesture.currentGestureIdBits.clear();
3583 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3584 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3585 mPointerGesture.currentGestureCoords[0].clear();
3586 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3587 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
3588 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003589
3590 mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
3591
3592 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3593 if (activeTouchId >= 0) {
3594 // Collapse all spots into one point at the pointer location.
3595 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_BUTTON_DRAG;
3596 mPointerGesture.spotIdBits.clear();
3597 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
3598 uint32_t id = mCurrentTouch.pointers[i].id;
3599 mPointerGesture.spotIdBits.markBit(id);
3600 mPointerGesture.spotIdToIndex[id] = i;
3601 mPointerGesture.spotCoords[i] = mPointerGesture.currentGestureCoords[0];
3602 }
3603 } else {
3604 // No fingers. Generate a spot at the pointer location so the
3605 // anchor appears to be pressed.
3606 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_BUTTON_CLICK;
3607 mPointerGesture.spotIdBits.clear();
3608 mPointerGesture.spotIdBits.markBit(0);
3609 mPointerGesture.spotIdToIndex[0] = 0;
3610 mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
3611 }
3612 moveSpotsLocked();
3613 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003614 } else if (mCurrentTouch.pointerCount == 0) {
3615 // Case 3. No fingers down and button is not pressed. (NEUTRAL)
3616 *outFinishPreviousGesture = true;
3617
Jeff Brown325bd072011-04-19 21:20:10 -07003618 // Watch for taps coming out of HOVER or TAP_DRAG mode.
Jeff Brown96ad3972011-03-09 17:39:48 -08003619 bool tapped = false;
Jeff Brown325bd072011-04-19 21:20:10 -07003620 if ((mPointerGesture.lastGestureMode == PointerGesture::HOVER
3621 || mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG)
Jeff Brown86ea1f52011-04-12 22:39:53 -07003622 && mLastTouch.pointerCount == 1) {
Jeff Brown325bd072011-04-19 21:20:10 -07003623 if (when <= mPointerGesture.tapDownTime + TAP_INTERVAL) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003624 float x, y;
3625 mPointerController->getPosition(&x, &y);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003626 if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
3627 && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003628#if DEBUG_GESTURES
3629 LOGD("Gestures: TAP");
3630#endif
Jeff Brown325bd072011-04-19 21:20:10 -07003631
3632 mPointerGesture.tapUpTime = when;
3633 getContext()->requestTimeoutAtTime(when + TAP_DRAG_INTERVAL);
3634
Jeff Brown96ad3972011-03-09 17:39:48 -08003635 mPointerGesture.activeGestureId = 0;
3636 mPointerGesture.currentGestureMode = PointerGesture::TAP;
Jeff Brown96ad3972011-03-09 17:39:48 -08003637 mPointerGesture.currentGestureIdBits.clear();
3638 mPointerGesture.currentGestureIdBits.markBit(
3639 mPointerGesture.activeGestureId);
3640 mPointerGesture.currentGestureIdToIndex[
3641 mPointerGesture.activeGestureId] = 0;
3642 mPointerGesture.currentGestureCoords[0].clear();
3643 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown86ea1f52011-04-12 22:39:53 -07003644 AMOTION_EVENT_AXIS_X, mPointerGesture.tapX);
Jeff Brown96ad3972011-03-09 17:39:48 -08003645 mPointerGesture.currentGestureCoords[0].setAxisValue(
Jeff Brown86ea1f52011-04-12 22:39:53 -07003646 AMOTION_EVENT_AXIS_Y, mPointerGesture.tapY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003647 mPointerGesture.currentGestureCoords[0].setAxisValue(
3648 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003649
3650 mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003651
3652 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3653 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_TAP;
3654 mPointerGesture.spotIdBits.clear();
3655 mPointerGesture.spotIdBits.markBit(lastActiveTouchId);
3656 mPointerGesture.spotIdToIndex[lastActiveTouchId] = 0;
3657 mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
3658 moveSpotsLocked();
3659 }
3660
Jeff Brown96ad3972011-03-09 17:39:48 -08003661 tapped = true;
3662 } else {
3663#if DEBUG_GESTURES
3664 LOGD("Gestures: Not a TAP, deltaX=%f, deltaY=%f",
Jeff Brown86ea1f52011-04-12 22:39:53 -07003665 x - mPointerGesture.tapX,
3666 y - mPointerGesture.tapY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003667#endif
3668 }
3669 } else {
3670#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003671 LOGD("Gestures: Not a TAP, %0.3fms since down",
3672 (when - mPointerGesture.tapDownTime) * 0.000001f);
Jeff Brown96ad3972011-03-09 17:39:48 -08003673#endif
Jeff Brown6328cdc2010-07-29 18:18:33 -07003674 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003675 }
Jeff Brown86ea1f52011-04-12 22:39:53 -07003676
Jeff Brown96ad3972011-03-09 17:39:48 -08003677 if (!tapped) {
3678#if DEBUG_GESTURES
3679 LOGD("Gestures: NEUTRAL");
3680#endif
3681 mPointerGesture.activeGestureId = -1;
3682 mPointerGesture.currentGestureMode = PointerGesture::NEUTRAL;
Jeff Brown96ad3972011-03-09 17:39:48 -08003683 mPointerGesture.currentGestureIdBits.clear();
Jeff Brown86ea1f52011-04-12 22:39:53 -07003684
3685 mPointerController->setButtonState(0);
3686
3687 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3688 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_NEUTRAL;
3689 mPointerGesture.spotIdBits.clear();
3690 moveSpotsLocked();
3691 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003692 }
3693 } else if (mCurrentTouch.pointerCount == 1) {
Jeff Brown325bd072011-04-19 21:20:10 -07003694 // Case 4. Exactly one finger down, button is not pressed. (HOVER or TAP_DRAG)
Jeff Brown96ad3972011-03-09 17:39:48 -08003695 // The pointer follows the active touch point.
Jeff Brown325bd072011-04-19 21:20:10 -07003696 // When in HOVER, emit HOVER_MOVE events at the pointer location.
3697 // When in TAP_DRAG, emit MOVE events at the pointer location.
3698 LOG_ASSERT(activeTouchId >= 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08003699
Jeff Brown325bd072011-04-19 21:20:10 -07003700 mPointerGesture.currentGestureMode = PointerGesture::HOVER;
3701 if (mPointerGesture.lastGestureMode == PointerGesture::TAP) {
3702 if (when <= mPointerGesture.tapUpTime + TAP_DRAG_INTERVAL) {
3703 float x, y;
3704 mPointerController->getPosition(&x, &y);
3705 if (fabs(x - mPointerGesture.tapX) <= TAP_SLOP
3706 && fabs(y - mPointerGesture.tapY) <= TAP_SLOP) {
3707 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
3708 } else {
Jeff Brown96ad3972011-03-09 17:39:48 -08003709#if DEBUG_GESTURES
Jeff Brown325bd072011-04-19 21:20:10 -07003710 LOGD("Gestures: Not a TAP_DRAG, deltaX=%f, deltaY=%f",
3711 x - mPointerGesture.tapX,
3712 y - mPointerGesture.tapY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003713#endif
Jeff Brown325bd072011-04-19 21:20:10 -07003714 }
3715 } else {
3716#if DEBUG_GESTURES
3717 LOGD("Gestures: Not a TAP_DRAG, %0.3fms time since up",
3718 (when - mPointerGesture.tapUpTime) * 0.000001f);
3719#endif
3720 }
3721 } else if (mPointerGesture.lastGestureMode == PointerGesture::TAP_DRAG) {
3722 mPointerGesture.currentGestureMode = PointerGesture::TAP_DRAG;
3723 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003724
3725 if (mLastTouch.idBits.hasBit(activeTouchId)) {
3726 const PointerData& currentPointer =
3727 mCurrentTouch.pointers[mCurrentTouch.idToIndex[activeTouchId]];
3728 const PointerData& lastPointer =
3729 mLastTouch.pointers[mLastTouch.idToIndex[activeTouchId]];
3730 float deltaX = (currentPointer.x - lastPointer.x)
3731 * mLocked.pointerGestureXMovementScale;
3732 float deltaY = (currentPointer.y - lastPointer.y)
3733 * mLocked.pointerGestureYMovementScale;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003734
3735 // Move the pointer using a relative motion.
Jeff Brown325bd072011-04-19 21:20:10 -07003736 // When using spots, the hover or drag will occur at the position of the anchor spot.
Jeff Brown96ad3972011-03-09 17:39:48 -08003737 mPointerController->move(deltaX, deltaY);
3738 }
3739
Jeff Brown325bd072011-04-19 21:20:10 -07003740 bool down;
3741 if (mPointerGesture.currentGestureMode == PointerGesture::TAP_DRAG) {
3742#if DEBUG_GESTURES
3743 LOGD("Gestures: TAP_DRAG");
3744#endif
3745 down = true;
3746 } else {
3747#if DEBUG_GESTURES
3748 LOGD("Gestures: HOVER");
3749#endif
3750 *outFinishPreviousGesture = true;
3751 mPointerGesture.activeGestureId = 0;
3752 down = false;
3753 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003754
3755 float x, y;
3756 mPointerController->getPosition(&x, &y);
3757
Jeff Brown96ad3972011-03-09 17:39:48 -08003758 mPointerGesture.currentGestureIdBits.clear();
3759 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3760 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3761 mPointerGesture.currentGestureCoords[0].clear();
3762 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X, x);
3763 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
Jeff Brown325bd072011-04-19 21:20:10 -07003764 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE,
3765 down ? 1.0f : 0.0f);
3766
3767 mPointerController->setButtonState(down ? BUTTON_STATE_PRIMARY : 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08003768
3769 if (mLastTouch.pointerCount == 0 && mCurrentTouch.pointerCount != 0) {
Jeff Brown325bd072011-04-19 21:20:10 -07003770 mPointerGesture.resetTap();
3771 mPointerGesture.tapDownTime = when;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003772 mPointerGesture.tapX = x;
3773 mPointerGesture.tapY = y;
3774 }
3775
Jeff Brown86ea1f52011-04-12 22:39:53 -07003776 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
Jeff Brown325bd072011-04-19 21:20:10 -07003777 mPointerGesture.spotGesture = down ? PointerControllerInterface::SPOT_GESTURE_DRAG
3778 : PointerControllerInterface::SPOT_GESTURE_HOVER;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003779 mPointerGesture.spotIdBits.clear();
3780 mPointerGesture.spotIdBits.markBit(activeTouchId);
3781 mPointerGesture.spotIdToIndex[activeTouchId] = 0;
3782 mPointerGesture.spotCoords[0] = mPointerGesture.currentGestureCoords[0];
3783 moveSpotsLocked();
Jeff Brown96ad3972011-03-09 17:39:48 -08003784 }
3785 } else {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003786 // Case 5. At least two fingers down, button is not pressed. (PRESS, SWIPE or FREEFORM)
3787 // We need to provide feedback for each finger that goes down so we cannot wait
3788 // for the fingers to move before deciding what to do.
Jeff Brown96ad3972011-03-09 17:39:48 -08003789 //
Jeff Brown86ea1f52011-04-12 22:39:53 -07003790 // The ambiguous case is deciding what to do when there are two fingers down but they
3791 // have not moved enough to determine whether they are part of a drag or part of a
3792 // freeform gesture, or just a press or long-press at the pointer location.
3793 //
3794 // When there are two fingers we start with the PRESS hypothesis and we generate a
3795 // down at the pointer location.
3796 //
3797 // When the two fingers move enough or when additional fingers are added, we make
3798 // a decision to transition into SWIPE or FREEFORM mode accordingly.
3799 LOG_ASSERT(activeTouchId >= 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08003800
Jeff Brown86ea1f52011-04-12 22:39:53 -07003801 bool needReference = false;
3802 bool settled = when >= mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL;
3803 if (mPointerGesture.lastGestureMode != PointerGesture::PRESS
Jeff Brown96ad3972011-03-09 17:39:48 -08003804 && mPointerGesture.lastGestureMode != PointerGesture::SWIPE
3805 && mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
Jeff Brown96ad3972011-03-09 17:39:48 -08003806 *outFinishPreviousGesture = true;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003807 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
3808 mPointerGesture.activeGestureId = 0;
Jeff Brown96ad3972011-03-09 17:39:48 -08003809
Jeff Brown86ea1f52011-04-12 22:39:53 -07003810 if (settled && mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS
3811 && mLastTouch.idBits.hasBit(mPointerGesture.activeTouchId)) {
3812 // The spot is already visible and has settled, use it as the reference point
3813 // for the gesture. Other spots will be positioned relative to this one.
3814#if DEBUG_GESTURES
3815 LOGD("Gestures: Using active spot as reference for MULTITOUCH, "
3816 "settle time expired %0.3fms ago",
3817 (when - mPointerGesture.firstTouchTime - MULTITOUCH_SETTLE_INTERVAL)
3818 * 0.000001f);
3819#endif
3820 const PointerData& d = mLastTouch.pointers[mLastTouch.idToIndex[
3821 mPointerGesture.activeTouchId]];
3822 mPointerGesture.referenceTouchX = d.x;
3823 mPointerGesture.referenceTouchY = d.y;
3824 const PointerCoords& c = mPointerGesture.spotCoords[mPointerGesture.spotIdToIndex[
3825 mPointerGesture.activeTouchId]];
3826 mPointerGesture.referenceGestureX = c.getAxisValue(AMOTION_EVENT_AXIS_X);
3827 mPointerGesture.referenceGestureY = c.getAxisValue(AMOTION_EVENT_AXIS_Y);
3828 } else {
3829#if DEBUG_GESTURES
3830 LOGD("Gestures: Using centroid as reference for MULTITOUCH, "
3831 "settle time remaining %0.3fms",
3832 (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
3833 * 0.000001f);
3834#endif
3835 needReference = true;
Jeff Brown96ad3972011-03-09 17:39:48 -08003836 }
Jeff Brown86ea1f52011-04-12 22:39:53 -07003837 } else if (!settled && mCurrentTouch.pointerCount > mLastTouch.pointerCount) {
3838 // Additional pointers have gone down but not yet settled.
3839 // Reset the gesture.
3840#if DEBUG_GESTURES
3841 LOGD("Gestures: Resetting gesture since additional pointers went down for MULTITOUCH, "
3842 "settle time remaining %0.3fms",
3843 (mPointerGesture.firstTouchTime + MULTITOUCH_SETTLE_INTERVAL - when)
3844 * 0.000001f);
3845#endif
3846 *outCancelPreviousGesture = true;
3847 mPointerGesture.currentGestureMode = PointerGesture::PRESS;
3848 mPointerGesture.activeGestureId = 0;
Jeff Brown96ad3972011-03-09 17:39:48 -08003849 } else {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003850 // Continue previous gesture.
Jeff Brown96ad3972011-03-09 17:39:48 -08003851 mPointerGesture.currentGestureMode = mPointerGesture.lastGestureMode;
3852 }
3853
Jeff Brown86ea1f52011-04-12 22:39:53 -07003854 if (needReference) {
3855 // Use the centroid and pointer location as the reference points for the gesture.
3856 mCurrentTouch.getCentroid(&mPointerGesture.referenceTouchX,
3857 &mPointerGesture.referenceTouchY);
3858 mPointerController->getPosition(&mPointerGesture.referenceGestureX,
3859 &mPointerGesture.referenceGestureY);
3860 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003861
Jeff Brown86ea1f52011-04-12 22:39:53 -07003862 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
3863 float d;
3864 if (mCurrentTouch.pointerCount > 2) {
3865 // There are more than two pointers, switch to FREEFORM.
3866#if DEBUG_GESTURES
3867 LOGD("Gestures: PRESS transitioned to FREEFORM, number of pointers %d > 2",
3868 mCurrentTouch.pointerCount);
3869#endif
3870 *outCancelPreviousGesture = true;
Jeff Brown96ad3972011-03-09 17:39:48 -08003871 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003872 } else if (((d = distance(
3873 mCurrentTouch.pointers[0].x, mCurrentTouch.pointers[0].y,
3874 mCurrentTouch.pointers[1].x, mCurrentTouch.pointers[1].y))
3875 > mLocked.pointerGestureMaxSwipeWidth)) {
3876 // There are two pointers but they are too far apart, switch to FREEFORM.
3877#if DEBUG_GESTURES
3878 LOGD("Gestures: PRESS transitioned to FREEFORM, distance %0.3f > %0.3f",
3879 d, mLocked.pointerGestureMaxSwipeWidth);
3880#endif
3881 *outCancelPreviousGesture = true;
3882 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
3883 } else {
3884 // There are two pointers. Wait for both pointers to start moving
3885 // before deciding whether this is a SWIPE or FREEFORM gesture.
3886 uint32_t id1 = mCurrentTouch.pointers[0].id;
3887 uint32_t id2 = mCurrentTouch.pointers[1].id;
Jeff Brown96ad3972011-03-09 17:39:48 -08003888
Jeff Brown86ea1f52011-04-12 22:39:53 -07003889 float vx1, vy1, vx2, vy2;
3890 mPointerGesture.velocityTracker.getVelocity(id1, &vx1, &vy1);
3891 mPointerGesture.velocityTracker.getVelocity(id2, &vx2, &vy2);
Jeff Brown96ad3972011-03-09 17:39:48 -08003892
Jeff Brown86ea1f52011-04-12 22:39:53 -07003893 float speed1 = hypotf(vx1, vy1);
3894 float speed2 = hypotf(vx2, vy2);
3895 if (speed1 >= MULTITOUCH_MIN_SPEED && speed2 >= MULTITOUCH_MIN_SPEED) {
3896 // Calculate the dot product of the velocity vectors.
Jeff Brown96ad3972011-03-09 17:39:48 -08003897 // When the vectors are oriented in approximately the same direction,
3898 // the angle betweeen them is near zero and the cosine of the angle
3899 // approches 1.0. Recall that dot(v1, v2) = cos(angle) * mag(v1) * mag(v2).
Jeff Brown86ea1f52011-04-12 22:39:53 -07003900 float dot = vx1 * vx2 + vy1 * vy2;
3901 float cosine = dot / (speed1 * speed2); // denominator always > 0
3902 if (cosine >= SWIPE_TRANSITION_ANGLE_COSINE) {
3903 // Pointers are moving in the same direction. Switch to SWIPE.
3904#if DEBUG_GESTURES
3905 LOGD("Gestures: PRESS transitioned to SWIPE, "
3906 "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
3907 "cosine %0.3f >= %0.3f",
3908 speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
3909 cosine, SWIPE_TRANSITION_ANGLE_COSINE);
3910#endif
Jeff Brown96ad3972011-03-09 17:39:48 -08003911 mPointerGesture.currentGestureMode = PointerGesture::SWIPE;
Jeff Brown86ea1f52011-04-12 22:39:53 -07003912 } else {
3913 // Pointers are moving in different directions. Switch to FREEFORM.
3914#if DEBUG_GESTURES
3915 LOGD("Gestures: PRESS transitioned to FREEFORM, "
3916 "speed1 %0.3f >= %0.3f, speed2 %0.3f >= %0.3f, "
3917 "cosine %0.3f < %0.3f",
3918 speed1, MULTITOUCH_MIN_SPEED, speed2, MULTITOUCH_MIN_SPEED,
3919 cosine, SWIPE_TRANSITION_ANGLE_COSINE);
3920#endif
3921 *outCancelPreviousGesture = true;
3922 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
Jeff Brown96ad3972011-03-09 17:39:48 -08003923 }
3924 }
Jeff Brown96ad3972011-03-09 17:39:48 -08003925 }
3926 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
Jeff Brown86ea1f52011-04-12 22:39:53 -07003927 // Switch from SWIPE to FREEFORM if additional pointers go down.
3928 // Cancel previous gesture.
3929 if (mCurrentTouch.pointerCount > 2) {
3930#if DEBUG_GESTURES
3931 LOGD("Gestures: SWIPE transitioned to FREEFORM, number of pointers %d > 2",
3932 mCurrentTouch.pointerCount);
3933#endif
Jeff Brown96ad3972011-03-09 17:39:48 -08003934 *outCancelPreviousGesture = true;
3935 mPointerGesture.currentGestureMode = PointerGesture::FREEFORM;
Jeff Brown6328cdc2010-07-29 18:18:33 -07003936 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07003937 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07003938
Jeff Brown86ea1f52011-04-12 22:39:53 -07003939 // Move the reference points based on the overall group motion of the fingers.
3940 // The objective is to calculate a vector delta that is common to the movement
3941 // of all fingers.
3942 BitSet32 commonIdBits(mLastTouch.idBits.value & mCurrentTouch.idBits.value);
3943 if (!commonIdBits.isEmpty()) {
3944 float commonDeltaX = 0, commonDeltaY = 0;
3945 for (BitSet32 idBits(commonIdBits); !idBits.isEmpty(); ) {
3946 bool first = (idBits == commonIdBits);
3947 uint32_t id = idBits.firstMarkedBit();
3948 idBits.clearBit(id);
3949
3950 const PointerData& cpd = mCurrentTouch.pointers[mCurrentTouch.idToIndex[id]];
3951 const PointerData& lpd = mLastTouch.pointers[mLastTouch.idToIndex[id]];
3952 float deltaX = cpd.x - lpd.x;
3953 float deltaY = cpd.y - lpd.y;
3954
3955 if (first) {
3956 commonDeltaX = deltaX;
3957 commonDeltaY = deltaY;
3958 } else {
3959 commonDeltaX = calculateCommonVector(commonDeltaX, deltaX);
3960 commonDeltaY = calculateCommonVector(commonDeltaY, deltaY);
3961 }
3962 }
3963
3964 mPointerGesture.referenceTouchX += commonDeltaX;
3965 mPointerGesture.referenceTouchY += commonDeltaY;
3966 mPointerGesture.referenceGestureX +=
3967 commonDeltaX * mLocked.pointerGestureXMovementScale;
3968 mPointerGesture.referenceGestureY +=
3969 commonDeltaY * mLocked.pointerGestureYMovementScale;
3970 clampPositionUsingPointerBounds(mPointerController,
3971 &mPointerGesture.referenceGestureX,
3972 &mPointerGesture.referenceGestureY);
3973 }
3974
3975 // Report gestures.
3976 if (mPointerGesture.currentGestureMode == PointerGesture::PRESS) {
3977 // PRESS mode.
Jeff Brown96ad3972011-03-09 17:39:48 -08003978#if DEBUG_GESTURES
Jeff Brown86ea1f52011-04-12 22:39:53 -07003979 LOGD("Gestures: PRESS activeTouchId=%d,"
Jeff Brown96ad3972011-03-09 17:39:48 -08003980 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown86ea1f52011-04-12 22:39:53 -07003981 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
Jeff Brown96ad3972011-03-09 17:39:48 -08003982#endif
Jeff Brown86ea1f52011-04-12 22:39:53 -07003983 LOG_ASSERT(mPointerGesture.activeGestureId >= 0);
Jeff Brown96ad3972011-03-09 17:39:48 -08003984
Jeff Brown96ad3972011-03-09 17:39:48 -08003985 mPointerGesture.currentGestureIdBits.clear();
3986 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
3987 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
3988 mPointerGesture.currentGestureCoords[0].clear();
Jeff Brown86ea1f52011-04-12 22:39:53 -07003989 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
3990 mPointerGesture.referenceGestureX);
3991 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
3992 mPointerGesture.referenceGestureY);
Jeff Brown96ad3972011-03-09 17:39:48 -08003993 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
Jeff Brown86ea1f52011-04-12 22:39:53 -07003994
3995 mPointerController->setButtonState(BUTTON_STATE_PRIMARY);
3996
3997 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
3998 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_PRESS;
3999 }
4000 } else if (mPointerGesture.currentGestureMode == PointerGesture::SWIPE) {
4001 // SWIPE mode.
4002#if DEBUG_GESTURES
4003 LOGD("Gestures: SWIPE activeTouchId=%d,"
4004 "activeGestureId=%d, currentTouchPointerCount=%d",
4005 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
4006#endif
4007 assert(mPointerGesture.activeGestureId >= 0);
4008
4009 mPointerGesture.currentGestureIdBits.clear();
4010 mPointerGesture.currentGestureIdBits.markBit(mPointerGesture.activeGestureId);
4011 mPointerGesture.currentGestureIdToIndex[mPointerGesture.activeGestureId] = 0;
4012 mPointerGesture.currentGestureCoords[0].clear();
4013 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_X,
4014 mPointerGesture.referenceGestureX);
4015 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_Y,
4016 mPointerGesture.referenceGestureY);
4017 mPointerGesture.currentGestureCoords[0].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4018
4019 mPointerController->setButtonState(0); // touch is not actually following the pointer
4020
4021 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4022 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_SWIPE;
4023 }
Jeff Brown96ad3972011-03-09 17:39:48 -08004024 } else if (mPointerGesture.currentGestureMode == PointerGesture::FREEFORM) {
4025 // FREEFORM mode.
4026#if DEBUG_GESTURES
4027 LOGD("Gestures: FREEFORM activeTouchId=%d,"
4028 "activeGestureId=%d, currentTouchPointerCount=%d",
Jeff Brown86ea1f52011-04-12 22:39:53 -07004029 activeTouchId, mPointerGesture.activeGestureId, mCurrentTouch.pointerCount);
Jeff Brown96ad3972011-03-09 17:39:48 -08004030#endif
4031 assert(mPointerGesture.activeGestureId >= 0);
4032
Jeff Brown96ad3972011-03-09 17:39:48 -08004033 mPointerGesture.currentGestureIdBits.clear();
4034
4035 BitSet32 mappedTouchIdBits;
4036 BitSet32 usedGestureIdBits;
4037 if (mPointerGesture.lastGestureMode != PointerGesture::FREEFORM) {
4038 // Initially, assign the active gesture id to the active touch point
4039 // if there is one. No other touch id bits are mapped yet.
4040 if (!*outCancelPreviousGesture) {
4041 mappedTouchIdBits.markBit(activeTouchId);
4042 usedGestureIdBits.markBit(mPointerGesture.activeGestureId);
4043 mPointerGesture.freeformTouchToGestureIdMap[activeTouchId] =
4044 mPointerGesture.activeGestureId;
4045 } else {
4046 mPointerGesture.activeGestureId = -1;
4047 }
4048 } else {
4049 // Otherwise, assume we mapped all touches from the previous frame.
4050 // Reuse all mappings that are still applicable.
4051 mappedTouchIdBits.value = mLastTouch.idBits.value & mCurrentTouch.idBits.value;
4052 usedGestureIdBits = mPointerGesture.lastGestureIdBits;
4053
4054 // Check whether we need to choose a new active gesture id because the
4055 // current went went up.
4056 for (BitSet32 upTouchIdBits(mLastTouch.idBits.value & ~mCurrentTouch.idBits.value);
4057 !upTouchIdBits.isEmpty(); ) {
4058 uint32_t upTouchId = upTouchIdBits.firstMarkedBit();
4059 upTouchIdBits.clearBit(upTouchId);
4060 uint32_t upGestureId = mPointerGesture.freeformTouchToGestureIdMap[upTouchId];
4061 if (upGestureId == uint32_t(mPointerGesture.activeGestureId)) {
4062 mPointerGesture.activeGestureId = -1;
4063 break;
4064 }
4065 }
4066 }
4067
4068#if DEBUG_GESTURES
4069 LOGD("Gestures: FREEFORM follow up "
4070 "mappedTouchIdBits=0x%08x, usedGestureIdBits=0x%08x, "
4071 "activeGestureId=%d",
4072 mappedTouchIdBits.value, usedGestureIdBits.value,
4073 mPointerGesture.activeGestureId);
4074#endif
4075
Jeff Brown86ea1f52011-04-12 22:39:53 -07004076 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
Jeff Brown96ad3972011-03-09 17:39:48 -08004077 uint32_t touchId = mCurrentTouch.pointers[i].id;
4078 uint32_t gestureId;
4079 if (!mappedTouchIdBits.hasBit(touchId)) {
4080 gestureId = usedGestureIdBits.firstUnmarkedBit();
4081 usedGestureIdBits.markBit(gestureId);
4082 mPointerGesture.freeformTouchToGestureIdMap[touchId] = gestureId;
4083#if DEBUG_GESTURES
4084 LOGD("Gestures: FREEFORM "
4085 "new mapping for touch id %d -> gesture id %d",
4086 touchId, gestureId);
4087#endif
4088 } else {
4089 gestureId = mPointerGesture.freeformTouchToGestureIdMap[touchId];
4090#if DEBUG_GESTURES
4091 LOGD("Gestures: FREEFORM "
4092 "existing mapping for touch id %d -> gesture id %d",
4093 touchId, gestureId);
4094#endif
4095 }
4096 mPointerGesture.currentGestureIdBits.markBit(gestureId);
4097 mPointerGesture.currentGestureIdToIndex[gestureId] = i;
4098
Jeff Brown86ea1f52011-04-12 22:39:53 -07004099 float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4100 * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
4101 float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4102 * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
Jeff Brown96ad3972011-03-09 17:39:48 -08004103
4104 mPointerGesture.currentGestureCoords[i].clear();
4105 mPointerGesture.currentGestureCoords[i].setAxisValue(
4106 AMOTION_EVENT_AXIS_X, x);
4107 mPointerGesture.currentGestureCoords[i].setAxisValue(
4108 AMOTION_EVENT_AXIS_Y, y);
4109 mPointerGesture.currentGestureCoords[i].setAxisValue(
4110 AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4111 }
4112
4113 if (mPointerGesture.activeGestureId < 0) {
4114 mPointerGesture.activeGestureId =
4115 mPointerGesture.currentGestureIdBits.firstMarkedBit();
4116#if DEBUG_GESTURES
4117 LOGD("Gestures: FREEFORM new "
4118 "activeGestureId=%d", mPointerGesture.activeGestureId);
4119#endif
4120 }
Jeff Brown96ad3972011-03-09 17:39:48 -08004121
Jeff Brown86ea1f52011-04-12 22:39:53 -07004122 mPointerController->setButtonState(0); // touch is not actually following the pointer
4123
4124 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4125 mPointerGesture.spotGesture = PointerControllerInterface::SPOT_GESTURE_FREEFORM;
4126 }
4127 }
4128
4129 // Update spot locations for PRESS, SWIPE and FREEFORM.
4130 // We use the same calculation as we do to calculate the gesture pointers
4131 // for FREEFORM so that the spots smoothly track gestures.
4132 if (mParameters.gestureMode == Parameters::GESTURE_MODE_SPOTS) {
4133 mPointerGesture.spotIdBits.clear();
4134 for (uint32_t i = 0; i < mCurrentTouch.pointerCount; i++) {
4135 uint32_t id = mCurrentTouch.pointers[i].id;
4136 mPointerGesture.spotIdBits.markBit(id);
4137 mPointerGesture.spotIdToIndex[id] = i;
4138
4139 float x = (mCurrentTouch.pointers[i].x - mPointerGesture.referenceTouchX)
4140 * mLocked.pointerGestureXZoomScale + mPointerGesture.referenceGestureX;
4141 float y = (mCurrentTouch.pointers[i].y - mPointerGesture.referenceTouchY)
4142 * mLocked.pointerGestureYZoomScale + mPointerGesture.referenceGestureY;
4143
4144 mPointerGesture.spotCoords[i].clear();
4145 mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_X, x);
4146 mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_Y, y);
4147 mPointerGesture.spotCoords[i].setAxisValue(AMOTION_EVENT_AXIS_PRESSURE, 1.0f);
4148 }
4149 moveSpotsLocked();
4150 }
Jeff Brown96ad3972011-03-09 17:39:48 -08004151 }
4152
4153#if DEBUG_GESTURES
4154 LOGD("Gestures: finishPreviousGesture=%s, cancelPreviousGesture=%s, "
Jeff Brown86ea1f52011-04-12 22:39:53 -07004155 "currentGestureMode=%d, currentGestureIdBits=0x%08x, "
4156 "lastGestureMode=%d, lastGestureIdBits=0x%08x",
Jeff Brown96ad3972011-03-09 17:39:48 -08004157 toString(*outFinishPreviousGesture), toString(*outCancelPreviousGesture),
Jeff Brown86ea1f52011-04-12 22:39:53 -07004158 mPointerGesture.currentGestureMode, mPointerGesture.currentGestureIdBits.value,
4159 mPointerGesture.lastGestureMode, mPointerGesture.lastGestureIdBits.value);
Jeff Brown96ad3972011-03-09 17:39:48 -08004160 for (BitSet32 idBits = mPointerGesture.currentGestureIdBits; !idBits.isEmpty(); ) {
4161 uint32_t id = idBits.firstMarkedBit();
4162 idBits.clearBit(id);
4163 uint32_t index = mPointerGesture.currentGestureIdToIndex[id];
4164 const PointerCoords& coords = mPointerGesture.currentGestureCoords[index];
4165 LOGD(" currentGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
4166 id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4167 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4168 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4169 }
4170 for (BitSet32 idBits = mPointerGesture.lastGestureIdBits; !idBits.isEmpty(); ) {
4171 uint32_t id = idBits.firstMarkedBit();
4172 idBits.clearBit(id);
4173 uint32_t index = mPointerGesture.lastGestureIdToIndex[id];
4174 const PointerCoords& coords = mPointerGesture.lastGestureCoords[index];
4175 LOGD(" lastGesture[%d]: index=%d, x=%0.3f, y=%0.3f, pressure=%0.3f",
4176 id, index, coords.getAxisValue(AMOTION_EVENT_AXIS_X),
4177 coords.getAxisValue(AMOTION_EVENT_AXIS_Y),
4178 coords.getAxisValue(AMOTION_EVENT_AXIS_PRESSURE));
4179 }
4180#endif
Jeff Brown325bd072011-04-19 21:20:10 -07004181 return true;
Jeff Brown96ad3972011-03-09 17:39:48 -08004182}
4183
Jeff Brown86ea1f52011-04-12 22:39:53 -07004184void TouchInputMapper::moveSpotsLocked() {
4185 mPointerController->setSpots(mPointerGesture.spotGesture,
4186 mPointerGesture.spotCoords, mPointerGesture.spotIdToIndex, mPointerGesture.spotIdBits);
4187}
4188
Jeff Brown96ad3972011-03-09 17:39:48 -08004189void TouchInputMapper::dispatchMotion(nsecs_t when, uint32_t policyFlags, uint32_t source,
4190 int32_t action, int32_t flags, uint32_t metaState, int32_t edgeFlags,
4191 const PointerCoords* coords, const uint32_t* idToIndex, BitSet32 idBits,
4192 int32_t changedId, float xPrecision, float yPrecision, nsecs_t downTime) {
4193 PointerCoords pointerCoords[MAX_POINTERS];
4194 int32_t pointerIds[MAX_POINTERS];
4195 uint32_t pointerCount = 0;
4196 while (!idBits.isEmpty()) {
4197 uint32_t id = idBits.firstMarkedBit();
4198 idBits.clearBit(id);
4199 uint32_t index = idToIndex[id];
4200 pointerIds[pointerCount] = id;
4201 pointerCoords[pointerCount].copyFrom(coords[index]);
4202
4203 if (changedId >= 0 && id == uint32_t(changedId)) {
4204 action |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
4205 }
4206
4207 pointerCount += 1;
4208 }
4209
4210 assert(pointerCount != 0);
4211
4212 if (changedId >= 0 && pointerCount == 1) {
4213 // Replace initial down and final up action.
4214 // We can compare the action without masking off the changed pointer index
4215 // because we know the index is 0.
4216 if (action == AMOTION_EVENT_ACTION_POINTER_DOWN) {
4217 action = AMOTION_EVENT_ACTION_DOWN;
4218 } else if (action == AMOTION_EVENT_ACTION_POINTER_UP) {
4219 action = AMOTION_EVENT_ACTION_UP;
4220 } else {
4221 // Can't happen.
4222 assert(false);
4223 }
4224 }
4225
4226 getDispatcher()->notifyMotion(when, getDeviceId(), source, policyFlags,
4227 action, flags, metaState, edgeFlags,
4228 pointerCount, pointerIds, pointerCoords, xPrecision, yPrecision, downTime);
4229}
4230
4231bool TouchInputMapper::updateMovedPointerCoords(
4232 const PointerCoords* inCoords, const uint32_t* inIdToIndex,
4233 PointerCoords* outCoords, const uint32_t* outIdToIndex, BitSet32 idBits) const {
4234 bool changed = false;
4235 while (!idBits.isEmpty()) {
4236 uint32_t id = idBits.firstMarkedBit();
4237 idBits.clearBit(id);
4238
4239 uint32_t inIndex = inIdToIndex[id];
4240 uint32_t outIndex = outIdToIndex[id];
4241 const PointerCoords& curInCoords = inCoords[inIndex];
4242 PointerCoords& curOutCoords = outCoords[outIndex];
4243
4244 if (curInCoords != curOutCoords) {
4245 curOutCoords.copyFrom(curInCoords);
4246 changed = true;
4247 }
4248 }
4249 return changed;
4250}
4251
4252void TouchInputMapper::fadePointer() {
4253 { // acquire lock
4254 AutoMutex _l(mLock);
4255 if (mPointerController != NULL) {
4256 mPointerController->fade();
4257 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004258 } // release lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07004259}
4260
Jeff Brown6328cdc2010-07-29 18:18:33 -07004261bool TouchInputMapper::isPointInsideSurfaceLocked(int32_t x, int32_t y) {
Jeff Brown9626b142011-03-03 02:09:54 -08004262 return x >= mRawAxes.x.minValue && x <= mRawAxes.x.maxValue
4263 && y >= mRawAxes.y.minValue && y <= mRawAxes.y.maxValue;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004264}
4265
Jeff Brown6328cdc2010-07-29 18:18:33 -07004266const TouchInputMapper::VirtualKey* TouchInputMapper::findVirtualKeyHitLocked(
4267 int32_t x, int32_t y) {
4268 size_t numVirtualKeys = mLocked.virtualKeys.size();
4269 for (size_t i = 0; i < numVirtualKeys; i++) {
4270 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004271
4272#if DEBUG_VIRTUAL_KEYS
4273 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
4274 "left=%d, top=%d, right=%d, bottom=%d",
4275 x, y,
4276 virtualKey.keyCode, virtualKey.scanCode,
4277 virtualKey.hitLeft, virtualKey.hitTop,
4278 virtualKey.hitRight, virtualKey.hitBottom);
4279#endif
4280
4281 if (virtualKey.isHit(x, y)) {
4282 return & virtualKey;
4283 }
4284 }
4285
4286 return NULL;
4287}
4288
4289void TouchInputMapper::calculatePointerIds() {
4290 uint32_t currentPointerCount = mCurrentTouch.pointerCount;
4291 uint32_t lastPointerCount = mLastTouch.pointerCount;
4292
4293 if (currentPointerCount == 0) {
4294 // No pointers to assign.
4295 mCurrentTouch.idBits.clear();
4296 } else if (lastPointerCount == 0) {
4297 // All pointers are new.
4298 mCurrentTouch.idBits.clear();
4299 for (uint32_t i = 0; i < currentPointerCount; i++) {
4300 mCurrentTouch.pointers[i].id = i;
4301 mCurrentTouch.idToIndex[i] = i;
4302 mCurrentTouch.idBits.markBit(i);
4303 }
4304 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
4305 // Only one pointer and no change in count so it must have the same id as before.
4306 uint32_t id = mLastTouch.pointers[0].id;
4307 mCurrentTouch.pointers[0].id = id;
4308 mCurrentTouch.idToIndex[id] = 0;
4309 mCurrentTouch.idBits.value = BitSet32::valueForBit(id);
4310 } else {
4311 // General case.
4312 // We build a heap of squared euclidean distances between current and last pointers
4313 // associated with the current and last pointer indices. Then, we find the best
4314 // match (by distance) for each current pointer.
4315 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
4316
4317 uint32_t heapSize = 0;
4318 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
4319 currentPointerIndex++) {
4320 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
4321 lastPointerIndex++) {
4322 int64_t deltaX = mCurrentTouch.pointers[currentPointerIndex].x
4323 - mLastTouch.pointers[lastPointerIndex].x;
4324 int64_t deltaY = mCurrentTouch.pointers[currentPointerIndex].y
4325 - mLastTouch.pointers[lastPointerIndex].y;
4326
4327 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4328
4329 // Insert new element into the heap (sift up).
4330 heap[heapSize].currentPointerIndex = currentPointerIndex;
4331 heap[heapSize].lastPointerIndex = lastPointerIndex;
4332 heap[heapSize].distance = distance;
4333 heapSize += 1;
4334 }
4335 }
4336
4337 // Heapify
4338 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
4339 startIndex -= 1;
4340 for (uint32_t parentIndex = startIndex; ;) {
4341 uint32_t childIndex = parentIndex * 2 + 1;
4342 if (childIndex >= heapSize) {
4343 break;
4344 }
4345
4346 if (childIndex + 1 < heapSize
4347 && heap[childIndex + 1].distance < heap[childIndex].distance) {
4348 childIndex += 1;
4349 }
4350
4351 if (heap[parentIndex].distance <= heap[childIndex].distance) {
4352 break;
4353 }
4354
4355 swap(heap[parentIndex], heap[childIndex]);
4356 parentIndex = childIndex;
4357 }
4358 }
4359
4360#if DEBUG_POINTER_ASSIGNMENT
4361 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
4362 for (size_t i = 0; i < heapSize; i++) {
4363 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
4364 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4365 heap[i].distance);
4366 }
4367#endif
4368
4369 // Pull matches out by increasing order of distance.
4370 // To avoid reassigning pointers that have already been matched, the loop keeps track
4371 // of which last and current pointers have been matched using the matchedXXXBits variables.
4372 // It also tracks the used pointer id bits.
4373 BitSet32 matchedLastBits(0);
4374 BitSet32 matchedCurrentBits(0);
4375 BitSet32 usedIdBits(0);
4376 bool first = true;
4377 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
4378 for (;;) {
4379 if (first) {
4380 // The first time through the loop, we just consume the root element of
4381 // the heap (the one with smallest distance).
4382 first = false;
4383 } else {
4384 // Previous iterations consumed the root element of the heap.
4385 // Pop root element off of the heap (sift down).
4386 heapSize -= 1;
4387 assert(heapSize > 0);
4388
4389 // Sift down.
4390 heap[0] = heap[heapSize];
4391 for (uint32_t parentIndex = 0; ;) {
4392 uint32_t childIndex = parentIndex * 2 + 1;
4393 if (childIndex >= heapSize) {
4394 break;
4395 }
4396
4397 if (childIndex + 1 < heapSize
4398 && heap[childIndex + 1].distance < heap[childIndex].distance) {
4399 childIndex += 1;
4400 }
4401
4402 if (heap[parentIndex].distance <= heap[childIndex].distance) {
4403 break;
4404 }
4405
4406 swap(heap[parentIndex], heap[childIndex]);
4407 parentIndex = childIndex;
4408 }
4409
4410#if DEBUG_POINTER_ASSIGNMENT
4411 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
4412 for (size_t i = 0; i < heapSize; i++) {
4413 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
4414 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
4415 heap[i].distance);
4416 }
4417#endif
4418 }
4419
4420 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
4421 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
4422
4423 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
4424 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
4425
4426 matchedCurrentBits.markBit(currentPointerIndex);
4427 matchedLastBits.markBit(lastPointerIndex);
4428
4429 uint32_t id = mLastTouch.pointers[lastPointerIndex].id;
4430 mCurrentTouch.pointers[currentPointerIndex].id = id;
4431 mCurrentTouch.idToIndex[id] = currentPointerIndex;
4432 usedIdBits.markBit(id);
4433
4434#if DEBUG_POINTER_ASSIGNMENT
4435 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
4436 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
4437#endif
4438 break;
4439 }
4440 }
4441
4442 // Assign fresh ids to new pointers.
4443 if (currentPointerCount > lastPointerCount) {
4444 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
4445 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
4446 uint32_t id = usedIdBits.firstUnmarkedBit();
4447
4448 mCurrentTouch.pointers[currentPointerIndex].id = id;
4449 mCurrentTouch.idToIndex[id] = currentPointerIndex;
4450 usedIdBits.markBit(id);
4451
4452#if DEBUG_POINTER_ASSIGNMENT
4453 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
4454 currentPointerIndex, id);
4455#endif
4456
4457 if (--i == 0) break; // done
4458 matchedCurrentBits.markBit(currentPointerIndex);
4459 }
4460 }
4461
4462 // Fix id bits.
4463 mCurrentTouch.idBits = usedIdBits;
4464 }
4465}
4466
4467/* Special hack for devices that have bad screen data: if one of the
4468 * points has moved more than a screen height from the last position,
4469 * then drop it. */
4470bool TouchInputMapper::applyBadTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004471 uint32_t pointerCount = mCurrentTouch.pointerCount;
4472
4473 // Nothing to do if there are no points.
4474 if (pointerCount == 0) {
4475 return false;
4476 }
4477
4478 // Don't do anything if a finger is going down or up. We run
4479 // here before assigning pointer IDs, so there isn't a good
4480 // way to do per-finger matching.
4481 if (pointerCount != mLastTouch.pointerCount) {
4482 return false;
4483 }
4484
4485 // We consider a single movement across more than a 7/16 of
4486 // the long size of the screen to be bad. This was a magic value
4487 // determined by looking at the maximum distance it is feasible
4488 // to actually move in one sample.
Jeff Brown9626b142011-03-03 02:09:54 -08004489 int32_t maxDeltaY = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) * 7 / 16;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004490
4491 // XXX The original code in InputDevice.java included commented out
4492 // code for testing the X axis. Note that when we drop a point
4493 // we don't actually restore the old X either. Strange.
4494 // The old code also tries to track when bad points were previously
4495 // detected but it turns out that due to the placement of a "break"
4496 // at the end of the loop, we never set mDroppedBadPoint to true
4497 // so it is effectively dead code.
4498 // Need to figure out if the old code is busted or just overcomplicated
4499 // but working as intended.
4500
4501 // Look through all new points and see if any are farther than
4502 // acceptable from all previous points.
4503 for (uint32_t i = pointerCount; i-- > 0; ) {
4504 int32_t y = mCurrentTouch.pointers[i].y;
4505 int32_t closestY = INT_MAX;
4506 int32_t closestDeltaY = 0;
4507
4508#if DEBUG_HACKS
4509 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
4510#endif
4511
4512 for (uint32_t j = pointerCount; j-- > 0; ) {
4513 int32_t lastY = mLastTouch.pointers[j].y;
4514 int32_t deltaY = abs(y - lastY);
4515
4516#if DEBUG_HACKS
4517 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
4518 j, lastY, deltaY);
4519#endif
4520
4521 if (deltaY < maxDeltaY) {
4522 goto SkipSufficientlyClosePoint;
4523 }
4524 if (deltaY < closestDeltaY) {
4525 closestDeltaY = deltaY;
4526 closestY = lastY;
4527 }
4528 }
4529
4530 // Must not have found a close enough match.
4531#if DEBUG_HACKS
4532 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
4533 i, y, closestY, closestDeltaY, maxDeltaY);
4534#endif
4535
4536 mCurrentTouch.pointers[i].y = closestY;
4537 return true; // XXX original code only corrects one point
4538
4539 SkipSufficientlyClosePoint: ;
4540 }
4541
4542 // No change.
4543 return false;
4544}
4545
4546/* Special hack for devices that have bad screen data: drop points where
4547 * the coordinate value for one axis has jumped to the other pointer's location.
4548 */
4549bool TouchInputMapper::applyJumpyTouchFilter() {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004550 uint32_t pointerCount = mCurrentTouch.pointerCount;
4551 if (mLastTouch.pointerCount != pointerCount) {
4552#if DEBUG_HACKS
4553 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
4554 mLastTouch.pointerCount, pointerCount);
4555 for (uint32_t i = 0; i < pointerCount; i++) {
4556 LOGD(" Pointer %d (%d, %d)", i,
4557 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4558 }
4559#endif
4560
4561 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
4562 if (mLastTouch.pointerCount == 1 && pointerCount == 2) {
4563 // Just drop the first few events going from 1 to 2 pointers.
4564 // They're bad often enough that they're not worth considering.
4565 mCurrentTouch.pointerCount = 1;
4566 mJumpyTouchFilter.jumpyPointsDropped += 1;
4567
4568#if DEBUG_HACKS
4569 LOGD("JumpyTouchFilter: Pointer 2 dropped");
4570#endif
4571 return true;
4572 } else if (mLastTouch.pointerCount == 2 && pointerCount == 1) {
4573 // The event when we go from 2 -> 1 tends to be messed up too
4574 mCurrentTouch.pointerCount = 2;
4575 mCurrentTouch.pointers[0] = mLastTouch.pointers[0];
4576 mCurrentTouch.pointers[1] = mLastTouch.pointers[1];
4577 mJumpyTouchFilter.jumpyPointsDropped += 1;
4578
4579#if DEBUG_HACKS
4580 for (int32_t i = 0; i < 2; i++) {
4581 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
4582 mCurrentTouch.pointers[i].x, mCurrentTouch.pointers[i].y);
4583 }
4584#endif
4585 return true;
4586 }
4587 }
4588 // Reset jumpy points dropped on other transitions or if limit exceeded.
4589 mJumpyTouchFilter.jumpyPointsDropped = 0;
4590
4591#if DEBUG_HACKS
4592 LOGD("JumpyTouchFilter: Transition - drop limit reset");
4593#endif
4594 return false;
4595 }
4596
4597 // We have the same number of pointers as last time.
4598 // A 'jumpy' point is one where the coordinate value for one axis
4599 // has jumped to the other pointer's location. No need to do anything
4600 // else if we only have one pointer.
4601 if (pointerCount < 2) {
4602 return false;
4603 }
4604
4605 if (mJumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
Jeff Brown9626b142011-03-03 02:09:54 -08004606 int jumpyEpsilon = (mRawAxes.y.maxValue - mRawAxes.y.minValue + 1) / JUMPY_EPSILON_DIVISOR;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004607
4608 // We only replace the single worst jumpy point as characterized by pointer distance
4609 // in a single axis.
4610 int32_t badPointerIndex = -1;
4611 int32_t badPointerReplacementIndex = -1;
4612 int32_t badPointerDistance = INT_MIN; // distance to be corrected
4613
4614 for (uint32_t i = pointerCount; i-- > 0; ) {
4615 int32_t x = mCurrentTouch.pointers[i].x;
4616 int32_t y = mCurrentTouch.pointers[i].y;
4617
4618#if DEBUG_HACKS
4619 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
4620#endif
4621
4622 // Check if a touch point is too close to another's coordinates
4623 bool dropX = false, dropY = false;
4624 for (uint32_t j = 0; j < pointerCount; j++) {
4625 if (i == j) {
4626 continue;
4627 }
4628
4629 if (abs(x - mCurrentTouch.pointers[j].x) <= jumpyEpsilon) {
4630 dropX = true;
4631 break;
4632 }
4633
4634 if (abs(y - mCurrentTouch.pointers[j].y) <= jumpyEpsilon) {
4635 dropY = true;
4636 break;
4637 }
4638 }
4639 if (! dropX && ! dropY) {
4640 continue; // not jumpy
4641 }
4642
4643 // Find a replacement candidate by comparing with older points on the
4644 // complementary (non-jumpy) axis.
4645 int32_t distance = INT_MIN; // distance to be corrected
4646 int32_t replacementIndex = -1;
4647
4648 if (dropX) {
4649 // X looks too close. Find an older replacement point with a close Y.
4650 int32_t smallestDeltaY = INT_MAX;
4651 for (uint32_t j = 0; j < pointerCount; j++) {
4652 int32_t deltaY = abs(y - mLastTouch.pointers[j].y);
4653 if (deltaY < smallestDeltaY) {
4654 smallestDeltaY = deltaY;
4655 replacementIndex = j;
4656 }
4657 }
4658 distance = abs(x - mLastTouch.pointers[replacementIndex].x);
4659 } else {
4660 // Y looks too close. Find an older replacement point with a close X.
4661 int32_t smallestDeltaX = INT_MAX;
4662 for (uint32_t j = 0; j < pointerCount; j++) {
4663 int32_t deltaX = abs(x - mLastTouch.pointers[j].x);
4664 if (deltaX < smallestDeltaX) {
4665 smallestDeltaX = deltaX;
4666 replacementIndex = j;
4667 }
4668 }
4669 distance = abs(y - mLastTouch.pointers[replacementIndex].y);
4670 }
4671
4672 // If replacing this pointer would correct a worse error than the previous ones
4673 // considered, then use this replacement instead.
4674 if (distance > badPointerDistance) {
4675 badPointerIndex = i;
4676 badPointerReplacementIndex = replacementIndex;
4677 badPointerDistance = distance;
4678 }
4679 }
4680
4681 // Correct the jumpy pointer if one was found.
4682 if (badPointerIndex >= 0) {
4683#if DEBUG_HACKS
4684 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
4685 badPointerIndex,
4686 mLastTouch.pointers[badPointerReplacementIndex].x,
4687 mLastTouch.pointers[badPointerReplacementIndex].y);
4688#endif
4689
4690 mCurrentTouch.pointers[badPointerIndex].x =
4691 mLastTouch.pointers[badPointerReplacementIndex].x;
4692 mCurrentTouch.pointers[badPointerIndex].y =
4693 mLastTouch.pointers[badPointerReplacementIndex].y;
4694 mJumpyTouchFilter.jumpyPointsDropped += 1;
4695 return true;
4696 }
4697 }
4698
4699 mJumpyTouchFilter.jumpyPointsDropped = 0;
4700 return false;
4701}
4702
4703/* Special hack for devices that have bad screen data: aggregate and
4704 * compute averages of the coordinate data, to reduce the amount of
4705 * jitter seen by applications. */
4706void TouchInputMapper::applyAveragingTouchFilter() {
4707 for (uint32_t currentIndex = 0; currentIndex < mCurrentTouch.pointerCount; currentIndex++) {
4708 uint32_t id = mCurrentTouch.pointers[currentIndex].id;
4709 int32_t x = mCurrentTouch.pointers[currentIndex].x;
4710 int32_t y = mCurrentTouch.pointers[currentIndex].y;
Jeff Brown8d608662010-08-30 03:02:23 -07004711 int32_t pressure;
4712 switch (mCalibration.pressureSource) {
4713 case Calibration::PRESSURE_SOURCE_PRESSURE:
4714 pressure = mCurrentTouch.pointers[currentIndex].pressure;
4715 break;
4716 case Calibration::PRESSURE_SOURCE_TOUCH:
4717 pressure = mCurrentTouch.pointers[currentIndex].touchMajor;
4718 break;
4719 default:
4720 pressure = 1;
4721 break;
4722 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07004723
4724 if (mLastTouch.idBits.hasBit(id)) {
4725 // Pointer was down before and is still down now.
4726 // Compute average over history trace.
4727 uint32_t start = mAveragingTouchFilter.historyStart[id];
4728 uint32_t end = mAveragingTouchFilter.historyEnd[id];
4729
4730 int64_t deltaX = x - mAveragingTouchFilter.historyData[end].pointers[id].x;
4731 int64_t deltaY = y - mAveragingTouchFilter.historyData[end].pointers[id].y;
4732 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
4733
4734#if DEBUG_HACKS
4735 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
4736 id, distance);
4737#endif
4738
4739 if (distance < AVERAGING_DISTANCE_LIMIT) {
4740 // Increment end index in preparation for recording new historical data.
4741 end += 1;
4742 if (end > AVERAGING_HISTORY_SIZE) {
4743 end = 0;
4744 }
4745
4746 // If the end index has looped back to the start index then we have filled
4747 // the historical trace up to the desired size so we drop the historical
4748 // data at the start of the trace.
4749 if (end == start) {
4750 start += 1;
4751 if (start > AVERAGING_HISTORY_SIZE) {
4752 start = 0;
4753 }
4754 }
4755
4756 // Add the raw data to the historical trace.
4757 mAveragingTouchFilter.historyStart[id] = start;
4758 mAveragingTouchFilter.historyEnd[id] = end;
4759 mAveragingTouchFilter.historyData[end].pointers[id].x = x;
4760 mAveragingTouchFilter.historyData[end].pointers[id].y = y;
4761 mAveragingTouchFilter.historyData[end].pointers[id].pressure = pressure;
4762
4763 // Average over all historical positions in the trace by total pressure.
4764 int32_t averagedX = 0;
4765 int32_t averagedY = 0;
4766 int32_t totalPressure = 0;
4767 for (;;) {
4768 int32_t historicalX = mAveragingTouchFilter.historyData[start].pointers[id].x;
4769 int32_t historicalY = mAveragingTouchFilter.historyData[start].pointers[id].y;
4770 int32_t historicalPressure = mAveragingTouchFilter.historyData[start]
4771 .pointers[id].pressure;
4772
4773 averagedX += historicalX * historicalPressure;
4774 averagedY += historicalY * historicalPressure;
4775 totalPressure += historicalPressure;
4776
4777 if (start == end) {
4778 break;
4779 }
4780
4781 start += 1;
4782 if (start > AVERAGING_HISTORY_SIZE) {
4783 start = 0;
4784 }
4785 }
4786
Jeff Brown8d608662010-08-30 03:02:23 -07004787 if (totalPressure != 0) {
4788 averagedX /= totalPressure;
4789 averagedY /= totalPressure;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004790
4791#if DEBUG_HACKS
Jeff Brown8d608662010-08-30 03:02:23 -07004792 LOGD("AveragingTouchFilter: Pointer id %d - "
4793 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
4794 averagedX, averagedY);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004795#endif
4796
Jeff Brown8d608662010-08-30 03:02:23 -07004797 mCurrentTouch.pointers[currentIndex].x = averagedX;
4798 mCurrentTouch.pointers[currentIndex].y = averagedY;
4799 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07004800 } else {
4801#if DEBUG_HACKS
4802 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
4803#endif
4804 }
4805 } else {
4806#if DEBUG_HACKS
4807 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
4808#endif
4809 }
4810
4811 // Reset pointer history.
4812 mAveragingTouchFilter.historyStart[id] = 0;
4813 mAveragingTouchFilter.historyEnd[id] = 0;
4814 mAveragingTouchFilter.historyData[0].pointers[id].x = x;
4815 mAveragingTouchFilter.historyData[0].pointers[id].y = y;
4816 mAveragingTouchFilter.historyData[0].pointers[id].pressure = pressure;
4817 }
4818}
4819
4820int32_t TouchInputMapper::getKeyCodeState(uint32_t sourceMask, int32_t keyCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004821 { // acquire lock
4822 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004823
Jeff Brown6328cdc2010-07-29 18:18:33 -07004824 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.keyCode == keyCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004825 return AKEY_STATE_VIRTUAL;
4826 }
4827
Jeff Brown6328cdc2010-07-29 18:18:33 -07004828 size_t numVirtualKeys = mLocked.virtualKeys.size();
4829 for (size_t i = 0; i < numVirtualKeys; i++) {
4830 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004831 if (virtualKey.keyCode == keyCode) {
4832 return AKEY_STATE_UP;
4833 }
4834 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004835 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004836
4837 return AKEY_STATE_UNKNOWN;
4838}
4839
4840int32_t TouchInputMapper::getScanCodeState(uint32_t sourceMask, int32_t scanCode) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004841 { // acquire lock
4842 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004843
Jeff Brown6328cdc2010-07-29 18:18:33 -07004844 if (mLocked.currentVirtualKey.down && mLocked.currentVirtualKey.scanCode == scanCode) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004845 return AKEY_STATE_VIRTUAL;
4846 }
4847
Jeff Brown6328cdc2010-07-29 18:18:33 -07004848 size_t numVirtualKeys = mLocked.virtualKeys.size();
4849 for (size_t i = 0; i < numVirtualKeys; i++) {
4850 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004851 if (virtualKey.scanCode == scanCode) {
4852 return AKEY_STATE_UP;
4853 }
4854 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004855 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004856
4857 return AKEY_STATE_UNKNOWN;
4858}
4859
4860bool TouchInputMapper::markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
4861 const int32_t* keyCodes, uint8_t* outFlags) {
Jeff Brown6328cdc2010-07-29 18:18:33 -07004862 { // acquire lock
4863 AutoMutex _l(mLock);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004864
Jeff Brown6328cdc2010-07-29 18:18:33 -07004865 size_t numVirtualKeys = mLocked.virtualKeys.size();
4866 for (size_t i = 0; i < numVirtualKeys; i++) {
4867 const VirtualKey& virtualKey = mLocked.virtualKeys[i];
Jeff Brown6d0fec22010-07-23 21:28:06 -07004868
4869 for (size_t i = 0; i < numCodes; i++) {
4870 if (virtualKey.keyCode == keyCodes[i]) {
4871 outFlags[i] = 1;
4872 }
4873 }
4874 }
Jeff Brown6328cdc2010-07-29 18:18:33 -07004875 } // release lock
Jeff Brown6d0fec22010-07-23 21:28:06 -07004876
4877 return true;
4878}
4879
4880
4881// --- SingleTouchInputMapper ---
4882
Jeff Brown47e6b1b2010-11-29 17:37:49 -08004883SingleTouchInputMapper::SingleTouchInputMapper(InputDevice* device) :
4884 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004885 initialize();
4886}
4887
4888SingleTouchInputMapper::~SingleTouchInputMapper() {
4889}
4890
4891void SingleTouchInputMapper::initialize() {
4892 mAccumulator.clear();
4893
4894 mDown = false;
4895 mX = 0;
4896 mY = 0;
Jeff Brown8d608662010-08-30 03:02:23 -07004897 mPressure = 0; // default to 0 for devices that don't report pressure
4898 mToolWidth = 0; // default to 0 for devices that don't report tool width
Jeff Brown96ad3972011-03-09 17:39:48 -08004899 mButtonState = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004900}
4901
4902void SingleTouchInputMapper::reset() {
4903 TouchInputMapper::reset();
4904
Jeff Brown6d0fec22010-07-23 21:28:06 -07004905 initialize();
4906 }
4907
4908void SingleTouchInputMapper::process(const RawEvent* rawEvent) {
4909 switch (rawEvent->type) {
4910 case EV_KEY:
4911 switch (rawEvent->scanCode) {
4912 case BTN_TOUCH:
4913 mAccumulator.fields |= Accumulator::FIELD_BTN_TOUCH;
4914 mAccumulator.btnTouch = rawEvent->value != 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07004915 // Don't sync immediately. Wait until the next SYN_REPORT since we might
4916 // not have received valid position information yet. This logic assumes that
4917 // BTN_TOUCH is always followed by SYN_REPORT as part of a complete packet.
Jeff Brown6d0fec22010-07-23 21:28:06 -07004918 break;
Jeff Brown96ad3972011-03-09 17:39:48 -08004919 default:
4920 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
4921 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
4922 if (buttonState) {
4923 if (rawEvent->value) {
4924 mAccumulator.buttonDown |= buttonState;
4925 } else {
4926 mAccumulator.buttonUp |= buttonState;
4927 }
4928 mAccumulator.fields |= Accumulator::FIELD_BUTTONS;
4929 }
4930 }
4931 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004932 }
4933 break;
4934
4935 case EV_ABS:
4936 switch (rawEvent->scanCode) {
4937 case ABS_X:
4938 mAccumulator.fields |= Accumulator::FIELD_ABS_X;
4939 mAccumulator.absX = rawEvent->value;
4940 break;
4941 case ABS_Y:
4942 mAccumulator.fields |= Accumulator::FIELD_ABS_Y;
4943 mAccumulator.absY = rawEvent->value;
4944 break;
4945 case ABS_PRESSURE:
4946 mAccumulator.fields |= Accumulator::FIELD_ABS_PRESSURE;
4947 mAccumulator.absPressure = rawEvent->value;
4948 break;
4949 case ABS_TOOL_WIDTH:
4950 mAccumulator.fields |= Accumulator::FIELD_ABS_TOOL_WIDTH;
4951 mAccumulator.absToolWidth = rawEvent->value;
4952 break;
4953 }
4954 break;
4955
4956 case EV_SYN:
4957 switch (rawEvent->scanCode) {
4958 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07004959 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07004960 break;
4961 }
4962 break;
4963 }
4964}
4965
4966void SingleTouchInputMapper::sync(nsecs_t when) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07004967 uint32_t fields = mAccumulator.fields;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07004968 if (fields == 0) {
4969 return; // no new state changes, so nothing to do
4970 }
Jeff Brown6d0fec22010-07-23 21:28:06 -07004971
4972 if (fields & Accumulator::FIELD_BTN_TOUCH) {
4973 mDown = mAccumulator.btnTouch;
4974 }
4975
4976 if (fields & Accumulator::FIELD_ABS_X) {
4977 mX = mAccumulator.absX;
4978 }
4979
4980 if (fields & Accumulator::FIELD_ABS_Y) {
4981 mY = mAccumulator.absY;
4982 }
4983
4984 if (fields & Accumulator::FIELD_ABS_PRESSURE) {
4985 mPressure = mAccumulator.absPressure;
4986 }
4987
4988 if (fields & Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown8d608662010-08-30 03:02:23 -07004989 mToolWidth = mAccumulator.absToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07004990 }
4991
Jeff Brown96ad3972011-03-09 17:39:48 -08004992 if (fields & Accumulator::FIELD_BUTTONS) {
4993 mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
4994 }
4995
Jeff Brown6d0fec22010-07-23 21:28:06 -07004996 mCurrentTouch.clear();
4997
4998 if (mDown) {
4999 mCurrentTouch.pointerCount = 1;
5000 mCurrentTouch.pointers[0].id = 0;
5001 mCurrentTouch.pointers[0].x = mX;
5002 mCurrentTouch.pointers[0].y = mY;
5003 mCurrentTouch.pointers[0].pressure = mPressure;
Jeff Brown8d608662010-08-30 03:02:23 -07005004 mCurrentTouch.pointers[0].touchMajor = 0;
5005 mCurrentTouch.pointers[0].touchMinor = 0;
5006 mCurrentTouch.pointers[0].toolMajor = mToolWidth;
5007 mCurrentTouch.pointers[0].toolMinor = mToolWidth;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005008 mCurrentTouch.pointers[0].orientation = 0;
5009 mCurrentTouch.idToIndex[0] = 0;
5010 mCurrentTouch.idBits.markBit(0);
Jeff Brown96ad3972011-03-09 17:39:48 -08005011 mCurrentTouch.buttonState = mButtonState;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005012 }
5013
5014 syncTouch(when, true);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005015
5016 mAccumulator.clear();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005017}
5018
Jeff Brown8d608662010-08-30 03:02:23 -07005019void SingleTouchInputMapper::configureRawAxes() {
5020 TouchInputMapper::configureRawAxes();
Jeff Brown6d0fec22010-07-23 21:28:06 -07005021
Jeff Brown8d608662010-08-30 03:02:23 -07005022 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_X, & mRawAxes.x);
5023 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_Y, & mRawAxes.y);
5024 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_PRESSURE, & mRawAxes.pressure);
5025 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), ABS_TOOL_WIDTH, & mRawAxes.toolMajor);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005026}
5027
5028
5029// --- MultiTouchInputMapper ---
5030
Jeff Brown47e6b1b2010-11-29 17:37:49 -08005031MultiTouchInputMapper::MultiTouchInputMapper(InputDevice* device) :
5032 TouchInputMapper(device) {
Jeff Brown6d0fec22010-07-23 21:28:06 -07005033 initialize();
5034}
5035
5036MultiTouchInputMapper::~MultiTouchInputMapper() {
5037}
5038
5039void MultiTouchInputMapper::initialize() {
5040 mAccumulator.clear();
Jeff Brown96ad3972011-03-09 17:39:48 -08005041 mButtonState = 0;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005042}
5043
5044void MultiTouchInputMapper::reset() {
5045 TouchInputMapper::reset();
5046
Jeff Brown6d0fec22010-07-23 21:28:06 -07005047 initialize();
5048}
5049
5050void MultiTouchInputMapper::process(const RawEvent* rawEvent) {
5051 switch (rawEvent->type) {
Jeff Brown96ad3972011-03-09 17:39:48 -08005052 case EV_KEY: {
5053 if (mParameters.deviceType == Parameters::DEVICE_TYPE_POINTER) {
5054 uint32_t buttonState = getButtonStateForScanCode(rawEvent->scanCode);
5055 if (buttonState) {
5056 if (rawEvent->value) {
5057 mAccumulator.buttonDown |= buttonState;
5058 } else {
5059 mAccumulator.buttonUp |= buttonState;
5060 }
5061 }
5062 }
5063 break;
5064 }
5065
Jeff Brown6d0fec22010-07-23 21:28:06 -07005066 case EV_ABS: {
5067 uint32_t pointerIndex = mAccumulator.pointerCount;
5068 Accumulator::Pointer* pointer = & mAccumulator.pointers[pointerIndex];
5069
5070 switch (rawEvent->scanCode) {
5071 case ABS_MT_POSITION_X:
5072 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_X;
5073 pointer->absMTPositionX = rawEvent->value;
5074 break;
5075 case ABS_MT_POSITION_Y:
5076 pointer->fields |= Accumulator::FIELD_ABS_MT_POSITION_Y;
5077 pointer->absMTPositionY = rawEvent->value;
5078 break;
5079 case ABS_MT_TOUCH_MAJOR:
5080 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
5081 pointer->absMTTouchMajor = rawEvent->value;
5082 break;
5083 case ABS_MT_TOUCH_MINOR:
5084 pointer->fields |= Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
5085 pointer->absMTTouchMinor = rawEvent->value;
5086 break;
5087 case ABS_MT_WIDTH_MAJOR:
5088 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
5089 pointer->absMTWidthMajor = rawEvent->value;
5090 break;
5091 case ABS_MT_WIDTH_MINOR:
5092 pointer->fields |= Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
5093 pointer->absMTWidthMinor = rawEvent->value;
5094 break;
5095 case ABS_MT_ORIENTATION:
5096 pointer->fields |= Accumulator::FIELD_ABS_MT_ORIENTATION;
5097 pointer->absMTOrientation = rawEvent->value;
5098 break;
5099 case ABS_MT_TRACKING_ID:
5100 pointer->fields |= Accumulator::FIELD_ABS_MT_TRACKING_ID;
5101 pointer->absMTTrackingId = rawEvent->value;
5102 break;
Jeff Brown8d608662010-08-30 03:02:23 -07005103 case ABS_MT_PRESSURE:
5104 pointer->fields |= Accumulator::FIELD_ABS_MT_PRESSURE;
5105 pointer->absMTPressure = rawEvent->value;
5106 break;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005107 }
5108 break;
5109 }
5110
5111 case EV_SYN:
5112 switch (rawEvent->scanCode) {
5113 case SYN_MT_REPORT: {
5114 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
5115 uint32_t pointerIndex = mAccumulator.pointerCount;
5116
5117 if (mAccumulator.pointers[pointerIndex].fields) {
5118 if (pointerIndex == MAX_POINTERS) {
5119 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
5120 MAX_POINTERS);
5121 } else {
5122 pointerIndex += 1;
5123 mAccumulator.pointerCount = pointerIndex;
5124 }
5125 }
5126
5127 mAccumulator.pointers[pointerIndex].clear();
5128 break;
5129 }
5130
5131 case SYN_REPORT:
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005132 sync(rawEvent->when);
Jeff Brown6d0fec22010-07-23 21:28:06 -07005133 break;
5134 }
5135 break;
5136 }
5137}
5138
5139void MultiTouchInputMapper::sync(nsecs_t when) {
5140 static const uint32_t REQUIRED_FIELDS =
Jeff Brown8d608662010-08-30 03:02:23 -07005141 Accumulator::FIELD_ABS_MT_POSITION_X | Accumulator::FIELD_ABS_MT_POSITION_Y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005142
Jeff Brown6d0fec22010-07-23 21:28:06 -07005143 uint32_t inCount = mAccumulator.pointerCount;
5144 uint32_t outCount = 0;
5145 bool havePointerIds = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005146
Jeff Brown6d0fec22010-07-23 21:28:06 -07005147 mCurrentTouch.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005148
Jeff Brown6d0fec22010-07-23 21:28:06 -07005149 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005150 const Accumulator::Pointer& inPointer = mAccumulator.pointers[inIndex];
5151 uint32_t fields = inPointer.fields;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005152
Jeff Brown6d0fec22010-07-23 21:28:06 -07005153 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005154 // Some drivers send empty MT sync packets without X / Y to indicate a pointer up.
5155 // Drop this finger.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005156 continue;
5157 }
5158
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005159 PointerData& outPointer = mCurrentTouch.pointers[outCount];
5160 outPointer.x = inPointer.absMTPositionX;
5161 outPointer.y = inPointer.absMTPositionY;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005162
Jeff Brown8d608662010-08-30 03:02:23 -07005163 if (fields & Accumulator::FIELD_ABS_MT_PRESSURE) {
5164 if (inPointer.absMTPressure <= 0) {
Jeff Brownc3db8582010-10-20 15:33:38 -07005165 // Some devices send sync packets with X / Y but with a 0 pressure to indicate
5166 // a pointer going up. Drop this finger.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005167 continue;
5168 }
Jeff Brown8d608662010-08-30 03:02:23 -07005169 outPointer.pressure = inPointer.absMTPressure;
5170 } else {
5171 // Default pressure to 0 if absent.
5172 outPointer.pressure = 0;
5173 }
5174
5175 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MAJOR) {
5176 if (inPointer.absMTTouchMajor <= 0) {
5177 // Some devices send sync packets with X / Y but with a 0 touch major to indicate
5178 // a pointer going up. Drop this finger.
5179 continue;
5180 }
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005181 outPointer.touchMajor = inPointer.absMTTouchMajor;
5182 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005183 // Default touch area to 0 if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005184 outPointer.touchMajor = 0;
5185 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005186
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005187 if (fields & Accumulator::FIELD_ABS_MT_TOUCH_MINOR) {
5188 outPointer.touchMinor = inPointer.absMTTouchMinor;
5189 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005190 // Assume touch area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005191 outPointer.touchMinor = outPointer.touchMajor;
5192 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005193
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005194 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MAJOR) {
5195 outPointer.toolMajor = inPointer.absMTWidthMajor;
5196 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005197 // Default tool area to 0 if absent.
5198 outPointer.toolMajor = 0;
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005199 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005200
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005201 if (fields & Accumulator::FIELD_ABS_MT_WIDTH_MINOR) {
5202 outPointer.toolMinor = inPointer.absMTWidthMinor;
5203 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005204 // Assume tool area is circular.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005205 outPointer.toolMinor = outPointer.toolMajor;
5206 }
5207
5208 if (fields & Accumulator::FIELD_ABS_MT_ORIENTATION) {
5209 outPointer.orientation = inPointer.absMTOrientation;
5210 } else {
Jeff Brown8d608662010-08-30 03:02:23 -07005211 // Default orientation to vertical if absent.
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005212 outPointer.orientation = 0;
5213 }
5214
Jeff Brown8d608662010-08-30 03:02:23 -07005215 // Assign pointer id using tracking id if available.
Jeff Brown6d0fec22010-07-23 21:28:06 -07005216 if (havePointerIds) {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005217 if (fields & Accumulator::FIELD_ABS_MT_TRACKING_ID) {
5218 uint32_t id = uint32_t(inPointer.absMTTrackingId);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005219
Jeff Brown6d0fec22010-07-23 21:28:06 -07005220 if (id > MAX_POINTER_ID) {
5221#if DEBUG_POINTERS
5222 LOGD("Pointers: Ignoring driver provided pointer id %d because "
Jeff Brown01ce2e92010-09-26 22:20:12 -07005223 "it is larger than max supported id %d",
Jeff Brown6d0fec22010-07-23 21:28:06 -07005224 id, MAX_POINTER_ID);
5225#endif
5226 havePointerIds = false;
5227 }
5228 else {
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005229 outPointer.id = id;
Jeff Brown6d0fec22010-07-23 21:28:06 -07005230 mCurrentTouch.idToIndex[id] = outCount;
5231 mCurrentTouch.idBits.markBit(id);
5232 }
5233 } else {
5234 havePointerIds = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005235 }
5236 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005237
Jeff Brown6d0fec22010-07-23 21:28:06 -07005238 outCount += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005239 }
5240
Jeff Brown6d0fec22010-07-23 21:28:06 -07005241 mCurrentTouch.pointerCount = outCount;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005242
Jeff Brown96ad3972011-03-09 17:39:48 -08005243 mButtonState = (mButtonState | mAccumulator.buttonDown) & ~mAccumulator.buttonUp;
5244 mCurrentTouch.buttonState = mButtonState;
5245
Jeff Brown6d0fec22010-07-23 21:28:06 -07005246 syncTouch(when, havePointerIds);
Jeff Brown2dfd7a72010-08-17 20:38:35 -07005247
5248 mAccumulator.clear();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005249}
5250
Jeff Brown8d608662010-08-30 03:02:23 -07005251void MultiTouchInputMapper::configureRawAxes() {
5252 TouchInputMapper::configureRawAxes();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005253
Jeff Brown8d608662010-08-30 03:02:23 -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);
Jeff Brown9c3cda02010-06-15 01:31:58 -07005262}
5263
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005264
Jeff Browncb1404e2011-01-15 18:14:15 -08005265// --- JoystickInputMapper ---
5266
5267JoystickInputMapper::JoystickInputMapper(InputDevice* device) :
5268 InputMapper(device) {
Jeff Browncb1404e2011-01-15 18:14:15 -08005269}
5270
5271JoystickInputMapper::~JoystickInputMapper() {
5272}
5273
5274uint32_t JoystickInputMapper::getSources() {
5275 return AINPUT_SOURCE_JOYSTICK;
5276}
5277
5278void JoystickInputMapper::populateDeviceInfo(InputDeviceInfo* info) {
5279 InputMapper::populateDeviceInfo(info);
5280
Jeff Brown6f2fba42011-02-19 01:08:02 -08005281 for (size_t i = 0; i < mAxes.size(); i++) {
5282 const Axis& axis = mAxes.valueAt(i);
Jeff Brownefd32662011-03-08 15:13:06 -08005283 info->addMotionRange(axis.axisInfo.axis, AINPUT_SOURCE_JOYSTICK,
5284 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005285 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
Jeff Brownefd32662011-03-08 15:13:06 -08005286 info->addMotionRange(axis.axisInfo.highAxis, AINPUT_SOURCE_JOYSTICK,
5287 axis.min, axis.max, axis.flat, axis.fuzz);
Jeff Brown85297452011-03-04 13:07:49 -08005288 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005289 }
5290}
5291
5292void JoystickInputMapper::dump(String8& dump) {
5293 dump.append(INDENT2 "Joystick Input Mapper:\n");
5294
Jeff Brown6f2fba42011-02-19 01:08:02 -08005295 dump.append(INDENT3 "Axes:\n");
5296 size_t numAxes = mAxes.size();
5297 for (size_t i = 0; i < numAxes; i++) {
5298 const Axis& axis = mAxes.valueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005299 const char* label = getAxisLabel(axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005300 if (label) {
Jeff Brown85297452011-03-04 13:07:49 -08005301 dump.appendFormat(INDENT4 "%s", label);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005302 } else {
Jeff Brown85297452011-03-04 13:07:49 -08005303 dump.appendFormat(INDENT4 "%d", axis.axisInfo.axis);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005304 }
Jeff Brown85297452011-03-04 13:07:49 -08005305 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5306 label = getAxisLabel(axis.axisInfo.highAxis);
5307 if (label) {
5308 dump.appendFormat(" / %s (split at %d)", label, axis.axisInfo.splitValue);
5309 } else {
5310 dump.appendFormat(" / %d (split at %d)", axis.axisInfo.highAxis,
5311 axis.axisInfo.splitValue);
5312 }
5313 } else if (axis.axisInfo.mode == AxisInfo::MODE_INVERT) {
5314 dump.append(" (invert)");
5315 }
5316
5317 dump.appendFormat(": min=%0.5f, max=%0.5f, flat=%0.5f, fuzz=%0.5f\n",
5318 axis.min, axis.max, axis.flat, axis.fuzz);
5319 dump.appendFormat(INDENT4 " scale=%0.5f, offset=%0.5f, "
5320 "highScale=%0.5f, highOffset=%0.5f\n",
5321 axis.scale, axis.offset, axis.highScale, axis.highOffset);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005322 dump.appendFormat(INDENT4 " rawAxis=%d, rawMin=%d, rawMax=%d, rawFlat=%d, rawFuzz=%d\n",
5323 mAxes.keyAt(i), axis.rawAxisInfo.minValue, axis.rawAxisInfo.maxValue,
5324 axis.rawAxisInfo.flat, axis.rawAxisInfo.fuzz);
Jeff Browncb1404e2011-01-15 18:14:15 -08005325 }
5326}
5327
5328void JoystickInputMapper::configure() {
5329 InputMapper::configure();
5330
Jeff Brown6f2fba42011-02-19 01:08:02 -08005331 // Collect all axes.
5332 for (int32_t abs = 0; abs <= ABS_MAX; abs++) {
5333 RawAbsoluteAxisInfo rawAxisInfo;
5334 getEventHub()->getAbsoluteAxisInfo(getDeviceId(), abs, &rawAxisInfo);
5335 if (rawAxisInfo.valid) {
Jeff Brown85297452011-03-04 13:07:49 -08005336 // Map axis.
5337 AxisInfo axisInfo;
5338 bool explicitlyMapped = !getEventHub()->mapAxis(getDeviceId(), abs, &axisInfo);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005339 if (!explicitlyMapped) {
5340 // Axis is not explicitly mapped, will choose a generic axis later.
Jeff Brown85297452011-03-04 13:07:49 -08005341 axisInfo.mode = AxisInfo::MODE_NORMAL;
5342 axisInfo.axis = -1;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005343 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005344
Jeff Brown85297452011-03-04 13:07:49 -08005345 // Apply flat override.
5346 int32_t rawFlat = axisInfo.flatOverride < 0
5347 ? rawAxisInfo.flat : axisInfo.flatOverride;
5348
5349 // Calculate scaling factors and limits.
Jeff Brown6f2fba42011-02-19 01:08:02 -08005350 Axis axis;
Jeff Brown85297452011-03-04 13:07:49 -08005351 if (axisInfo.mode == AxisInfo::MODE_SPLIT) {
5352 float scale = 1.0f / (axisInfo.splitValue - rawAxisInfo.minValue);
5353 float highScale = 1.0f / (rawAxisInfo.maxValue - axisInfo.splitValue);
5354 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5355 scale, 0.0f, highScale, 0.0f,
5356 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
5357 } else if (isCenteredAxis(axisInfo.axis)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005358 float scale = 2.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
5359 float offset = avg(rawAxisInfo.minValue, rawAxisInfo.maxValue) * -scale;
Jeff Brown85297452011-03-04 13:07:49 -08005360 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5361 scale, offset, scale, offset,
5362 -1.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005363 } else {
5364 float scale = 1.0f / (rawAxisInfo.maxValue - rawAxisInfo.minValue);
Jeff Brown85297452011-03-04 13:07:49 -08005365 axis.initialize(rawAxisInfo, axisInfo, explicitlyMapped,
5366 scale, 0.0f, scale, 0.0f,
5367 0.0f, 1.0f, rawFlat * scale, rawAxisInfo.fuzz * scale);
Jeff Brown6f2fba42011-02-19 01:08:02 -08005368 }
5369
5370 // To eliminate noise while the joystick is at rest, filter out small variations
5371 // in axis values up front.
5372 axis.filter = axis.flat * 0.25f;
5373
5374 mAxes.add(abs, axis);
5375 }
5376 }
5377
5378 // If there are too many axes, start dropping them.
5379 // Prefer to keep explicitly mapped axes.
5380 if (mAxes.size() > PointerCoords::MAX_AXES) {
5381 LOGI("Joystick '%s' has %d axes but the framework only supports a maximum of %d.",
5382 getDeviceName().string(), mAxes.size(), PointerCoords::MAX_AXES);
5383 pruneAxes(true);
5384 pruneAxes(false);
5385 }
5386
5387 // Assign generic axis ids to remaining axes.
5388 int32_t nextGenericAxisId = AMOTION_EVENT_AXIS_GENERIC_1;
5389 size_t numAxes = mAxes.size();
5390 for (size_t i = 0; i < numAxes; i++) {
5391 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005392 if (axis.axisInfo.axis < 0) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005393 while (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16
5394 && haveAxis(nextGenericAxisId)) {
5395 nextGenericAxisId += 1;
5396 }
5397
5398 if (nextGenericAxisId <= AMOTION_EVENT_AXIS_GENERIC_16) {
Jeff Brown85297452011-03-04 13:07:49 -08005399 axis.axisInfo.axis = nextGenericAxisId;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005400 nextGenericAxisId += 1;
5401 } else {
5402 LOGI("Ignoring joystick '%s' axis %d because all of the generic axis ids "
5403 "have already been assigned to other axes.",
5404 getDeviceName().string(), mAxes.keyAt(i));
5405 mAxes.removeItemsAt(i--);
5406 numAxes -= 1;
5407 }
5408 }
5409 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005410}
5411
Jeff Brown85297452011-03-04 13:07:49 -08005412bool JoystickInputMapper::haveAxis(int32_t axisId) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005413 size_t numAxes = mAxes.size();
5414 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005415 const Axis& axis = mAxes.valueAt(i);
5416 if (axis.axisInfo.axis == axisId
5417 || (axis.axisInfo.mode == AxisInfo::MODE_SPLIT
5418 && axis.axisInfo.highAxis == axisId)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005419 return true;
5420 }
5421 }
5422 return false;
5423}
Jeff Browncb1404e2011-01-15 18:14:15 -08005424
Jeff Brown6f2fba42011-02-19 01:08:02 -08005425void JoystickInputMapper::pruneAxes(bool ignoreExplicitlyMappedAxes) {
5426 size_t i = mAxes.size();
5427 while (mAxes.size() > PointerCoords::MAX_AXES && i-- > 0) {
5428 if (ignoreExplicitlyMappedAxes && mAxes.valueAt(i).explicitlyMapped) {
5429 continue;
5430 }
5431 LOGI("Discarding joystick '%s' axis %d because there are too many axes.",
5432 getDeviceName().string(), mAxes.keyAt(i));
5433 mAxes.removeItemsAt(i);
5434 }
5435}
5436
5437bool JoystickInputMapper::isCenteredAxis(int32_t axis) {
5438 switch (axis) {
5439 case AMOTION_EVENT_AXIS_X:
5440 case AMOTION_EVENT_AXIS_Y:
5441 case AMOTION_EVENT_AXIS_Z:
5442 case AMOTION_EVENT_AXIS_RX:
5443 case AMOTION_EVENT_AXIS_RY:
5444 case AMOTION_EVENT_AXIS_RZ:
5445 case AMOTION_EVENT_AXIS_HAT_X:
5446 case AMOTION_EVENT_AXIS_HAT_Y:
5447 case AMOTION_EVENT_AXIS_ORIENTATION:
Jeff Brown85297452011-03-04 13:07:49 -08005448 case AMOTION_EVENT_AXIS_RUDDER:
5449 case AMOTION_EVENT_AXIS_WHEEL:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005450 return true;
5451 default:
5452 return false;
5453 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005454}
5455
5456void JoystickInputMapper::reset() {
5457 // Recenter all axes.
5458 nsecs_t when = systemTime(SYSTEM_TIME_MONOTONIC);
Jeff Browncb1404e2011-01-15 18:14:15 -08005459
Jeff Brown6f2fba42011-02-19 01:08:02 -08005460 size_t numAxes = mAxes.size();
5461 for (size_t i = 0; i < numAxes; i++) {
5462 Axis& axis = mAxes.editValueAt(i);
Jeff Brown85297452011-03-04 13:07:49 -08005463 axis.resetValue();
Jeff Brown6f2fba42011-02-19 01:08:02 -08005464 }
5465
5466 sync(when, true /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005467
5468 InputMapper::reset();
5469}
5470
5471void JoystickInputMapper::process(const RawEvent* rawEvent) {
5472 switch (rawEvent->type) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005473 case EV_ABS: {
5474 ssize_t index = mAxes.indexOfKey(rawEvent->scanCode);
5475 if (index >= 0) {
5476 Axis& axis = mAxes.editValueAt(index);
Jeff Brown85297452011-03-04 13:07:49 -08005477 float newValue, highNewValue;
5478 switch (axis.axisInfo.mode) {
5479 case AxisInfo::MODE_INVERT:
5480 newValue = (axis.rawAxisInfo.maxValue - rawEvent->value)
5481 * axis.scale + axis.offset;
5482 highNewValue = 0.0f;
5483 break;
5484 case AxisInfo::MODE_SPLIT:
5485 if (rawEvent->value < axis.axisInfo.splitValue) {
5486 newValue = (axis.axisInfo.splitValue - rawEvent->value)
5487 * axis.scale + axis.offset;
5488 highNewValue = 0.0f;
5489 } else if (rawEvent->value > axis.axisInfo.splitValue) {
5490 newValue = 0.0f;
5491 highNewValue = (rawEvent->value - axis.axisInfo.splitValue)
5492 * axis.highScale + axis.highOffset;
5493 } else {
5494 newValue = 0.0f;
5495 highNewValue = 0.0f;
5496 }
5497 break;
5498 default:
5499 newValue = rawEvent->value * axis.scale + axis.offset;
5500 highNewValue = 0.0f;
5501 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005502 }
Jeff Brown85297452011-03-04 13:07:49 -08005503 axis.newValue = newValue;
5504 axis.highNewValue = highNewValue;
Jeff Browncb1404e2011-01-15 18:14:15 -08005505 }
5506 break;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005507 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005508
5509 case EV_SYN:
5510 switch (rawEvent->scanCode) {
5511 case SYN_REPORT:
Jeff Brown6f2fba42011-02-19 01:08:02 -08005512 sync(rawEvent->when, false /*force*/);
Jeff Browncb1404e2011-01-15 18:14:15 -08005513 break;
5514 }
5515 break;
5516 }
5517}
5518
Jeff Brown6f2fba42011-02-19 01:08:02 -08005519void JoystickInputMapper::sync(nsecs_t when, bool force) {
Jeff Brown85297452011-03-04 13:07:49 -08005520 if (!filterAxes(force)) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005521 return;
Jeff Browncb1404e2011-01-15 18:14:15 -08005522 }
5523
5524 int32_t metaState = mContext->getGlobalMetaState();
5525
Jeff Brown6f2fba42011-02-19 01:08:02 -08005526 PointerCoords pointerCoords;
5527 pointerCoords.clear();
5528
5529 size_t numAxes = mAxes.size();
5530 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005531 const Axis& axis = mAxes.valueAt(i);
5532 pointerCoords.setAxisValue(axis.axisInfo.axis, axis.currentValue);
5533 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5534 pointerCoords.setAxisValue(axis.axisInfo.highAxis, axis.highCurrentValue);
5535 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005536 }
5537
Jeff Brown56194eb2011-03-02 19:23:13 -08005538 // Moving a joystick axis should not wake the devide because joysticks can
5539 // be fairly noisy even when not in use. On the other hand, pushing a gamepad
5540 // button will likely wake the device.
5541 // TODO: Use the input device configuration to control this behavior more finely.
5542 uint32_t policyFlags = 0;
5543
Jeff Brown6f2fba42011-02-19 01:08:02 -08005544 int32_t pointerId = 0;
Jeff Brown56194eb2011-03-02 19:23:13 -08005545 getDispatcher()->notifyMotion(when, getDeviceId(), AINPUT_SOURCE_JOYSTICK, policyFlags,
Jeff Brown6f2fba42011-02-19 01:08:02 -08005546 AMOTION_EVENT_ACTION_MOVE, 0, metaState, AMOTION_EVENT_EDGE_FLAG_NONE,
5547 1, &pointerId, &pointerCoords, 0, 0, 0);
Jeff Browncb1404e2011-01-15 18:14:15 -08005548}
5549
Jeff Brown85297452011-03-04 13:07:49 -08005550bool JoystickInputMapper::filterAxes(bool force) {
5551 bool atLeastOneSignificantChange = force;
Jeff Brown6f2fba42011-02-19 01:08:02 -08005552 size_t numAxes = mAxes.size();
5553 for (size_t i = 0; i < numAxes; i++) {
Jeff Brown85297452011-03-04 13:07:49 -08005554 Axis& axis = mAxes.editValueAt(i);
5555 if (force || hasValueChangedSignificantly(axis.filter,
5556 axis.newValue, axis.currentValue, axis.min, axis.max)) {
5557 axis.currentValue = axis.newValue;
5558 atLeastOneSignificantChange = true;
5559 }
5560 if (axis.axisInfo.mode == AxisInfo::MODE_SPLIT) {
5561 if (force || hasValueChangedSignificantly(axis.filter,
5562 axis.highNewValue, axis.highCurrentValue, axis.min, axis.max)) {
5563 axis.highCurrentValue = axis.highNewValue;
5564 atLeastOneSignificantChange = true;
5565 }
5566 }
5567 }
5568 return atLeastOneSignificantChange;
5569}
5570
5571bool JoystickInputMapper::hasValueChangedSignificantly(
5572 float filter, float newValue, float currentValue, float min, float max) {
5573 if (newValue != currentValue) {
5574 // Filter out small changes in value unless the value is converging on the axis
5575 // bounds or center point. This is intended to reduce the amount of information
5576 // sent to applications by particularly noisy joysticks (such as PS3).
5577 if (fabs(newValue - currentValue) > filter
5578 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, min)
5579 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, max)
5580 || hasMovedNearerToValueWithinFilteredRange(filter, newValue, currentValue, 0)) {
5581 return true;
5582 }
5583 }
5584 return false;
5585}
5586
5587bool JoystickInputMapper::hasMovedNearerToValueWithinFilteredRange(
5588 float filter, float newValue, float currentValue, float thresholdValue) {
5589 float newDistance = fabs(newValue - thresholdValue);
5590 if (newDistance < filter) {
5591 float oldDistance = fabs(currentValue - thresholdValue);
5592 if (newDistance < oldDistance) {
Jeff Brown6f2fba42011-02-19 01:08:02 -08005593 return true;
5594 }
Jeff Browncb1404e2011-01-15 18:14:15 -08005595 }
Jeff Brown6f2fba42011-02-19 01:08:02 -08005596 return false;
Jeff Browncb1404e2011-01-15 18:14:15 -08005597}
5598
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07005599} // namespace android