blob: fced15cbbc91803b99e5bb377779112b6ac86cd1 [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070021
Jeff Brown5c225b12010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
32
Jeff Brown9c3cda02010-06-15 01:31:58 -070033/** Amount that trackball needs to move in order to generate a key event. */
34#define TRACKBALL_MOVEMENT_THRESHOLD 6
35
36/* Slop distance for jumpy pointer detection.
37 * The vertical range of the screen divided by this is our epsilon value. */
38#define JUMPY_EPSILON_DIVISOR 212
39
40/* Number of jumpy points to drop for touchscreens that need it. */
41#define JUMPY_TRANSITION_DROPS 3
42#define JUMPY_DROP_LIMIT 3
43
44/* Maximum squared distance for averaging.
45 * If moving farther than this, turn of averaging to avoid lag in response. */
46#define AVERAGING_DISTANCE_LIMIT (75 * 75)
47
48
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070049namespace android {
50
51// --- Static Functions ---
52
53template<typename T>
54inline static T abs(const T& value) {
55 return value < 0 ? - value : value;
56}
57
58template<typename T>
59inline static T min(const T& a, const T& b) {
60 return a < b ? a : b;
61}
62
Jeff Brown5c225b12010-06-16 01:53:36 -070063template<typename T>
64inline static void swap(T& a, T& b) {
65 T temp = a;
66 a = b;
67 b = temp;
68}
69
70
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070071int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
72 int32_t mask;
73 switch (keyCode) {
74 case KEYCODE_ALT_LEFT:
75 mask = META_ALT_LEFT_ON;
76 break;
77 case KEYCODE_ALT_RIGHT:
78 mask = META_ALT_RIGHT_ON;
79 break;
80 case KEYCODE_SHIFT_LEFT:
81 mask = META_SHIFT_LEFT_ON;
82 break;
83 case KEYCODE_SHIFT_RIGHT:
84 mask = META_SHIFT_RIGHT_ON;
85 break;
86 case KEYCODE_SYM:
87 mask = META_SYM_ON;
88 break;
89 default:
90 return oldMetaState;
91 }
92
93 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
94 & ~ (META_ALT_ON | META_SHIFT_ON);
95
96 if (newMetaState & (META_ALT_LEFT_ON | META_ALT_RIGHT_ON)) {
97 newMetaState |= META_ALT_ON;
98 }
99
100 if (newMetaState & (META_SHIFT_LEFT_ON | META_SHIFT_RIGHT_ON)) {
101 newMetaState |= META_SHIFT_ON;
102 }
103
104 return newMetaState;
105}
106
107static const int32_t keyCodeRotationMap[][4] = {
108 // key codes enumerated counter-clockwise with the original (unrotated) key first
109 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
110 { KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT },
111 { KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN },
112 { KEYCODE_DPAD_UP, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT },
113 { KEYCODE_DPAD_LEFT, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_RIGHT, KEYCODE_DPAD_UP },
114};
115static const int keyCodeRotationMapSize =
116 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
117
118int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700119 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700120 for (int i = 0; i < keyCodeRotationMapSize; i++) {
121 if (keyCode == keyCodeRotationMap[i][0]) {
122 return keyCodeRotationMap[i][orientation];
123 }
124 }
125 }
126 return keyCode;
127}
128
129
130// --- InputDevice ---
131
132InputDevice::InputDevice(int32_t id, uint32_t classes, String8 name) :
133 id(id), classes(classes), name(name), ignored(false) {
134}
135
136void InputDevice::reset() {
137 if (isKeyboard()) {
138 keyboard.reset();
139 }
140
141 if (isTrackball()) {
142 trackball.reset();
143 }
144
145 if (isMultiTouchScreen()) {
146 multiTouchScreen.reset();
147 } else if (isSingleTouchScreen()) {
148 singleTouchScreen.reset();
149 }
150
151 if (isTouchScreen()) {
152 touchScreen.reset();
153 }
154}
155
156
157// --- InputDevice::TouchData ---
158
159void InputDevice::TouchData::copyFrom(const TouchData& other) {
160 pointerCount = other.pointerCount;
161 idBits = other.idBits;
162
163 for (uint32_t i = 0; i < pointerCount; i++) {
164 pointers[i] = other.pointers[i];
165 idToIndex[i] = other.idToIndex[i];
166 }
167}
168
169
170// --- InputDevice::KeyboardState ---
171
172void InputDevice::KeyboardState::reset() {
173 current.metaState = META_NONE;
174 current.downTime = 0;
175}
176
177
178// --- InputDevice::TrackballState ---
179
180void InputDevice::TrackballState::reset() {
181 accumulator.clear();
182 current.down = false;
183 current.downTime = 0;
184}
185
186
187// --- InputDevice::TouchScreenState ---
188
189void InputDevice::TouchScreenState::reset() {
190 lastTouch.clear();
191 downTime = 0;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700192 currentVirtualKey.status = CurrentVirtualKeyState::STATUS_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700193
194 for (uint32_t i = 0; i < MAX_POINTERS; i++) {
195 averagingTouchFilter.historyStart[i] = 0;
196 averagingTouchFilter.historyEnd[i] = 0;
197 }
198
199 jumpyTouchFilter.jumpyPointsDropped = 0;
200}
201
Jeff Brown5c225b12010-06-16 01:53:36 -0700202struct PointerDistanceHeapElement {
203 uint32_t currentPointerIndex : 8;
204 uint32_t lastPointerIndex : 8;
205 uint64_t distance : 48; // squared distance
206};
207
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700208void InputDevice::TouchScreenState::calculatePointerIds() {
209 uint32_t currentPointerCount = currentTouch.pointerCount;
210 uint32_t lastPointerCount = lastTouch.pointerCount;
211
212 if (currentPointerCount == 0) {
213 // No pointers to assign.
214 currentTouch.idBits.clear();
215 } else if (lastPointerCount == 0) {
216 // All pointers are new.
217 currentTouch.idBits.clear();
218 for (uint32_t i = 0; i < currentPointerCount; i++) {
219 currentTouch.pointers[i].id = i;
220 currentTouch.idToIndex[i] = i;
221 currentTouch.idBits.markBit(i);
222 }
223 } else if (currentPointerCount == 1 && lastPointerCount == 1) {
224 // Only one pointer and no change in count so it must have the same id as before.
225 uint32_t id = lastTouch.pointers[0].id;
226 currentTouch.pointers[0].id = id;
227 currentTouch.idToIndex[id] = 0;
228 currentTouch.idBits.value = BitSet32::valueForBit(id);
229 } else {
230 // General case.
231 // We build a heap of squared euclidean distances between current and last pointers
232 // associated with the current and last pointer indices. Then, we find the best
233 // match (by distance) for each current pointer.
Jeff Brown5c225b12010-06-16 01:53:36 -0700234 PointerDistanceHeapElement heap[MAX_POINTERS * MAX_POINTERS];
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700235
236 uint32_t heapSize = 0;
237 for (uint32_t currentPointerIndex = 0; currentPointerIndex < currentPointerCount;
238 currentPointerIndex++) {
239 for (uint32_t lastPointerIndex = 0; lastPointerIndex < lastPointerCount;
240 lastPointerIndex++) {
241 int64_t deltaX = currentTouch.pointers[currentPointerIndex].x
242 - lastTouch.pointers[lastPointerIndex].x;
243 int64_t deltaY = currentTouch.pointers[currentPointerIndex].y
244 - lastTouch.pointers[lastPointerIndex].y;
245
246 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
247
248 // Insert new element into the heap (sift up).
Jeff Brown5c225b12010-06-16 01:53:36 -0700249 heap[heapSize].currentPointerIndex = currentPointerIndex;
250 heap[heapSize].lastPointerIndex = lastPointerIndex;
251 heap[heapSize].distance = distance;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700252 heapSize += 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700253 }
254 }
255
Jeff Brown5c225b12010-06-16 01:53:36 -0700256 // Heapify
257 for (uint32_t startIndex = heapSize / 2; startIndex != 0; ) {
258 startIndex -= 1;
259 for (uint32_t parentIndex = startIndex; ;) {
260 uint32_t childIndex = parentIndex * 2 + 1;
261 if (childIndex >= heapSize) {
262 break;
263 }
264
265 if (childIndex + 1 < heapSize
266 && heap[childIndex + 1].distance < heap[childIndex].distance) {
267 childIndex += 1;
268 }
269
270 if (heap[parentIndex].distance <= heap[childIndex].distance) {
271 break;
272 }
273
274 swap(heap[parentIndex], heap[childIndex]);
275 parentIndex = childIndex;
276 }
277 }
278
279#if DEBUG_POINTER_ASSIGNMENT
280 LOGD("calculatePointerIds - initial distance min-heap: size=%d", heapSize);
281 for (size_t i = 0; i < heapSize; i++) {
282 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
283 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
284 heap[i].distance);
285 }
286#endif
287
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700288 // Pull matches out by increasing order of distance.
289 // To avoid reassigning pointers that have already been matched, the loop keeps track
290 // of which last and current pointers have been matched using the matchedXXXBits variables.
291 // It also tracks the used pointer id bits.
292 BitSet32 matchedLastBits(0);
293 BitSet32 matchedCurrentBits(0);
294 BitSet32 usedIdBits(0);
295 bool first = true;
296 for (uint32_t i = min(currentPointerCount, lastPointerCount); i > 0; i--) {
297 for (;;) {
298 if (first) {
299 // The first time through the loop, we just consume the root element of
Jeff Brown5c225b12010-06-16 01:53:36 -0700300 // the heap (the one with smallest distance).
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700301 first = false;
302 } else {
303 // Previous iterations consumed the root element of the heap.
304 // Pop root element off of the heap (sift down).
305 heapSize -= 1;
306 assert(heapSize > 0);
307
Jeff Brown5c225b12010-06-16 01:53:36 -0700308 // Sift down.
309 heap[0] = heap[heapSize];
310 for (uint32_t parentIndex = 0; ;) {
311 uint32_t childIndex = parentIndex * 2 + 1;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700312 if (childIndex >= heapSize) {
313 break;
314 }
315
316 if (childIndex + 1 < heapSize
317 && heap[childIndex + 1].distance < heap[childIndex].distance) {
318 childIndex += 1;
319 }
320
Jeff Brown5c225b12010-06-16 01:53:36 -0700321 if (heap[parentIndex].distance <= heap[childIndex].distance) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700322 break;
323 }
324
Jeff Brown5c225b12010-06-16 01:53:36 -0700325 swap(heap[parentIndex], heap[childIndex]);
326 parentIndex = childIndex;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700327 }
Jeff Brown5c225b12010-06-16 01:53:36 -0700328
329#if DEBUG_POINTER_ASSIGNMENT
330 LOGD("calculatePointerIds - reduced distance min-heap: size=%d", heapSize);
331 for (size_t i = 0; i < heapSize; i++) {
332 LOGD(" heap[%d]: cur=%d, last=%d, distance=%lld",
333 i, heap[i].currentPointerIndex, heap[i].lastPointerIndex,
334 heap[i].distance);
335 }
336#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700337 }
338
339 uint32_t currentPointerIndex = heap[0].currentPointerIndex;
340 if (matchedCurrentBits.hasBit(currentPointerIndex)) continue; // already matched
341
342 uint32_t lastPointerIndex = heap[0].lastPointerIndex;
343 if (matchedLastBits.hasBit(lastPointerIndex)) continue; // already matched
344
345 matchedCurrentBits.markBit(currentPointerIndex);
346 matchedLastBits.markBit(lastPointerIndex);
347
348 uint32_t id = lastTouch.pointers[lastPointerIndex].id;
349 currentTouch.pointers[currentPointerIndex].id = id;
350 currentTouch.idToIndex[id] = currentPointerIndex;
351 usedIdBits.markBit(id);
Jeff Brown5c225b12010-06-16 01:53:36 -0700352
353#if DEBUG_POINTER_ASSIGNMENT
354 LOGD("calculatePointerIds - matched: cur=%d, last=%d, id=%d, distance=%lld",
355 lastPointerIndex, currentPointerIndex, id, heap[0].distance);
356#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700357 break;
358 }
359 }
360
361 // Assign fresh ids to new pointers.
362 if (currentPointerCount > lastPointerCount) {
363 for (uint32_t i = currentPointerCount - lastPointerCount; ;) {
364 uint32_t currentPointerIndex = matchedCurrentBits.firstUnmarkedBit();
365 uint32_t id = usedIdBits.firstUnmarkedBit();
366
367 currentTouch.pointers[currentPointerIndex].id = id;
368 currentTouch.idToIndex[id] = currentPointerIndex;
369 usedIdBits.markBit(id);
370
Jeff Brown5c225b12010-06-16 01:53:36 -0700371#if DEBUG_POINTER_ASSIGNMENT
372 LOGD("calculatePointerIds - assigned: cur=%d, id=%d",
373 currentPointerIndex, id);
374#endif
375
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700376 if (--i == 0) break; // done
377 matchedCurrentBits.markBit(currentPointerIndex);
378 }
379 }
380
381 // Fix id bits.
382 currentTouch.idBits = usedIdBits;
383 }
384}
385
386/* Special hack for devices that have bad screen data: if one of the
387 * points has moved more than a screen height from the last position,
388 * then drop it. */
389bool InputDevice::TouchScreenState::applyBadTouchFilter() {
Jeff Brown0b72e822010-06-29 16:52:21 -0700390 // This hack requires valid axis parameters.
391 if (! parameters.yAxis.valid) {
392 return false;
393 }
394
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700395 uint32_t pointerCount = currentTouch.pointerCount;
396
397 // Nothing to do if there are no points.
398 if (pointerCount == 0) {
399 return false;
400 }
401
402 // Don't do anything if a finger is going down or up. We run
403 // here before assigning pointer IDs, so there isn't a good
404 // way to do per-finger matching.
405 if (pointerCount != lastTouch.pointerCount) {
406 return false;
407 }
408
409 // We consider a single movement across more than a 7/16 of
410 // the long size of the screen to be bad. This was a magic value
411 // determined by looking at the maximum distance it is feasible
412 // to actually move in one sample.
413 int32_t maxDeltaY = parameters.yAxis.range * 7 / 16;
414
415 // XXX The original code in InputDevice.java included commented out
416 // code for testing the X axis. Note that when we drop a point
417 // we don't actually restore the old X either. Strange.
418 // The old code also tries to track when bad points were previously
419 // detected but it turns out that due to the placement of a "break"
420 // at the end of the loop, we never set mDroppedBadPoint to true
421 // so it is effectively dead code.
422 // Need to figure out if the old code is busted or just overcomplicated
423 // but working as intended.
424
425 // Look through all new points and see if any are farther than
426 // acceptable from all previous points.
427 for (uint32_t i = pointerCount; i-- > 0; ) {
428 int32_t y = currentTouch.pointers[i].y;
429 int32_t closestY = INT_MAX;
430 int32_t closestDeltaY = 0;
431
432#if DEBUG_HACKS
433 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
434#endif
435
436 for (uint32_t j = pointerCount; j-- > 0; ) {
437 int32_t lastY = lastTouch.pointers[j].y;
438 int32_t deltaY = abs(y - lastY);
439
440#if DEBUG_HACKS
441 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
442 j, lastY, deltaY);
443#endif
444
445 if (deltaY < maxDeltaY) {
446 goto SkipSufficientlyClosePoint;
447 }
448 if (deltaY < closestDeltaY) {
449 closestDeltaY = deltaY;
450 closestY = lastY;
451 }
452 }
453
454 // Must not have found a close enough match.
455#if DEBUG_HACKS
456 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
457 i, y, closestY, closestDeltaY, maxDeltaY);
458#endif
459
460 currentTouch.pointers[i].y = closestY;
461 return true; // XXX original code only corrects one point
462
463 SkipSufficientlyClosePoint: ;
464 }
465
466 // No change.
467 return false;
468}
469
470/* Special hack for devices that have bad screen data: drop points where
471 * the coordinate value for one axis has jumped to the other pointer's location.
472 */
473bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
Jeff Brown0b72e822010-06-29 16:52:21 -0700474 // This hack requires valid axis parameters.
475 if (! parameters.yAxis.valid) {
476 return false;
477 }
478
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700479 uint32_t pointerCount = currentTouch.pointerCount;
480 if (lastTouch.pointerCount != pointerCount) {
481#if DEBUG_HACKS
482 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
483 lastTouch.pointerCount, pointerCount);
484 for (uint32_t i = 0; i < pointerCount; i++) {
485 LOGD(" Pointer %d (%d, %d)", i,
486 currentTouch.pointers[i].x, currentTouch.pointers[i].y);
487 }
488#endif
489
490 if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
491 if (lastTouch.pointerCount == 1 && pointerCount == 2) {
492 // Just drop the first few events going from 1 to 2 pointers.
493 // They're bad often enough that they're not worth considering.
494 currentTouch.pointerCount = 1;
495 jumpyTouchFilter.jumpyPointsDropped += 1;
496
497#if DEBUG_HACKS
498 LOGD("JumpyTouchFilter: Pointer 2 dropped");
499#endif
500 return true;
501 } else if (lastTouch.pointerCount == 2 && pointerCount == 1) {
502 // The event when we go from 2 -> 1 tends to be messed up too
503 currentTouch.pointerCount = 2;
504 currentTouch.pointers[0] = lastTouch.pointers[0];
505 currentTouch.pointers[1] = lastTouch.pointers[1];
506 jumpyTouchFilter.jumpyPointsDropped += 1;
507
508#if DEBUG_HACKS
509 for (int32_t i = 0; i < 2; i++) {
510 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
511 currentTouch.pointers[i].x, currentTouch.pointers[i].y);
512 }
513#endif
514 return true;
515 }
516 }
517 // Reset jumpy points dropped on other transitions or if limit exceeded.
518 jumpyTouchFilter.jumpyPointsDropped = 0;
519
520#if DEBUG_HACKS
521 LOGD("JumpyTouchFilter: Transition - drop limit reset");
522#endif
523 return false;
524 }
525
526 // We have the same number of pointers as last time.
527 // A 'jumpy' point is one where the coordinate value for one axis
528 // has jumped to the other pointer's location. No need to do anything
529 // else if we only have one pointer.
530 if (pointerCount < 2) {
531 return false;
532 }
533
534 if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
535 int jumpyEpsilon = parameters.yAxis.range / JUMPY_EPSILON_DIVISOR;
536
537 // We only replace the single worst jumpy point as characterized by pointer distance
538 // in a single axis.
539 int32_t badPointerIndex = -1;
540 int32_t badPointerReplacementIndex = -1;
541 int32_t badPointerDistance = INT_MIN; // distance to be corrected
542
543 for (uint32_t i = pointerCount; i-- > 0; ) {
544 int32_t x = currentTouch.pointers[i].x;
545 int32_t y = currentTouch.pointers[i].y;
546
547#if DEBUG_HACKS
548 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
549#endif
550
551 // Check if a touch point is too close to another's coordinates
552 bool dropX = false, dropY = false;
553 for (uint32_t j = 0; j < pointerCount; j++) {
554 if (i == j) {
555 continue;
556 }
557
558 if (abs(x - currentTouch.pointers[j].x) <= jumpyEpsilon) {
559 dropX = true;
560 break;
561 }
562
563 if (abs(y - currentTouch.pointers[j].y) <= jumpyEpsilon) {
564 dropY = true;
565 break;
566 }
567 }
568 if (! dropX && ! dropY) {
569 continue; // not jumpy
570 }
571
572 // Find a replacement candidate by comparing with older points on the
573 // complementary (non-jumpy) axis.
574 int32_t distance = INT_MIN; // distance to be corrected
575 int32_t replacementIndex = -1;
576
577 if (dropX) {
578 // X looks too close. Find an older replacement point with a close Y.
579 int32_t smallestDeltaY = INT_MAX;
580 for (uint32_t j = 0; j < pointerCount; j++) {
581 int32_t deltaY = abs(y - lastTouch.pointers[j].y);
582 if (deltaY < smallestDeltaY) {
583 smallestDeltaY = deltaY;
584 replacementIndex = j;
585 }
586 }
587 distance = abs(x - lastTouch.pointers[replacementIndex].x);
588 } else {
589 // Y looks too close. Find an older replacement point with a close X.
590 int32_t smallestDeltaX = INT_MAX;
591 for (uint32_t j = 0; j < pointerCount; j++) {
592 int32_t deltaX = abs(x - lastTouch.pointers[j].x);
593 if (deltaX < smallestDeltaX) {
594 smallestDeltaX = deltaX;
595 replacementIndex = j;
596 }
597 }
598 distance = abs(y - lastTouch.pointers[replacementIndex].y);
599 }
600
601 // If replacing this pointer would correct a worse error than the previous ones
602 // considered, then use this replacement instead.
603 if (distance > badPointerDistance) {
604 badPointerIndex = i;
605 badPointerReplacementIndex = replacementIndex;
606 badPointerDistance = distance;
607 }
608 }
609
610 // Correct the jumpy pointer if one was found.
611 if (badPointerIndex >= 0) {
612#if DEBUG_HACKS
613 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
614 badPointerIndex,
615 lastTouch.pointers[badPointerReplacementIndex].x,
616 lastTouch.pointers[badPointerReplacementIndex].y);
617#endif
618
619 currentTouch.pointers[badPointerIndex].x =
620 lastTouch.pointers[badPointerReplacementIndex].x;
621 currentTouch.pointers[badPointerIndex].y =
622 lastTouch.pointers[badPointerReplacementIndex].y;
623 jumpyTouchFilter.jumpyPointsDropped += 1;
624 return true;
625 }
626 }
627
628 jumpyTouchFilter.jumpyPointsDropped = 0;
629 return false;
630}
631
632/* Special hack for devices that have bad screen data: aggregate and
633 * compute averages of the coordinate data, to reduce the amount of
634 * jitter seen by applications. */
635void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
636 for (uint32_t currentIndex = 0; currentIndex < currentTouch.pointerCount; currentIndex++) {
637 uint32_t id = currentTouch.pointers[currentIndex].id;
638 int32_t x = currentTouch.pointers[currentIndex].x;
639 int32_t y = currentTouch.pointers[currentIndex].y;
640 int32_t pressure = currentTouch.pointers[currentIndex].pressure;
641
642 if (lastTouch.idBits.hasBit(id)) {
Jeff Brown349703e2010-06-22 01:27:15 -0700643 // Pointer was down before and is still down now.
644 // Compute average over history trace.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700645 uint32_t start = averagingTouchFilter.historyStart[id];
646 uint32_t end = averagingTouchFilter.historyEnd[id];
647
648 int64_t deltaX = x - averagingTouchFilter.historyData[end].pointers[id].x;
649 int64_t deltaY = y - averagingTouchFilter.historyData[end].pointers[id].y;
650 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
651
652#if DEBUG_HACKS
653 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
654 id, distance);
655#endif
656
657 if (distance < AVERAGING_DISTANCE_LIMIT) {
Jeff Brown349703e2010-06-22 01:27:15 -0700658 // Increment end index in preparation for recording new historical data.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700659 end += 1;
660 if (end > AVERAGING_HISTORY_SIZE) {
661 end = 0;
662 }
663
Jeff Brown349703e2010-06-22 01:27:15 -0700664 // If the end index has looped back to the start index then we have filled
665 // the historical trace up to the desired size so we drop the historical
666 // data at the start of the trace.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700667 if (end == start) {
668 start += 1;
669 if (start > AVERAGING_HISTORY_SIZE) {
670 start = 0;
671 }
672 }
673
Jeff Brown349703e2010-06-22 01:27:15 -0700674 // Add the raw data to the historical trace.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700675 averagingTouchFilter.historyStart[id] = start;
676 averagingTouchFilter.historyEnd[id] = end;
677 averagingTouchFilter.historyData[end].pointers[id].x = x;
678 averagingTouchFilter.historyData[end].pointers[id].y = y;
679 averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
680
Jeff Brown349703e2010-06-22 01:27:15 -0700681 // Average over all historical positions in the trace by total pressure.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700682 int32_t averagedX = 0;
683 int32_t averagedY = 0;
684 int32_t totalPressure = 0;
685 for (;;) {
686 int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
Jeff Brown349703e2010-06-22 01:27:15 -0700687 int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700688 int32_t historicalPressure = averagingTouchFilter.historyData[start]
689 .pointers[id].pressure;
690
Jeff Brown349703e2010-06-22 01:27:15 -0700691 averagedX += historicalX * historicalPressure;
692 averagedY += historicalY * historicalPressure;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700693 totalPressure += historicalPressure;
694
695 if (start == end) {
696 break;
697 }
698
699 start += 1;
700 if (start > AVERAGING_HISTORY_SIZE) {
701 start = 0;
702 }
703 }
704
705 averagedX /= totalPressure;
706 averagedY /= totalPressure;
707
708#if DEBUG_HACKS
709 LOGD("AveragingTouchFilter: Pointer id %d - "
710 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
711 averagedX, averagedY);
712#endif
713
714 currentTouch.pointers[currentIndex].x = averagedX;
715 currentTouch.pointers[currentIndex].y = averagedY;
716 } else {
717#if DEBUG_HACKS
718 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
719#endif
720 }
721 } else {
722#if DEBUG_HACKS
723 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
724#endif
725 }
726
727 // Reset pointer history.
728 averagingTouchFilter.historyStart[id] = 0;
729 averagingTouchFilter.historyEnd[id] = 0;
730 averagingTouchFilter.historyData[0].pointers[id].x = x;
731 averagingTouchFilter.historyData[0].pointers[id].y = y;
732 averagingTouchFilter.historyData[0].pointers[id].pressure = pressure;
733 }
734}
735
736bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
Jeff Brown0b72e822010-06-29 16:52:21 -0700737 if (! parameters.xAxis.valid || ! parameters.yAxis.valid) {
738 // Assume all points on a touch screen without valid axis parameters are
739 // inside the display.
740 return true;
741 }
742
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700743 return x >= parameters.xAxis.minValue
744 && x <= parameters.xAxis.maxValue
745 && y >= parameters.yAxis.minValue
746 && y <= parameters.yAxis.maxValue;
747}
748
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700749const InputDevice::VirtualKey* InputDevice::TouchScreenState::findVirtualKeyHit() const {
750 int32_t x = currentTouch.pointers[0].x;
751 int32_t y = currentTouch.pointers[0].y;
752 for (size_t i = 0; i < virtualKeys.size(); i++) {
753 const InputDevice::VirtualKey& virtualKey = virtualKeys[i];
754
755#if DEBUG_VIRTUAL_KEYS
756 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
757 "left=%d, top=%d, right=%d, bottom=%d",
758 x, y,
759 virtualKey.keyCode, virtualKey.scanCode,
760 virtualKey.hitLeft, virtualKey.hitTop,
761 virtualKey.hitRight, virtualKey.hitBottom);
762#endif
763
764 if (virtualKey.isHit(x, y)) {
765 return & virtualKey;
766 }
767 }
768
769 return NULL;
770}
771
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700772
773// --- InputDevice::SingleTouchScreenState ---
774
775void InputDevice::SingleTouchScreenState::reset() {
776 accumulator.clear();
777 current.down = false;
778 current.x = 0;
779 current.y = 0;
780 current.pressure = 0;
781 current.size = 0;
782}
783
784
785// --- InputDevice::MultiTouchScreenState ---
786
787void InputDevice::MultiTouchScreenState::reset() {
788 accumulator.clear();
789}
790
791
792// --- InputReader ---
793
794InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700795 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700796 const sp<InputDispatcherInterface>& dispatcher) :
797 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700798 configureExcludedDevices();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700799 resetGlobalMetaState();
800 resetDisplayProperties();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700801 updateExportedVirtualKeyState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700802}
803
804InputReader::~InputReader() {
805 for (size_t i = 0; i < mDevices.size(); i++) {
806 delete mDevices.valueAt(i);
807 }
808}
809
810void InputReader::loopOnce() {
811 RawEvent rawEvent;
812 mEventHub->getEvent(& rawEvent.deviceId, & rawEvent.type, & rawEvent.scanCode,
813 & rawEvent.keyCode, & rawEvent.flags, & rawEvent.value, & rawEvent.when);
814
815 // Replace the event timestamp so it is in same timebase as java.lang.System.nanoTime()
816 // and android.os.SystemClock.uptimeMillis() as expected by the rest of the system.
817 rawEvent.when = systemTime(SYSTEM_TIME_MONOTONIC);
818
819#if DEBUG_RAW_EVENTS
820 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
821 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
822 rawEvent.value);
823#endif
824
825 process(& rawEvent);
826}
827
828void InputReader::process(const RawEvent* rawEvent) {
829 switch (rawEvent->type) {
830 case EventHubInterface::DEVICE_ADDED:
831 handleDeviceAdded(rawEvent);
832 break;
833
834 case EventHubInterface::DEVICE_REMOVED:
835 handleDeviceRemoved(rawEvent);
836 break;
837
838 case EV_SYN:
839 handleSync(rawEvent);
840 break;
841
842 case EV_KEY:
843 handleKey(rawEvent);
844 break;
845
846 case EV_REL:
847 handleRelativeMotion(rawEvent);
848 break;
849
850 case EV_ABS:
851 handleAbsoluteMotion(rawEvent);
852 break;
853
854 case EV_SW:
855 handleSwitch(rawEvent);
856 break;
857 }
858}
859
860void InputReader::handleDeviceAdded(const RawEvent* rawEvent) {
861 InputDevice* device = getDevice(rawEvent->deviceId);
862 if (device) {
863 LOGW("Ignoring spurious device added event for deviceId %d.", rawEvent->deviceId);
864 return;
865 }
866
867 addDevice(rawEvent->when, rawEvent->deviceId);
868}
869
870void InputReader::handleDeviceRemoved(const RawEvent* rawEvent) {
871 InputDevice* device = getDevice(rawEvent->deviceId);
872 if (! device) {
873 LOGW("Ignoring spurious device removed event for deviceId %d.", rawEvent->deviceId);
874 return;
875 }
876
877 removeDevice(rawEvent->when, device);
878}
879
880void InputReader::handleSync(const RawEvent* rawEvent) {
881 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
882 if (! device) return;
883
884 if (rawEvent->scanCode == SYN_MT_REPORT) {
885 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
886 // We drop pointers with pressure <= 0 since that indicates they are not down.
887 if (device->isMultiTouchScreen()) {
888 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
889
890 if (device->multiTouchScreen.accumulator.pointers[pointerIndex].fields) {
891 if (pointerIndex == MAX_POINTERS) {
892 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
893 MAX_POINTERS);
894 } else {
895 pointerIndex += 1;
896 device->multiTouchScreen.accumulator.pointerCount = pointerIndex;
897 }
898 }
899
900 device->multiTouchScreen.accumulator.pointers[pointerIndex].clear();
901 }
902 } else if (rawEvent->scanCode == SYN_REPORT) {
903 // General Sync: The driver has returned all data for the current event update.
904 if (device->isMultiTouchScreen()) {
905 if (device->multiTouchScreen.accumulator.isDirty()) {
906 onMultiTouchScreenStateChanged(rawEvent->when, device);
907 device->multiTouchScreen.accumulator.clear();
908 }
909 } else if (device->isSingleTouchScreen()) {
910 if (device->singleTouchScreen.accumulator.isDirty()) {
911 onSingleTouchScreenStateChanged(rawEvent->when, device);
912 device->singleTouchScreen.accumulator.clear();
913 }
914 }
915
916 if (device->trackball.accumulator.isDirty()) {
917 onTrackballStateChanged(rawEvent->when, device);
918 device->trackball.accumulator.clear();
919 }
920 }
921}
922
923void InputReader::handleKey(const RawEvent* rawEvent) {
924 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
925 if (! device) return;
926
927 bool down = rawEvent->value != 0;
928 int32_t scanCode = rawEvent->scanCode;
929
930 if (device->isKeyboard() && (scanCode < BTN_FIRST || scanCode > BTN_LAST)) {
931 int32_t keyCode = rawEvent->keyCode;
932 onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
933 } else if (device->isSingleTouchScreen()) {
934 switch (rawEvent->scanCode) {
935 case BTN_TOUCH:
936 device->singleTouchScreen.accumulator.fields |=
937 InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
938 device->singleTouchScreen.accumulator.btnTouch = down;
939 break;
940 }
941 } else if (device->isTrackball()) {
942 switch (rawEvent->scanCode) {
943 case BTN_MOUSE:
944 device->trackball.accumulator.fields |=
945 InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
946 device->trackball.accumulator.btnMouse = down;
947
948 // send the down immediately
949 // XXX this emulates the old behavior of KeyInputQueue, unclear whether it is
950 // necessary or if we can wait until the next sync
951 onTrackballStateChanged(rawEvent->when, device);
952 device->trackball.accumulator.clear();
953 break;
954 }
955 }
956}
957
958void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
959 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
960 if (! device) return;
961
962 if (device->isTrackball()) {
963 switch (rawEvent->scanCode) {
964 case REL_X:
965 device->trackball.accumulator.fields |=
966 InputDevice::TrackballState::Accumulator::FIELD_REL_X;
967 device->trackball.accumulator.relX = rawEvent->value;
968 break;
969 case REL_Y:
970 device->trackball.accumulator.fields |=
971 InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
972 device->trackball.accumulator.relY = rawEvent->value;
973 break;
974 }
975 }
976}
977
978void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
979 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
980 if (! device) return;
981
982 if (device->isMultiTouchScreen()) {
983 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
984 InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
985 & device->multiTouchScreen.accumulator.pointers[pointerIndex];
986
987 switch (rawEvent->scanCode) {
988 case ABS_MT_POSITION_X:
989 pointer->fields |=
990 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
991 pointer->absMTPositionX = rawEvent->value;
992 break;
993 case ABS_MT_POSITION_Y:
994 pointer->fields |=
995 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
996 pointer->absMTPositionY = rawEvent->value;
997 break;
998 case ABS_MT_TOUCH_MAJOR:
999 pointer->fields |=
1000 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
1001 pointer->absMTTouchMajor = rawEvent->value;
1002 break;
1003 case ABS_MT_WIDTH_MAJOR:
1004 pointer->fields |=
1005 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
1006 pointer->absMTWidthMajor = rawEvent->value;
1007 break;
1008 case ABS_MT_TRACKING_ID:
1009 pointer->fields |=
1010 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
1011 pointer->absMTTrackingId = rawEvent->value;
1012 break;
1013 }
1014 } else if (device->isSingleTouchScreen()) {
1015 switch (rawEvent->scanCode) {
1016 case ABS_X:
1017 device->singleTouchScreen.accumulator.fields |=
1018 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
1019 device->singleTouchScreen.accumulator.absX = rawEvent->value;
1020 break;
1021 case ABS_Y:
1022 device->singleTouchScreen.accumulator.fields |=
1023 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
1024 device->singleTouchScreen.accumulator.absY = rawEvent->value;
1025 break;
1026 case ABS_PRESSURE:
1027 device->singleTouchScreen.accumulator.fields |=
1028 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
1029 device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
1030 break;
1031 case ABS_TOOL_WIDTH:
1032 device->singleTouchScreen.accumulator.fields |=
1033 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
1034 device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
1035 break;
1036 }
1037 }
1038}
1039
1040void InputReader::handleSwitch(const RawEvent* rawEvent) {
1041 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
1042 if (! device) return;
1043
Jeff Brown9c3cda02010-06-15 01:31:58 -07001044 onSwitch(rawEvent->when, device, rawEvent->scanCode, rawEvent->value);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001045}
1046
1047void InputReader::onKey(nsecs_t when, InputDevice* device,
1048 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
1049 /* Refresh display properties so we can rotate key codes according to display orientation */
1050
1051 if (! refreshDisplayProperties()) {
1052 return;
1053 }
1054
1055 /* Update device state */
1056
1057 int32_t oldMetaState = device->keyboard.current.metaState;
1058 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
1059 if (oldMetaState != newMetaState) {
1060 device->keyboard.current.metaState = newMetaState;
1061 resetGlobalMetaState();
1062 }
1063
1064 // FIXME if we send a down event about a rotated key press we should ensure that we send
1065 // a corresponding up event about the rotated key press even if the orientation
1066 // has changed in the meantime
1067 keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
1068
1069 if (down) {
1070 device->keyboard.current.downTime = when;
1071 }
1072
1073 /* Apply policy */
1074
1075 int32_t policyActions = mPolicy->interceptKey(when, device->id,
1076 down, keyCode, scanCode, policyFlags);
1077
1078 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1079 return; // event dropped
1080 }
1081
1082 /* Enqueue key event for dispatch */
1083
1084 int32_t keyEventAction;
1085 if (down) {
1086 device->keyboard.current.downTime = when;
1087 keyEventAction = KEY_EVENT_ACTION_DOWN;
1088 } else {
1089 keyEventAction = KEY_EVENT_ACTION_UP;
1090 }
1091
1092 int32_t keyEventFlags = KEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001093 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001094 keyEventFlags = keyEventFlags | KEY_EVENT_FLAG_WOKE_HERE;
1095 }
1096
1097 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
1098 keyEventAction, keyEventFlags, keyCode, scanCode,
1099 device->keyboard.current.metaState,
1100 device->keyboard.current.downTime);
1101}
1102
Jeff Brown9c3cda02010-06-15 01:31:58 -07001103void InputReader::onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode,
1104 int32_t switchValue) {
1105 int32_t policyActions = mPolicy->interceptSwitch(when, switchCode, switchValue);
1106
1107 uint32_t policyFlags = 0;
1108 applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001109}
1110
1111void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
1112 InputDevice* device) {
1113 static const uint32_t REQUIRED_FIELDS =
1114 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
1115 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
1116 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
1117 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
1118
1119 /* Refresh display properties so we can map touch screen coords into display coords */
1120
1121 if (! refreshDisplayProperties()) {
1122 return;
1123 }
1124
1125 /* Update device state */
1126
1127 InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
1128 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
1129
1130 uint32_t inCount = in->accumulator.pointerCount;
1131 uint32_t outCount = 0;
1132 bool havePointerIds = true;
1133
1134 out->clear();
1135
1136 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
1137 uint32_t fields = in->accumulator.pointers[inIndex].fields;
1138
1139 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
1140#if DEBUG_POINTERS
1141 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
1142 inIndex, fields);
1143 continue;
1144#endif
1145 }
1146
1147 if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
1148 // Pointer is not down. Drop it.
1149 continue;
1150 }
1151
1152 // FIXME assignment of pressure may be incorrect, probably better to let
1153 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
1154 // isn't quite right either. Should be using touch for that.
1155 out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
1156 out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
1157 out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
1158 out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
1159
1160 if (havePointerIds) {
1161 if (fields & InputDevice::MultiTouchScreenState::Accumulator::
1162 FIELD_ABS_MT_TRACKING_ID) {
1163 uint32_t id = uint32_t(in->accumulator.pointers[inIndex].absMTTrackingId);
1164
1165 if (id > MAX_POINTER_ID) {
1166#if DEBUG_POINTERS
1167 LOGD("Pointers: Ignoring driver provided pointer id %d because "
1168 "it is larger than max supported id %d for optimizations",
1169 id, MAX_POINTER_ID);
1170#endif
1171 havePointerIds = false;
1172 }
1173 else {
1174 out->pointers[outCount].id = id;
1175 out->idToIndex[id] = outCount;
1176 out->idBits.markBit(id);
1177 }
1178 } else {
1179 havePointerIds = false;
1180 }
1181 }
1182
1183 outCount += 1;
1184 }
1185
1186 out->pointerCount = outCount;
1187
1188 onTouchScreenChanged(when, device, havePointerIds);
1189}
1190
1191void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
1192 InputDevice* device) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001193 /* Refresh display properties so we can map touch screen coords into display coords */
1194
1195 if (! refreshDisplayProperties()) {
1196 return;
1197 }
1198
1199 /* Update device state */
1200
1201 InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
1202 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
1203
1204 uint32_t fields = in->accumulator.fields;
1205
1206 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
1207 in->current.down = in->accumulator.btnTouch;
1208 }
1209
Jeff Brown349703e2010-06-22 01:27:15 -07001210 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001211 in->current.x = in->accumulator.absX;
Jeff Brown349703e2010-06-22 01:27:15 -07001212 }
1213
1214 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001215 in->current.y = in->accumulator.absY;
Jeff Brown349703e2010-06-22 01:27:15 -07001216 }
1217
1218 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001219 in->current.pressure = in->accumulator.absPressure;
Jeff Brown349703e2010-06-22 01:27:15 -07001220 }
1221
1222 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001223 in->current.size = in->accumulator.absToolWidth;
1224 }
1225
1226 out->clear();
1227
1228 if (in->current.down) {
1229 out->pointerCount = 1;
1230 out->pointers[0].id = 0;
1231 out->pointers[0].x = in->current.x;
1232 out->pointers[0].y = in->current.y;
1233 out->pointers[0].pressure = in->current.pressure;
1234 out->pointers[0].size = in->current.size;
1235 out->idToIndex[0] = 0;
1236 out->idBits.markBit(0);
1237 }
1238
1239 onTouchScreenChanged(when, device, true);
1240}
1241
1242void InputReader::onTouchScreenChanged(nsecs_t when,
1243 InputDevice* device, bool havePointerIds) {
1244 /* Apply policy */
1245
1246 int32_t policyActions = mPolicy->interceptTouch(when);
1247
1248 uint32_t policyFlags = 0;
1249 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1250 device->touchScreen.lastTouch.clear();
1251 return; // event dropped
1252 }
1253
1254 /* Preprocess pointer data */
1255
1256 if (device->touchScreen.parameters.useBadTouchFilter) {
1257 if (device->touchScreen.applyBadTouchFilter()) {
1258 havePointerIds = false;
1259 }
1260 }
1261
1262 if (device->touchScreen.parameters.useJumpyTouchFilter) {
1263 if (device->touchScreen.applyJumpyTouchFilter()) {
1264 havePointerIds = false;
1265 }
1266 }
1267
1268 if (! havePointerIds) {
1269 device->touchScreen.calculatePointerIds();
1270 }
1271
1272 InputDevice::TouchData temp;
1273 InputDevice::TouchData* savedTouch;
1274 if (device->touchScreen.parameters.useAveragingTouchFilter) {
1275 temp.copyFrom(device->touchScreen.currentTouch);
1276 savedTouch = & temp;
1277
1278 device->touchScreen.applyAveragingTouchFilter();
1279 } else {
1280 savedTouch = & device->touchScreen.currentTouch;
1281 }
1282
1283 /* Process virtual keys or touches */
1284
1285 if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
1286 dispatchTouches(when, device, policyFlags);
1287 }
1288
1289 // Copy current touch to last touch in preparation for the next cycle.
1290 device->touchScreen.lastTouch.copyFrom(*savedTouch);
1291}
1292
1293bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
1294 InputDevice* device, uint32_t policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001295 switch (device->touchScreen.currentVirtualKey.status) {
1296 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001297 if (device->touchScreen.currentTouch.pointerCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001298 // Pointer went up after virtual key canceled.
1299 device->touchScreen.currentVirtualKey.status =
1300 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
1301 }
1302 return true; // consumed
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001303
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001304 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN:
1305 if (device->touchScreen.currentTouch.pointerCount == 0) {
1306 // Pointer went up while virtual key was down.
1307 device->touchScreen.currentVirtualKey.status =
1308 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001309#if DEBUG_VIRTUAL_KEYS
1310 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1311 device->touchScreen.currentVirtualKey.keyCode,
1312 device->touchScreen.currentVirtualKey.scanCode);
1313#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001314 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
1315 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
1316 return true; // consumed
1317 }
1318
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001319 if (device->touchScreen.currentTouch.pointerCount == 1) {
1320 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
1321 if (virtualKey
1322 && virtualKey->keyCode == device->touchScreen.currentVirtualKey.keyCode) {
1323 // Pointer is still within the space of the virtual key.
1324 return true; // consumed
1325 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001326 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001327
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001328 // Pointer left virtual key area or another pointer also went down.
1329 // Send key cancellation.
1330 device->touchScreen.currentVirtualKey.status =
1331 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001332#if DEBUG_VIRTUAL_KEYS
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001333 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1334 device->touchScreen.currentVirtualKey.keyCode,
1335 device->touchScreen.currentVirtualKey.scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001336#endif
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001337 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
1338 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1339 | KEY_EVENT_FLAG_CANCELED);
1340 return true; // consumed
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001341
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001342 default:
1343 if (device->touchScreen.currentTouch.pointerCount == 1
1344 && device->touchScreen.lastTouch.pointerCount == 0) {
1345 // Pointer just went down. Check for virtual key hit.
1346 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
1347 if (virtualKey) {
1348 device->touchScreen.currentVirtualKey.status =
1349 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001350 device->touchScreen.currentVirtualKey.downTime = when;
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001351 device->touchScreen.currentVirtualKey.keyCode = virtualKey->keyCode;
1352 device->touchScreen.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001353#if DEBUG_VIRTUAL_KEYS
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001354 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1355 device->touchScreen.currentVirtualKey.keyCode,
1356 device->touchScreen.currentVirtualKey.scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001357#endif
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001358 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
1359 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
1360 return true; // consumed
1361 }
1362 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001363 return false; // not consumed
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001364 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001365}
1366
1367void InputReader::dispatchVirtualKey(nsecs_t when,
1368 InputDevice* device, uint32_t policyFlags,
1369 int32_t keyEventAction, int32_t keyEventFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -07001370 updateExportedVirtualKeyState();
1371
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001372 int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
1373 int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
1374 nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
1375 int32_t metaState = globalMetaState();
1376
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001377 if (keyEventAction == KEY_EVENT_ACTION_DOWN) {
1378 mPolicy->virtualKeyDownFeedback();
1379 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001380
Jeff Brown349703e2010-06-22 01:27:15 -07001381 int32_t policyActions = mPolicy->interceptKey(when, device->id,
1382 keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
1383
1384 if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1385 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
1386 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1387 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001388}
1389
1390void InputReader::dispatchTouches(nsecs_t when,
1391 InputDevice* device, uint32_t policyFlags) {
1392 uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
1393 uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
1394 if (currentPointerCount == 0 && lastPointerCount == 0) {
1395 return; // nothing to do!
1396 }
1397
1398 BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
1399 BitSet32 lastIdBits = device->touchScreen.lastTouch.idBits;
1400
1401 if (currentIdBits == lastIdBits) {
1402 // No pointer id changes so this is a move event.
1403 // The dispatcher takes care of batching moves so we don't have to deal with that here.
1404 int32_t motionEventAction = MOTION_EVENT_ACTION_MOVE;
1405 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
1406 currentIdBits, motionEventAction);
1407 } else {
1408 // There may be pointers going up and pointers going down at the same time when pointer
1409 // ids are reported by the device driver.
1410 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1411 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1412 BitSet32 activeIdBits(lastIdBits.value);
1413
1414 while (! upIdBits.isEmpty()) {
1415 uint32_t upId = upIdBits.firstMarkedBit();
1416 upIdBits.clearBit(upId);
1417 BitSet32 oldActiveIdBits = activeIdBits;
1418 activeIdBits.clearBit(upId);
1419
1420 int32_t motionEventAction;
1421 if (activeIdBits.isEmpty()) {
1422 motionEventAction = MOTION_EVENT_ACTION_UP;
1423 } else {
1424 motionEventAction = MOTION_EVENT_ACTION_POINTER_UP
1425 | (upId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1426 }
1427
1428 dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
1429 oldActiveIdBits, motionEventAction);
1430 }
1431
1432 while (! downIdBits.isEmpty()) {
1433 uint32_t downId = downIdBits.firstMarkedBit();
1434 downIdBits.clearBit(downId);
1435 BitSet32 oldActiveIdBits = activeIdBits;
1436 activeIdBits.markBit(downId);
1437
1438 int32_t motionEventAction;
1439 if (oldActiveIdBits.isEmpty()) {
1440 motionEventAction = MOTION_EVENT_ACTION_DOWN;
1441 device->touchScreen.downTime = when;
1442 } else {
1443 motionEventAction = MOTION_EVENT_ACTION_POINTER_DOWN
1444 | (downId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1445 }
1446
1447 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
1448 activeIdBits, motionEventAction);
1449 }
1450 }
1451}
1452
1453void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
1454 InputDevice::TouchData* touch, BitSet32 idBits,
1455 int32_t motionEventAction) {
1456 int32_t orientedWidth, orientedHeight;
1457 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001458 case InputReaderPolicyInterface::ROTATION_90:
1459 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001460 orientedWidth = mDisplayHeight;
1461 orientedHeight = mDisplayWidth;
1462 break;
1463 default:
1464 orientedWidth = mDisplayWidth;
1465 orientedHeight = mDisplayHeight;
1466 break;
1467 }
1468
1469 uint32_t pointerCount = 0;
1470 int32_t pointerIds[MAX_POINTERS];
1471 PointerCoords pointerCoords[MAX_POINTERS];
1472
Jeff Brown0b72e822010-06-29 16:52:21 -07001473 const InputDevice::TouchScreenState::Precalculated& precalculated =
1474 device->touchScreen.precalculated;
1475
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001476 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1477 // display coordinates (PointerCoords) and adjust for display orientation.
1478 while (! idBits.isEmpty()) {
1479 uint32_t id = idBits.firstMarkedBit();
1480 idBits.clearBit(id);
1481 uint32_t index = touch->idToIndex[id];
1482
Jeff Brown0b72e822010-06-29 16:52:21 -07001483 float x = float(touch->pointers[index].x
1484 - precalculated.xOrigin) * precalculated.xScale;
1485 float y = float(touch->pointers[index].y
1486 - precalculated.yOrigin) * precalculated.yScale;
1487 float pressure = float(touch->pointers[index].pressure
1488 - precalculated.pressureOrigin) * precalculated.pressureScale;
1489 float size = float(touch->pointers[index].size
1490 - precalculated.sizeOrigin) * precalculated.sizeScale;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001491
1492 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001493 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001494 float xTemp = x;
1495 x = y;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001496 y = mDisplayWidth - xTemp;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001497 break;
1498 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001499 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001500 x = mDisplayWidth - x;
1501 y = mDisplayHeight - y;
1502 break;
1503 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001504 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001505 float xTemp = x;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001506 x = mDisplayHeight - y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001507 y = xTemp;
1508 break;
1509 }
1510 }
1511
1512 pointerIds[pointerCount] = int32_t(id);
1513
1514 pointerCoords[pointerCount].x = x;
1515 pointerCoords[pointerCount].y = y;
1516 pointerCoords[pointerCount].pressure = pressure;
1517 pointerCoords[pointerCount].size = size;
1518
1519 pointerCount += 1;
1520 }
1521
1522 // Check edge flags by looking only at the first pointer since the flags are
1523 // global to the event.
1524 // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
1525 int32_t motionEventEdgeFlags = 0;
1526 if (motionEventAction == MOTION_EVENT_ACTION_DOWN) {
1527 if (pointerCoords[0].x <= 0) {
1528 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_LEFT;
1529 } else if (pointerCoords[0].x >= orientedWidth) {
1530 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_RIGHT;
1531 }
1532 if (pointerCoords[0].y <= 0) {
1533 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_TOP;
1534 } else if (pointerCoords[0].y >= orientedHeight) {
1535 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_BOTTOM;
1536 }
1537 }
1538
1539 nsecs_t downTime = device->touchScreen.downTime;
1540 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TOUCH, policyFlags,
1541 motionEventAction, globalMetaState(), motionEventEdgeFlags,
1542 pointerCount, pointerIds, pointerCoords,
1543 0, 0, downTime);
1544}
1545
1546void InputReader::onTrackballStateChanged(nsecs_t when,
1547 InputDevice* device) {
1548 static const uint32_t DELTA_FIELDS =
1549 InputDevice::TrackballState::Accumulator::FIELD_REL_X
1550 | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
1551
1552 /* Refresh display properties so we can trackball moves according to display orientation */
1553
1554 if (! refreshDisplayProperties()) {
1555 return;
1556 }
1557
1558 /* Update device state */
1559
1560 uint32_t fields = device->trackball.accumulator.fields;
1561 bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001562 bool deltaChanged = fields & DELTA_FIELDS;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001563
1564 bool down;
1565 if (downChanged) {
1566 if (device->trackball.accumulator.btnMouse) {
1567 device->trackball.current.down = true;
1568 device->trackball.current.downTime = when;
1569 down = true;
1570 } else {
1571 device->trackball.current.down = false;
1572 down = false;
1573 }
1574 } else {
1575 down = device->trackball.current.down;
1576 }
1577
1578 /* Apply policy */
1579
1580 int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
1581
1582 uint32_t policyFlags = 0;
1583 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1584 return; // event dropped
1585 }
1586
1587 /* Enqueue motion event for dispatch */
1588
1589 int32_t motionEventAction;
1590 if (downChanged) {
1591 motionEventAction = down ? MOTION_EVENT_ACTION_DOWN : MOTION_EVENT_ACTION_UP;
1592 } else {
1593 motionEventAction = MOTION_EVENT_ACTION_MOVE;
1594 }
1595
1596 int32_t pointerId = 0;
1597 PointerCoords pointerCoords;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001598 pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
1599 ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
1600 pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
1601 ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001602 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
1603 pointerCoords.size = 0;
1604
1605 float temp;
1606 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001607 case InputReaderPolicyInterface::ROTATION_90:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001608 temp = pointerCoords.x;
1609 pointerCoords.x = pointerCoords.y;
1610 pointerCoords.y = - temp;
1611 break;
1612
Jeff Brown9c3cda02010-06-15 01:31:58 -07001613 case InputReaderPolicyInterface::ROTATION_180:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001614 pointerCoords.x = - pointerCoords.x;
1615 pointerCoords.y = - pointerCoords.y;
1616 break;
1617
Jeff Brown9c3cda02010-06-15 01:31:58 -07001618 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001619 temp = pointerCoords.x;
1620 pointerCoords.x = - pointerCoords.y;
1621 pointerCoords.y = temp;
1622 break;
1623 }
1624
1625 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TRACKBALL, policyFlags,
1626 motionEventAction, globalMetaState(), MOTION_EVENT_EDGE_FLAG_NONE,
1627 1, & pointerId, & pointerCoords,
1628 device->trackball.precalculated.xPrecision,
1629 device->trackball.precalculated.yPrecision,
1630 device->trackball.current.downTime);
1631}
1632
1633void InputReader::onConfigurationChanged(nsecs_t when) {
1634 // Reset global meta state because it depends on the list of all configured devices.
1635 resetGlobalMetaState();
1636
1637 // Reset virtual keys, just in case.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001638 updateExportedVirtualKeyState();
1639
1640 // Update input configuration.
1641 updateExportedInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001642
1643 // Enqueue configuration changed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001644 mDispatcher->notifyConfigurationChanged(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001645}
1646
1647bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
1648 int32_t policyActions, uint32_t* policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001649 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001650 mDispatcher->notifyAppSwitchComing(when);
1651 }
1652
Jeff Brown9c3cda02010-06-15 01:31:58 -07001653 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001654 *policyFlags |= POLICY_FLAG_WOKE_HERE;
1655 }
1656
Jeff Brown9c3cda02010-06-15 01:31:58 -07001657 if (policyActions & InputReaderPolicyInterface::ACTION_BRIGHT_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001658 *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
1659 }
1660
Jeff Brown9c3cda02010-06-15 01:31:58 -07001661 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001662}
1663
1664void InputReader::resetDisplayProperties() {
1665 mDisplayWidth = mDisplayHeight = -1;
1666 mDisplayOrientation = -1;
1667}
1668
1669bool InputReader::refreshDisplayProperties() {
1670 int32_t newWidth, newHeight, newOrientation;
1671 if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
1672 if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
1673 LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
1674 mDisplayWidth, mDisplayHeight, newWidth, newHeight);
1675
1676 mDisplayWidth = newWidth;
1677 mDisplayHeight = newHeight;
1678
1679 for (size_t i = 0; i < mDevices.size(); i++) {
1680 configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
1681 }
1682 }
1683
Jeff Brown0b72e822010-06-29 16:52:21 -07001684 if (newOrientation != mDisplayOrientation) {
1685 LOGD("Display orientation changed to %d", mDisplayOrientation);
1686
1687 mDisplayOrientation = newOrientation;
1688 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001689 return true;
1690 } else {
1691 resetDisplayProperties();
1692 return false;
1693 }
1694}
1695
1696InputDevice* InputReader::getDevice(int32_t deviceId) {
1697 ssize_t index = mDevices.indexOfKey(deviceId);
1698 return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
1699}
1700
1701InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
1702 InputDevice* device = getDevice(deviceId);
1703 return device && ! device->ignored ? device : NULL;
1704}
1705
1706void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
1707 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
1708 String8 name = mEventHub->getDeviceName(deviceId);
1709 InputDevice* device = new InputDevice(deviceId, classes, name);
1710
1711 if (classes != 0) {
1712 LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
1713 device->name.string(), device->classes);
1714
1715 configureDevice(device);
1716 } else {
1717 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
1718 device->name.string());
1719
1720 device->ignored = true;
1721 }
1722
1723 device->reset();
1724
1725 mDevices.add(deviceId, device);
1726
1727 if (! device->ignored) {
1728 onConfigurationChanged(when);
1729 }
1730}
1731
1732void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
1733 mDevices.removeItem(device->id);
1734
1735 if (! device->ignored) {
1736 LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
1737 device->name.string(), device->classes);
1738
1739 onConfigurationChanged(when);
1740 } else {
1741 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
1742 device->name.string());
1743 }
1744
1745 delete device;
1746}
1747
1748void InputReader::configureDevice(InputDevice* device) {
1749 if (device->isMultiTouchScreen()) {
1750 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
1751 & device->touchScreen.parameters.xAxis);
1752 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
1753 & device->touchScreen.parameters.yAxis);
1754 configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
1755 & device->touchScreen.parameters.pressureAxis);
1756 configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
1757 & device->touchScreen.parameters.sizeAxis);
1758 } else if (device->isSingleTouchScreen()) {
1759 configureAbsoluteAxisInfo(device, ABS_X, "X",
1760 & device->touchScreen.parameters.xAxis);
1761 configureAbsoluteAxisInfo(device, ABS_Y, "Y",
1762 & device->touchScreen.parameters.yAxis);
1763 configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
1764 & device->touchScreen.parameters.pressureAxis);
1765 configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
1766 & device->touchScreen.parameters.sizeAxis);
1767 }
1768
1769 if (device->isTouchScreen()) {
1770 device->touchScreen.parameters.useBadTouchFilter =
1771 mPolicy->filterTouchEvents();
1772 device->touchScreen.parameters.useAveragingTouchFilter =
1773 mPolicy->filterTouchEvents();
1774 device->touchScreen.parameters.useJumpyTouchFilter =
1775 mPolicy->filterJumpyTouchEvents();
1776
Jeff Brown0b72e822010-06-29 16:52:21 -07001777 if (device->touchScreen.parameters.pressureAxis.valid) {
1778 device->touchScreen.precalculated.pressureOrigin =
1779 device->touchScreen.parameters.pressureAxis.minValue;
1780 device->touchScreen.precalculated.pressureScale =
1781 1.0f / device->touchScreen.parameters.pressureAxis.range;
1782 } else {
1783 device->touchScreen.precalculated.pressureOrigin = 0;
1784 device->touchScreen.precalculated.pressureScale = 1.0f;
1785 }
1786
1787 if (device->touchScreen.parameters.sizeAxis.valid) {
1788 device->touchScreen.precalculated.sizeOrigin =
1789 device->touchScreen.parameters.sizeAxis.minValue;
1790 device->touchScreen.precalculated.sizeScale =
1791 1.0f / device->touchScreen.parameters.sizeAxis.range;
1792 } else {
1793 device->touchScreen.precalculated.sizeOrigin = 0;
1794 device->touchScreen.precalculated.sizeScale = 1.0f;
1795 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001796 }
1797
1798 if (device->isTrackball()) {
1799 device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1800 device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1801 device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1802 device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1803 }
1804
1805 configureDeviceForCurrentDisplaySize(device);
1806}
1807
1808void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
1809 if (device->isTouchScreen()) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001810 if (device->touchScreen.parameters.xAxis.valid
1811 && device->touchScreen.parameters.yAxis.valid) {
1812 device->touchScreen.precalculated.xOrigin =
1813 device->touchScreen.parameters.xAxis.minValue;
1814 device->touchScreen.precalculated.yOrigin =
1815 device->touchScreen.parameters.yAxis.minValue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001816
Jeff Brown0b72e822010-06-29 16:52:21 -07001817 if (mDisplayWidth < 0) {
1818 LOGD("Skipping part of touch screen configuration since display size is unknown.");
1819
1820 device->touchScreen.precalculated.xScale = 1.0f;
1821 device->touchScreen.precalculated.yScale = 1.0f;
1822 } else {
1823 LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
1824 device->name.string());
1825
1826 device->touchScreen.precalculated.xScale =
1827 float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
1828 device->touchScreen.precalculated.yScale =
1829 float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
1830
1831 configureVirtualKeys(device);
1832 }
1833 } else {
1834 device->touchScreen.precalculated.xOrigin = 0;
1835 device->touchScreen.precalculated.xScale = 1.0f;
1836 device->touchScreen.precalculated.yOrigin = 0;
1837 device->touchScreen.precalculated.yScale = 1.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001838 }
1839 }
1840}
1841
1842void InputReader::configureVirtualKeys(InputDevice* device) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001843 assert(device->touchScreen.parameters.xAxis.valid
1844 && device->touchScreen.parameters.yAxis.valid);
1845
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001846 device->touchScreen.virtualKeys.clear();
1847
Jeff Brown9c3cda02010-06-15 01:31:58 -07001848 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001849 mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
1850 if (virtualKeyDefinitions.size() == 0) {
1851 return;
1852 }
1853
1854 device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1855
1856 int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
1857 int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
1858 int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
1859 int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
1860
1861 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001862 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001863 virtualKeyDefinitions[i];
1864
1865 device->touchScreen.virtualKeys.add();
1866 InputDevice::VirtualKey& virtualKey =
1867 device->touchScreen.virtualKeys.editTop();
1868
1869 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1870 int32_t keyCode;
1871 uint32_t flags;
1872 if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
1873 & keyCode, & flags)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001874 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001875 device->touchScreen.virtualKeys.pop(); // drop the key
1876 continue;
1877 }
1878
1879 virtualKey.keyCode = keyCode;
1880 virtualKey.flags = flags;
1881
1882 // convert the key definition's display coordinates into touch coordinates for a hit box
1883 int32_t halfWidth = virtualKeyDefinition.width / 2;
1884 int32_t halfHeight = virtualKeyDefinition.height / 2;
1885
1886 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1887 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1888 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1889 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1890 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1891 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1892 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1893 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1894
1895 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1896 virtualKey.scanCode, virtualKey.keyCode,
1897 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1898 }
1899}
1900
1901void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
1902 int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
1903 if (! mEventHub->getAbsoluteInfo(device->id, axis,
1904 & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
1905 out->range = out->maxValue - out->minValue;
1906 if (out->range != 0) {
1907 LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
1908 name, out->minValue, out->maxValue, out->flat, out->fuzz);
Jeff Brown0b72e822010-06-29 16:52:21 -07001909 out->valid = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001910 return;
1911 }
1912 }
1913
Jeff Brown0b72e822010-06-29 16:52:21 -07001914 out->valid = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001915 out->minValue = 0;
1916 out->maxValue = 0;
1917 out->flat = 0;
1918 out->fuzz = 0;
1919 out->range = 0;
Jeff Brown0b72e822010-06-29 16:52:21 -07001920 LOGI(" %s: unknown axis values, marking as invalid", name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001921}
1922
Jeff Brown9c3cda02010-06-15 01:31:58 -07001923void InputReader::configureExcludedDevices() {
1924 Vector<String8> excludedDeviceNames;
1925 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
1926
1927 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
1928 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
1929 }
1930}
1931
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001932void InputReader::resetGlobalMetaState() {
1933 mGlobalMetaState = -1;
1934}
1935
1936int32_t InputReader::globalMetaState() {
1937 if (mGlobalMetaState == -1) {
1938 mGlobalMetaState = 0;
1939 for (size_t i = 0; i < mDevices.size(); i++) {
1940 InputDevice* device = mDevices.valueAt(i);
1941 if (device->isKeyboard()) {
1942 mGlobalMetaState |= device->keyboard.current.metaState;
1943 }
1944 }
1945 }
1946 return mGlobalMetaState;
1947}
1948
Jeff Brown9c3cda02010-06-15 01:31:58 -07001949void InputReader::updateExportedVirtualKeyState() {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001950 int32_t keyCode = -1, scanCode = -1;
1951
1952 for (size_t i = 0; i < mDevices.size(); i++) {
1953 InputDevice* device = mDevices.valueAt(i);
1954 if (device->isTouchScreen()) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001955 if (device->touchScreen.currentVirtualKey.status
1956 == InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001957 keyCode = device->touchScreen.currentVirtualKey.keyCode;
1958 scanCode = device->touchScreen.currentVirtualKey.scanCode;
1959 }
1960 }
1961 }
1962
Jeff Brown9c3cda02010-06-15 01:31:58 -07001963 { // acquire exported state lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001964 AutoMutex _l(mExportedStateLock);
1965
Jeff Brown9c3cda02010-06-15 01:31:58 -07001966 mExportedVirtualKeyCode = keyCode;
1967 mExportedVirtualScanCode = scanCode;
1968 } // release exported state lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001969}
1970
1971bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001972 { // acquire exported state lock
1973 AutoMutex _l(mExportedStateLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001974
Jeff Brown9c3cda02010-06-15 01:31:58 -07001975 *outKeyCode = mExportedVirtualKeyCode;
1976 *outScanCode = mExportedVirtualScanCode;
1977 return mExportedVirtualKeyCode != -1;
1978 } // release exported state lock
1979}
1980
1981void InputReader::updateExportedInputConfiguration() {
1982 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
1983 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
1984 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
1985
1986 for (size_t i = 0; i < mDevices.size(); i++) {
1987 InputDevice* device = mDevices.valueAt(i);
1988 int32_t deviceClasses = device->classes;
1989
1990 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
1991 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
1992 }
1993 if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
1994 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
1995 }
1996 if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
1997 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
1998 } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
1999 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
2000 }
2001 }
2002
2003 { // acquire exported state lock
2004 AutoMutex _l(mExportedStateLock);
2005
2006 mExportedInputConfiguration.touchScreen = touchScreenConfig;
2007 mExportedInputConfiguration.keyboard = keyboardConfig;
2008 mExportedInputConfiguration.navigation = navigationConfig;
2009 } // release exported state lock
2010}
2011
2012void InputReader::getCurrentInputConfiguration(InputConfiguration* outConfiguration) const {
2013 { // acquire exported state lock
2014 AutoMutex _l(mExportedStateLock);
2015
2016 *outConfiguration = mExportedInputConfiguration;
2017 } // release exported state lock
2018}
2019
2020int32_t InputReader::getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
2021 int32_t scanCode) const {
2022 { // acquire exported state lock
2023 AutoMutex _l(mExportedStateLock);
2024
2025 if (mExportedVirtualScanCode == scanCode) {
2026 return KEY_STATE_VIRTUAL;
2027 }
2028 } // release exported state lock
2029
2030 return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
2031}
2032
2033int32_t InputReader::getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
2034 int32_t keyCode) const {
2035 { // acquire exported state lock
2036 AutoMutex _l(mExportedStateLock);
2037
2038 if (mExportedVirtualKeyCode == keyCode) {
2039 return KEY_STATE_VIRTUAL;
2040 }
2041 } // release exported state lock
2042
2043 return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
2044}
2045
2046int32_t InputReader::getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
2047 int32_t sw) const {
2048 return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
2049}
2050
2051bool InputReader::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
2052 return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07002053}
2054
2055
2056// --- InputReaderThread ---
2057
2058InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
2059 Thread(/*canCallJava*/ true), mReader(reader) {
2060}
2061
2062InputReaderThread::~InputReaderThread() {
2063}
2064
2065bool InputReaderThread::threadLoop() {
2066 mReader->loopOnce();
2067 return true;
2068}
2069
2070} // namespace android