blob: 8087f84bc54c8e675e9ce7d2f4d2b5da837b930a [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;
192 currentVirtualKey.down = false;
193
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() {
390 uint32_t pointerCount = currentTouch.pointerCount;
391
392 // Nothing to do if there are no points.
393 if (pointerCount == 0) {
394 return false;
395 }
396
397 // Don't do anything if a finger is going down or up. We run
398 // here before assigning pointer IDs, so there isn't a good
399 // way to do per-finger matching.
400 if (pointerCount != lastTouch.pointerCount) {
401 return false;
402 }
403
404 // We consider a single movement across more than a 7/16 of
405 // the long size of the screen to be bad. This was a magic value
406 // determined by looking at the maximum distance it is feasible
407 // to actually move in one sample.
408 int32_t maxDeltaY = parameters.yAxis.range * 7 / 16;
409
410 // XXX The original code in InputDevice.java included commented out
411 // code for testing the X axis. Note that when we drop a point
412 // we don't actually restore the old X either. Strange.
413 // The old code also tries to track when bad points were previously
414 // detected but it turns out that due to the placement of a "break"
415 // at the end of the loop, we never set mDroppedBadPoint to true
416 // so it is effectively dead code.
417 // Need to figure out if the old code is busted or just overcomplicated
418 // but working as intended.
419
420 // Look through all new points and see if any are farther than
421 // acceptable from all previous points.
422 for (uint32_t i = pointerCount; i-- > 0; ) {
423 int32_t y = currentTouch.pointers[i].y;
424 int32_t closestY = INT_MAX;
425 int32_t closestDeltaY = 0;
426
427#if DEBUG_HACKS
428 LOGD("BadTouchFilter: Looking at next point #%d: y=%d", i, y);
429#endif
430
431 for (uint32_t j = pointerCount; j-- > 0; ) {
432 int32_t lastY = lastTouch.pointers[j].y;
433 int32_t deltaY = abs(y - lastY);
434
435#if DEBUG_HACKS
436 LOGD("BadTouchFilter: Comparing with last point #%d: y=%d deltaY=%d",
437 j, lastY, deltaY);
438#endif
439
440 if (deltaY < maxDeltaY) {
441 goto SkipSufficientlyClosePoint;
442 }
443 if (deltaY < closestDeltaY) {
444 closestDeltaY = deltaY;
445 closestY = lastY;
446 }
447 }
448
449 // Must not have found a close enough match.
450#if DEBUG_HACKS
451 LOGD("BadTouchFilter: Dropping bad point #%d: newY=%d oldY=%d deltaY=%d maxDeltaY=%d",
452 i, y, closestY, closestDeltaY, maxDeltaY);
453#endif
454
455 currentTouch.pointers[i].y = closestY;
456 return true; // XXX original code only corrects one point
457
458 SkipSufficientlyClosePoint: ;
459 }
460
461 // No change.
462 return false;
463}
464
465/* Special hack for devices that have bad screen data: drop points where
466 * the coordinate value for one axis has jumped to the other pointer's location.
467 */
468bool InputDevice::TouchScreenState::applyJumpyTouchFilter() {
469 uint32_t pointerCount = currentTouch.pointerCount;
470 if (lastTouch.pointerCount != pointerCount) {
471#if DEBUG_HACKS
472 LOGD("JumpyTouchFilter: Different pointer count %d -> %d",
473 lastTouch.pointerCount, pointerCount);
474 for (uint32_t i = 0; i < pointerCount; i++) {
475 LOGD(" Pointer %d (%d, %d)", i,
476 currentTouch.pointers[i].x, currentTouch.pointers[i].y);
477 }
478#endif
479
480 if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_TRANSITION_DROPS) {
481 if (lastTouch.pointerCount == 1 && pointerCount == 2) {
482 // Just drop the first few events going from 1 to 2 pointers.
483 // They're bad often enough that they're not worth considering.
484 currentTouch.pointerCount = 1;
485 jumpyTouchFilter.jumpyPointsDropped += 1;
486
487#if DEBUG_HACKS
488 LOGD("JumpyTouchFilter: Pointer 2 dropped");
489#endif
490 return true;
491 } else if (lastTouch.pointerCount == 2 && pointerCount == 1) {
492 // The event when we go from 2 -> 1 tends to be messed up too
493 currentTouch.pointerCount = 2;
494 currentTouch.pointers[0] = lastTouch.pointers[0];
495 currentTouch.pointers[1] = lastTouch.pointers[1];
496 jumpyTouchFilter.jumpyPointsDropped += 1;
497
498#if DEBUG_HACKS
499 for (int32_t i = 0; i < 2; i++) {
500 LOGD("JumpyTouchFilter: Pointer %d replaced (%d, %d)", i,
501 currentTouch.pointers[i].x, currentTouch.pointers[i].y);
502 }
503#endif
504 return true;
505 }
506 }
507 // Reset jumpy points dropped on other transitions or if limit exceeded.
508 jumpyTouchFilter.jumpyPointsDropped = 0;
509
510#if DEBUG_HACKS
511 LOGD("JumpyTouchFilter: Transition - drop limit reset");
512#endif
513 return false;
514 }
515
516 // We have the same number of pointers as last time.
517 // A 'jumpy' point is one where the coordinate value for one axis
518 // has jumped to the other pointer's location. No need to do anything
519 // else if we only have one pointer.
520 if (pointerCount < 2) {
521 return false;
522 }
523
524 if (jumpyTouchFilter.jumpyPointsDropped < JUMPY_DROP_LIMIT) {
525 int jumpyEpsilon = parameters.yAxis.range / JUMPY_EPSILON_DIVISOR;
526
527 // We only replace the single worst jumpy point as characterized by pointer distance
528 // in a single axis.
529 int32_t badPointerIndex = -1;
530 int32_t badPointerReplacementIndex = -1;
531 int32_t badPointerDistance = INT_MIN; // distance to be corrected
532
533 for (uint32_t i = pointerCount; i-- > 0; ) {
534 int32_t x = currentTouch.pointers[i].x;
535 int32_t y = currentTouch.pointers[i].y;
536
537#if DEBUG_HACKS
538 LOGD("JumpyTouchFilter: Point %d (%d, %d)", i, x, y);
539#endif
540
541 // Check if a touch point is too close to another's coordinates
542 bool dropX = false, dropY = false;
543 for (uint32_t j = 0; j < pointerCount; j++) {
544 if (i == j) {
545 continue;
546 }
547
548 if (abs(x - currentTouch.pointers[j].x) <= jumpyEpsilon) {
549 dropX = true;
550 break;
551 }
552
553 if (abs(y - currentTouch.pointers[j].y) <= jumpyEpsilon) {
554 dropY = true;
555 break;
556 }
557 }
558 if (! dropX && ! dropY) {
559 continue; // not jumpy
560 }
561
562 // Find a replacement candidate by comparing with older points on the
563 // complementary (non-jumpy) axis.
564 int32_t distance = INT_MIN; // distance to be corrected
565 int32_t replacementIndex = -1;
566
567 if (dropX) {
568 // X looks too close. Find an older replacement point with a close Y.
569 int32_t smallestDeltaY = INT_MAX;
570 for (uint32_t j = 0; j < pointerCount; j++) {
571 int32_t deltaY = abs(y - lastTouch.pointers[j].y);
572 if (deltaY < smallestDeltaY) {
573 smallestDeltaY = deltaY;
574 replacementIndex = j;
575 }
576 }
577 distance = abs(x - lastTouch.pointers[replacementIndex].x);
578 } else {
579 // Y looks too close. Find an older replacement point with a close X.
580 int32_t smallestDeltaX = INT_MAX;
581 for (uint32_t j = 0; j < pointerCount; j++) {
582 int32_t deltaX = abs(x - lastTouch.pointers[j].x);
583 if (deltaX < smallestDeltaX) {
584 smallestDeltaX = deltaX;
585 replacementIndex = j;
586 }
587 }
588 distance = abs(y - lastTouch.pointers[replacementIndex].y);
589 }
590
591 // If replacing this pointer would correct a worse error than the previous ones
592 // considered, then use this replacement instead.
593 if (distance > badPointerDistance) {
594 badPointerIndex = i;
595 badPointerReplacementIndex = replacementIndex;
596 badPointerDistance = distance;
597 }
598 }
599
600 // Correct the jumpy pointer if one was found.
601 if (badPointerIndex >= 0) {
602#if DEBUG_HACKS
603 LOGD("JumpyTouchFilter: Replacing bad pointer %d with (%d, %d)",
604 badPointerIndex,
605 lastTouch.pointers[badPointerReplacementIndex].x,
606 lastTouch.pointers[badPointerReplacementIndex].y);
607#endif
608
609 currentTouch.pointers[badPointerIndex].x =
610 lastTouch.pointers[badPointerReplacementIndex].x;
611 currentTouch.pointers[badPointerIndex].y =
612 lastTouch.pointers[badPointerReplacementIndex].y;
613 jumpyTouchFilter.jumpyPointsDropped += 1;
614 return true;
615 }
616 }
617
618 jumpyTouchFilter.jumpyPointsDropped = 0;
619 return false;
620}
621
622/* Special hack for devices that have bad screen data: aggregate and
623 * compute averages of the coordinate data, to reduce the amount of
624 * jitter seen by applications. */
625void InputDevice::TouchScreenState::applyAveragingTouchFilter() {
626 for (uint32_t currentIndex = 0; currentIndex < currentTouch.pointerCount; currentIndex++) {
627 uint32_t id = currentTouch.pointers[currentIndex].id;
628 int32_t x = currentTouch.pointers[currentIndex].x;
629 int32_t y = currentTouch.pointers[currentIndex].y;
630 int32_t pressure = currentTouch.pointers[currentIndex].pressure;
631
632 if (lastTouch.idBits.hasBit(id)) {
Jeff Brown349703e2010-06-22 01:27:15 -0700633 // Pointer was down before and is still down now.
634 // Compute average over history trace.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700635 uint32_t start = averagingTouchFilter.historyStart[id];
636 uint32_t end = averagingTouchFilter.historyEnd[id];
637
638 int64_t deltaX = x - averagingTouchFilter.historyData[end].pointers[id].x;
639 int64_t deltaY = y - averagingTouchFilter.historyData[end].pointers[id].y;
640 uint64_t distance = uint64_t(deltaX * deltaX + deltaY * deltaY);
641
642#if DEBUG_HACKS
643 LOGD("AveragingTouchFilter: Pointer id %d - Distance from last sample: %lld",
644 id, distance);
645#endif
646
647 if (distance < AVERAGING_DISTANCE_LIMIT) {
Jeff Brown349703e2010-06-22 01:27:15 -0700648 // Increment end index in preparation for recording new historical data.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700649 end += 1;
650 if (end > AVERAGING_HISTORY_SIZE) {
651 end = 0;
652 }
653
Jeff Brown349703e2010-06-22 01:27:15 -0700654 // If the end index has looped back to the start index then we have filled
655 // the historical trace up to the desired size so we drop the historical
656 // data at the start of the trace.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700657 if (end == start) {
658 start += 1;
659 if (start > AVERAGING_HISTORY_SIZE) {
660 start = 0;
661 }
662 }
663
Jeff Brown349703e2010-06-22 01:27:15 -0700664 // Add the raw data to the historical trace.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700665 averagingTouchFilter.historyStart[id] = start;
666 averagingTouchFilter.historyEnd[id] = end;
667 averagingTouchFilter.historyData[end].pointers[id].x = x;
668 averagingTouchFilter.historyData[end].pointers[id].y = y;
669 averagingTouchFilter.historyData[end].pointers[id].pressure = pressure;
670
Jeff Brown349703e2010-06-22 01:27:15 -0700671 // Average over all historical positions in the trace by total pressure.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700672 int32_t averagedX = 0;
673 int32_t averagedY = 0;
674 int32_t totalPressure = 0;
675 for (;;) {
676 int32_t historicalX = averagingTouchFilter.historyData[start].pointers[id].x;
Jeff Brown349703e2010-06-22 01:27:15 -0700677 int32_t historicalY = averagingTouchFilter.historyData[start].pointers[id].y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700678 int32_t historicalPressure = averagingTouchFilter.historyData[start]
679 .pointers[id].pressure;
680
Jeff Brown349703e2010-06-22 01:27:15 -0700681 averagedX += historicalX * historicalPressure;
682 averagedY += historicalY * historicalPressure;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700683 totalPressure += historicalPressure;
684
685 if (start == end) {
686 break;
687 }
688
689 start += 1;
690 if (start > AVERAGING_HISTORY_SIZE) {
691 start = 0;
692 }
693 }
694
695 averagedX /= totalPressure;
696 averagedY /= totalPressure;
697
698#if DEBUG_HACKS
699 LOGD("AveragingTouchFilter: Pointer id %d - "
700 "totalPressure=%d, averagedX=%d, averagedY=%d", id, totalPressure,
701 averagedX, averagedY);
702#endif
703
704 currentTouch.pointers[currentIndex].x = averagedX;
705 currentTouch.pointers[currentIndex].y = averagedY;
706 } else {
707#if DEBUG_HACKS
708 LOGD("AveragingTouchFilter: Pointer id %d - Exceeded max distance", id);
709#endif
710 }
711 } else {
712#if DEBUG_HACKS
713 LOGD("AveragingTouchFilter: Pointer id %d - Pointer went up", id);
714#endif
715 }
716
717 // Reset pointer history.
718 averagingTouchFilter.historyStart[id] = 0;
719 averagingTouchFilter.historyEnd[id] = 0;
720 averagingTouchFilter.historyData[0].pointers[id].x = x;
721 averagingTouchFilter.historyData[0].pointers[id].y = y;
722 averagingTouchFilter.historyData[0].pointers[id].pressure = pressure;
723 }
724}
725
726bool InputDevice::TouchScreenState::isPointInsideDisplay(int32_t x, int32_t y) const {
727 return x >= parameters.xAxis.minValue
728 && x <= parameters.xAxis.maxValue
729 && y >= parameters.yAxis.minValue
730 && y <= parameters.yAxis.maxValue;
731}
732
733
734// --- InputDevice::SingleTouchScreenState ---
735
736void InputDevice::SingleTouchScreenState::reset() {
737 accumulator.clear();
738 current.down = false;
739 current.x = 0;
740 current.y = 0;
741 current.pressure = 0;
742 current.size = 0;
743}
744
745
746// --- InputDevice::MultiTouchScreenState ---
747
748void InputDevice::MultiTouchScreenState::reset() {
749 accumulator.clear();
750}
751
752
753// --- InputReader ---
754
755InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700756 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700757 const sp<InputDispatcherInterface>& dispatcher) :
758 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700759 configureExcludedDevices();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700760 resetGlobalMetaState();
761 resetDisplayProperties();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700762 updateExportedVirtualKeyState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700763}
764
765InputReader::~InputReader() {
766 for (size_t i = 0; i < mDevices.size(); i++) {
767 delete mDevices.valueAt(i);
768 }
769}
770
771void InputReader::loopOnce() {
772 RawEvent rawEvent;
773 mEventHub->getEvent(& rawEvent.deviceId, & rawEvent.type, & rawEvent.scanCode,
774 & rawEvent.keyCode, & rawEvent.flags, & rawEvent.value, & rawEvent.when);
775
776 // Replace the event timestamp so it is in same timebase as java.lang.System.nanoTime()
777 // and android.os.SystemClock.uptimeMillis() as expected by the rest of the system.
778 rawEvent.when = systemTime(SYSTEM_TIME_MONOTONIC);
779
780#if DEBUG_RAW_EVENTS
781 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
782 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
783 rawEvent.value);
784#endif
785
786 process(& rawEvent);
787}
788
789void InputReader::process(const RawEvent* rawEvent) {
790 switch (rawEvent->type) {
791 case EventHubInterface::DEVICE_ADDED:
792 handleDeviceAdded(rawEvent);
793 break;
794
795 case EventHubInterface::DEVICE_REMOVED:
796 handleDeviceRemoved(rawEvent);
797 break;
798
799 case EV_SYN:
800 handleSync(rawEvent);
801 break;
802
803 case EV_KEY:
804 handleKey(rawEvent);
805 break;
806
807 case EV_REL:
808 handleRelativeMotion(rawEvent);
809 break;
810
811 case EV_ABS:
812 handleAbsoluteMotion(rawEvent);
813 break;
814
815 case EV_SW:
816 handleSwitch(rawEvent);
817 break;
818 }
819}
820
821void InputReader::handleDeviceAdded(const RawEvent* rawEvent) {
822 InputDevice* device = getDevice(rawEvent->deviceId);
823 if (device) {
824 LOGW("Ignoring spurious device added event for deviceId %d.", rawEvent->deviceId);
825 return;
826 }
827
828 addDevice(rawEvent->when, rawEvent->deviceId);
829}
830
831void InputReader::handleDeviceRemoved(const RawEvent* rawEvent) {
832 InputDevice* device = getDevice(rawEvent->deviceId);
833 if (! device) {
834 LOGW("Ignoring spurious device removed event for deviceId %d.", rawEvent->deviceId);
835 return;
836 }
837
838 removeDevice(rawEvent->when, device);
839}
840
841void InputReader::handleSync(const RawEvent* rawEvent) {
842 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
843 if (! device) return;
844
845 if (rawEvent->scanCode == SYN_MT_REPORT) {
846 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
847 // We drop pointers with pressure <= 0 since that indicates they are not down.
848 if (device->isMultiTouchScreen()) {
849 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
850
851 if (device->multiTouchScreen.accumulator.pointers[pointerIndex].fields) {
852 if (pointerIndex == MAX_POINTERS) {
853 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
854 MAX_POINTERS);
855 } else {
856 pointerIndex += 1;
857 device->multiTouchScreen.accumulator.pointerCount = pointerIndex;
858 }
859 }
860
861 device->multiTouchScreen.accumulator.pointers[pointerIndex].clear();
862 }
863 } else if (rawEvent->scanCode == SYN_REPORT) {
864 // General Sync: The driver has returned all data for the current event update.
865 if (device->isMultiTouchScreen()) {
866 if (device->multiTouchScreen.accumulator.isDirty()) {
867 onMultiTouchScreenStateChanged(rawEvent->when, device);
868 device->multiTouchScreen.accumulator.clear();
869 }
870 } else if (device->isSingleTouchScreen()) {
871 if (device->singleTouchScreen.accumulator.isDirty()) {
872 onSingleTouchScreenStateChanged(rawEvent->when, device);
873 device->singleTouchScreen.accumulator.clear();
874 }
875 }
876
877 if (device->trackball.accumulator.isDirty()) {
878 onTrackballStateChanged(rawEvent->when, device);
879 device->trackball.accumulator.clear();
880 }
881 }
882}
883
884void InputReader::handleKey(const RawEvent* rawEvent) {
885 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
886 if (! device) return;
887
888 bool down = rawEvent->value != 0;
889 int32_t scanCode = rawEvent->scanCode;
890
891 if (device->isKeyboard() && (scanCode < BTN_FIRST || scanCode > BTN_LAST)) {
892 int32_t keyCode = rawEvent->keyCode;
893 onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
894 } else if (device->isSingleTouchScreen()) {
895 switch (rawEvent->scanCode) {
896 case BTN_TOUCH:
897 device->singleTouchScreen.accumulator.fields |=
898 InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
899 device->singleTouchScreen.accumulator.btnTouch = down;
900 break;
901 }
902 } else if (device->isTrackball()) {
903 switch (rawEvent->scanCode) {
904 case BTN_MOUSE:
905 device->trackball.accumulator.fields |=
906 InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
907 device->trackball.accumulator.btnMouse = down;
908
909 // send the down immediately
910 // XXX this emulates the old behavior of KeyInputQueue, unclear whether it is
911 // necessary or if we can wait until the next sync
912 onTrackballStateChanged(rawEvent->when, device);
913 device->trackball.accumulator.clear();
914 break;
915 }
916 }
917}
918
919void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
920 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
921 if (! device) return;
922
923 if (device->isTrackball()) {
924 switch (rawEvent->scanCode) {
925 case REL_X:
926 device->trackball.accumulator.fields |=
927 InputDevice::TrackballState::Accumulator::FIELD_REL_X;
928 device->trackball.accumulator.relX = rawEvent->value;
929 break;
930 case REL_Y:
931 device->trackball.accumulator.fields |=
932 InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
933 device->trackball.accumulator.relY = rawEvent->value;
934 break;
935 }
936 }
937}
938
939void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
940 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
941 if (! device) return;
942
943 if (device->isMultiTouchScreen()) {
944 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
945 InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
946 & device->multiTouchScreen.accumulator.pointers[pointerIndex];
947
948 switch (rawEvent->scanCode) {
949 case ABS_MT_POSITION_X:
950 pointer->fields |=
951 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
952 pointer->absMTPositionX = rawEvent->value;
953 break;
954 case ABS_MT_POSITION_Y:
955 pointer->fields |=
956 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
957 pointer->absMTPositionY = rawEvent->value;
958 break;
959 case ABS_MT_TOUCH_MAJOR:
960 pointer->fields |=
961 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
962 pointer->absMTTouchMajor = rawEvent->value;
963 break;
964 case ABS_MT_WIDTH_MAJOR:
965 pointer->fields |=
966 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
967 pointer->absMTWidthMajor = rawEvent->value;
968 break;
969 case ABS_MT_TRACKING_ID:
970 pointer->fields |=
971 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
972 pointer->absMTTrackingId = rawEvent->value;
973 break;
974 }
975 } else if (device->isSingleTouchScreen()) {
976 switch (rawEvent->scanCode) {
977 case ABS_X:
978 device->singleTouchScreen.accumulator.fields |=
979 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
980 device->singleTouchScreen.accumulator.absX = rawEvent->value;
981 break;
982 case ABS_Y:
983 device->singleTouchScreen.accumulator.fields |=
984 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
985 device->singleTouchScreen.accumulator.absY = rawEvent->value;
986 break;
987 case ABS_PRESSURE:
988 device->singleTouchScreen.accumulator.fields |=
989 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
990 device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
991 break;
992 case ABS_TOOL_WIDTH:
993 device->singleTouchScreen.accumulator.fields |=
994 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
995 device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
996 break;
997 }
998 }
999}
1000
1001void InputReader::handleSwitch(const RawEvent* rawEvent) {
1002 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
1003 if (! device) return;
1004
Jeff Brown9c3cda02010-06-15 01:31:58 -07001005 onSwitch(rawEvent->when, device, rawEvent->scanCode, rawEvent->value);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001006}
1007
1008void InputReader::onKey(nsecs_t when, InputDevice* device,
1009 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
1010 /* Refresh display properties so we can rotate key codes according to display orientation */
1011
1012 if (! refreshDisplayProperties()) {
1013 return;
1014 }
1015
1016 /* Update device state */
1017
1018 int32_t oldMetaState = device->keyboard.current.metaState;
1019 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
1020 if (oldMetaState != newMetaState) {
1021 device->keyboard.current.metaState = newMetaState;
1022 resetGlobalMetaState();
1023 }
1024
1025 // FIXME if we send a down event about a rotated key press we should ensure that we send
1026 // a corresponding up event about the rotated key press even if the orientation
1027 // has changed in the meantime
1028 keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
1029
1030 if (down) {
1031 device->keyboard.current.downTime = when;
1032 }
1033
1034 /* Apply policy */
1035
1036 int32_t policyActions = mPolicy->interceptKey(when, device->id,
1037 down, keyCode, scanCode, policyFlags);
1038
1039 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1040 return; // event dropped
1041 }
1042
1043 /* Enqueue key event for dispatch */
1044
1045 int32_t keyEventAction;
1046 if (down) {
1047 device->keyboard.current.downTime = when;
1048 keyEventAction = KEY_EVENT_ACTION_DOWN;
1049 } else {
1050 keyEventAction = KEY_EVENT_ACTION_UP;
1051 }
1052
1053 int32_t keyEventFlags = KEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001054 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001055 keyEventFlags = keyEventFlags | KEY_EVENT_FLAG_WOKE_HERE;
1056 }
1057
1058 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
1059 keyEventAction, keyEventFlags, keyCode, scanCode,
1060 device->keyboard.current.metaState,
1061 device->keyboard.current.downTime);
1062}
1063
Jeff Brown9c3cda02010-06-15 01:31:58 -07001064void InputReader::onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode,
1065 int32_t switchValue) {
1066 int32_t policyActions = mPolicy->interceptSwitch(when, switchCode, switchValue);
1067
1068 uint32_t policyFlags = 0;
1069 applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001070}
1071
1072void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
1073 InputDevice* device) {
1074 static const uint32_t REQUIRED_FIELDS =
1075 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
1076 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
1077 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
1078 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
1079
1080 /* Refresh display properties so we can map touch screen coords into display coords */
1081
1082 if (! refreshDisplayProperties()) {
1083 return;
1084 }
1085
1086 /* Update device state */
1087
1088 InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
1089 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
1090
1091 uint32_t inCount = in->accumulator.pointerCount;
1092 uint32_t outCount = 0;
1093 bool havePointerIds = true;
1094
1095 out->clear();
1096
1097 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
1098 uint32_t fields = in->accumulator.pointers[inIndex].fields;
1099
1100 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
1101#if DEBUG_POINTERS
1102 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
1103 inIndex, fields);
1104 continue;
1105#endif
1106 }
1107
1108 if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
1109 // Pointer is not down. Drop it.
1110 continue;
1111 }
1112
1113 // FIXME assignment of pressure may be incorrect, probably better to let
1114 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
1115 // isn't quite right either. Should be using touch for that.
1116 out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
1117 out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
1118 out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
1119 out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
1120
1121 if (havePointerIds) {
1122 if (fields & InputDevice::MultiTouchScreenState::Accumulator::
1123 FIELD_ABS_MT_TRACKING_ID) {
1124 uint32_t id = uint32_t(in->accumulator.pointers[inIndex].absMTTrackingId);
1125
1126 if (id > MAX_POINTER_ID) {
1127#if DEBUG_POINTERS
1128 LOGD("Pointers: Ignoring driver provided pointer id %d because "
1129 "it is larger than max supported id %d for optimizations",
1130 id, MAX_POINTER_ID);
1131#endif
1132 havePointerIds = false;
1133 }
1134 else {
1135 out->pointers[outCount].id = id;
1136 out->idToIndex[id] = outCount;
1137 out->idBits.markBit(id);
1138 }
1139 } else {
1140 havePointerIds = false;
1141 }
1142 }
1143
1144 outCount += 1;
1145 }
1146
1147 out->pointerCount = outCount;
1148
1149 onTouchScreenChanged(when, device, havePointerIds);
1150}
1151
1152void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
1153 InputDevice* device) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001154 /* Refresh display properties so we can map touch screen coords into display coords */
1155
1156 if (! refreshDisplayProperties()) {
1157 return;
1158 }
1159
1160 /* Update device state */
1161
1162 InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
1163 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
1164
1165 uint32_t fields = in->accumulator.fields;
1166
1167 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
1168 in->current.down = in->accumulator.btnTouch;
1169 }
1170
Jeff Brown349703e2010-06-22 01:27:15 -07001171 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001172 in->current.x = in->accumulator.absX;
Jeff Brown349703e2010-06-22 01:27:15 -07001173 }
1174
1175 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001176 in->current.y = in->accumulator.absY;
Jeff Brown349703e2010-06-22 01:27:15 -07001177 }
1178
1179 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001180 in->current.pressure = in->accumulator.absPressure;
Jeff Brown349703e2010-06-22 01:27:15 -07001181 }
1182
1183 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001184 in->current.size = in->accumulator.absToolWidth;
1185 }
1186
1187 out->clear();
1188
1189 if (in->current.down) {
1190 out->pointerCount = 1;
1191 out->pointers[0].id = 0;
1192 out->pointers[0].x = in->current.x;
1193 out->pointers[0].y = in->current.y;
1194 out->pointers[0].pressure = in->current.pressure;
1195 out->pointers[0].size = in->current.size;
1196 out->idToIndex[0] = 0;
1197 out->idBits.markBit(0);
1198 }
1199
1200 onTouchScreenChanged(when, device, true);
1201}
1202
1203void InputReader::onTouchScreenChanged(nsecs_t when,
1204 InputDevice* device, bool havePointerIds) {
1205 /* Apply policy */
1206
1207 int32_t policyActions = mPolicy->interceptTouch(when);
1208
1209 uint32_t policyFlags = 0;
1210 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1211 device->touchScreen.lastTouch.clear();
1212 return; // event dropped
1213 }
1214
1215 /* Preprocess pointer data */
1216
1217 if (device->touchScreen.parameters.useBadTouchFilter) {
1218 if (device->touchScreen.applyBadTouchFilter()) {
1219 havePointerIds = false;
1220 }
1221 }
1222
1223 if (device->touchScreen.parameters.useJumpyTouchFilter) {
1224 if (device->touchScreen.applyJumpyTouchFilter()) {
1225 havePointerIds = false;
1226 }
1227 }
1228
1229 if (! havePointerIds) {
1230 device->touchScreen.calculatePointerIds();
1231 }
1232
1233 InputDevice::TouchData temp;
1234 InputDevice::TouchData* savedTouch;
1235 if (device->touchScreen.parameters.useAveragingTouchFilter) {
1236 temp.copyFrom(device->touchScreen.currentTouch);
1237 savedTouch = & temp;
1238
1239 device->touchScreen.applyAveragingTouchFilter();
1240 } else {
1241 savedTouch = & device->touchScreen.currentTouch;
1242 }
1243
1244 /* Process virtual keys or touches */
1245
1246 if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
1247 dispatchTouches(when, device, policyFlags);
1248 }
1249
1250 // Copy current touch to last touch in preparation for the next cycle.
1251 device->touchScreen.lastTouch.copyFrom(*savedTouch);
1252}
1253
1254bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
1255 InputDevice* device, uint32_t policyFlags) {
1256 if (device->touchScreen.currentVirtualKey.down) {
1257 if (device->touchScreen.currentTouch.pointerCount == 0) {
1258 // Pointer went up while virtual key was down. Send key up event.
1259 device->touchScreen.currentVirtualKey.down = false;
1260
1261#if DEBUG_VIRTUAL_KEYS
1262 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1263 device->touchScreen.currentVirtualKey.keyCode,
1264 device->touchScreen.currentVirtualKey.scanCode);
1265#endif
1266
1267 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
1268 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
1269 return true; // consumed
1270 }
1271
1272 int32_t x = device->touchScreen.currentTouch.pointers[0].x;
1273 int32_t y = device->touchScreen.currentTouch.pointers[0].y;
Jeff Brown5c225b12010-06-16 01:53:36 -07001274 if (device->touchScreen.isPointInsideDisplay(x, y)
1275 || device->touchScreen.currentTouch.pointerCount != 1) {
1276 // Pointer moved inside the display area or another pointer also went down.
1277 // Send key cancellation.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001278 device->touchScreen.currentVirtualKey.down = false;
1279
1280#if DEBUG_VIRTUAL_KEYS
1281 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1282 device->touchScreen.currentVirtualKey.keyCode,
1283 device->touchScreen.currentVirtualKey.scanCode);
1284#endif
1285
1286 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
1287 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1288 | KEY_EVENT_FLAG_CANCELED);
1289
1290 // Clear the last touch data so we will consider the pointer as having just been
1291 // pressed down when generating subsequent motion events.
1292 device->touchScreen.lastTouch.clear();
1293 return false; // not consumed
1294 }
Jeff Brown5c225b12010-06-16 01:53:36 -07001295 } else if (device->touchScreen.currentTouch.pointerCount == 1
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001296 && device->touchScreen.lastTouch.pointerCount == 0) {
1297 int32_t x = device->touchScreen.currentTouch.pointers[0].x;
1298 int32_t y = device->touchScreen.currentTouch.pointers[0].y;
1299 for (size_t i = 0; i < device->touchScreen.virtualKeys.size(); i++) {
1300 const InputDevice::VirtualKey& virtualKey = device->touchScreen.virtualKeys[i];
1301
1302#if DEBUG_VIRTUAL_KEYS
1303 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
1304 "left=%d, top=%d, right=%d, bottom=%d",
1305 x, y,
1306 virtualKey.keyCode, virtualKey.scanCode,
1307 virtualKey.hitLeft, virtualKey.hitTop,
1308 virtualKey.hitRight, virtualKey.hitBottom);
1309#endif
1310
1311 if (virtualKey.isHit(x, y)) {
1312 device->touchScreen.currentVirtualKey.down = true;
1313 device->touchScreen.currentVirtualKey.downTime = when;
1314 device->touchScreen.currentVirtualKey.keyCode = virtualKey.keyCode;
1315 device->touchScreen.currentVirtualKey.scanCode = virtualKey.scanCode;
1316
1317#if DEBUG_VIRTUAL_KEYS
1318 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1319 device->touchScreen.currentVirtualKey.keyCode,
1320 device->touchScreen.currentVirtualKey.scanCode);
1321#endif
1322
1323 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
1324 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
1325 return true; // consumed
1326 }
1327 }
1328 }
1329
1330 return false; // not consumed
1331}
1332
1333void InputReader::dispatchVirtualKey(nsecs_t when,
1334 InputDevice* device, uint32_t policyFlags,
1335 int32_t keyEventAction, int32_t keyEventFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -07001336 updateExportedVirtualKeyState();
1337
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001338 int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
1339 int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
1340 nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
1341 int32_t metaState = globalMetaState();
1342
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001343 mPolicy->virtualKeyFeedback(when, device->id, keyEventAction, keyEventFlags,
1344 keyCode, scanCode, metaState, downTime);
1345
Jeff Brown349703e2010-06-22 01:27:15 -07001346 int32_t policyActions = mPolicy->interceptKey(when, device->id,
1347 keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
1348
1349 if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1350 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
1351 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1352 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001353}
1354
1355void InputReader::dispatchTouches(nsecs_t when,
1356 InputDevice* device, uint32_t policyFlags) {
1357 uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
1358 uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
1359 if (currentPointerCount == 0 && lastPointerCount == 0) {
1360 return; // nothing to do!
1361 }
1362
1363 BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
1364 BitSet32 lastIdBits = device->touchScreen.lastTouch.idBits;
1365
1366 if (currentIdBits == lastIdBits) {
1367 // No pointer id changes so this is a move event.
1368 // The dispatcher takes care of batching moves so we don't have to deal with that here.
1369 int32_t motionEventAction = MOTION_EVENT_ACTION_MOVE;
1370 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
1371 currentIdBits, motionEventAction);
1372 } else {
1373 // There may be pointers going up and pointers going down at the same time when pointer
1374 // ids are reported by the device driver.
1375 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1376 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1377 BitSet32 activeIdBits(lastIdBits.value);
1378
1379 while (! upIdBits.isEmpty()) {
1380 uint32_t upId = upIdBits.firstMarkedBit();
1381 upIdBits.clearBit(upId);
1382 BitSet32 oldActiveIdBits = activeIdBits;
1383 activeIdBits.clearBit(upId);
1384
1385 int32_t motionEventAction;
1386 if (activeIdBits.isEmpty()) {
1387 motionEventAction = MOTION_EVENT_ACTION_UP;
1388 } else {
1389 motionEventAction = MOTION_EVENT_ACTION_POINTER_UP
1390 | (upId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1391 }
1392
1393 dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
1394 oldActiveIdBits, motionEventAction);
1395 }
1396
1397 while (! downIdBits.isEmpty()) {
1398 uint32_t downId = downIdBits.firstMarkedBit();
1399 downIdBits.clearBit(downId);
1400 BitSet32 oldActiveIdBits = activeIdBits;
1401 activeIdBits.markBit(downId);
1402
1403 int32_t motionEventAction;
1404 if (oldActiveIdBits.isEmpty()) {
1405 motionEventAction = MOTION_EVENT_ACTION_DOWN;
1406 device->touchScreen.downTime = when;
1407 } else {
1408 motionEventAction = MOTION_EVENT_ACTION_POINTER_DOWN
1409 | (downId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1410 }
1411
1412 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
1413 activeIdBits, motionEventAction);
1414 }
1415 }
1416}
1417
1418void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
1419 InputDevice::TouchData* touch, BitSet32 idBits,
1420 int32_t motionEventAction) {
1421 int32_t orientedWidth, orientedHeight;
1422 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001423 case InputReaderPolicyInterface::ROTATION_90:
1424 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001425 orientedWidth = mDisplayHeight;
1426 orientedHeight = mDisplayWidth;
1427 break;
1428 default:
1429 orientedWidth = mDisplayWidth;
1430 orientedHeight = mDisplayHeight;
1431 break;
1432 }
1433
1434 uint32_t pointerCount = 0;
1435 int32_t pointerIds[MAX_POINTERS];
1436 PointerCoords pointerCoords[MAX_POINTERS];
1437
1438 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1439 // display coordinates (PointerCoords) and adjust for display orientation.
1440 while (! idBits.isEmpty()) {
1441 uint32_t id = idBits.firstMarkedBit();
1442 idBits.clearBit(id);
1443 uint32_t index = touch->idToIndex[id];
1444
1445 float x = (float(touch->pointers[index].x)
1446 - device->touchScreen.parameters.xAxis.minValue)
1447 * device->touchScreen.precalculated.xScale;
1448 float y = (float(touch->pointers[index].y)
1449 - device->touchScreen.parameters.yAxis.minValue)
1450 * device->touchScreen.precalculated.yScale;
1451 float pressure = (float(touch->pointers[index].pressure)
1452 - device->touchScreen.parameters.pressureAxis.minValue)
1453 * device->touchScreen.precalculated.pressureScale;
1454 float size = (float(touch->pointers[index].size)
1455 - device->touchScreen.parameters.sizeAxis.minValue)
1456 * device->touchScreen.precalculated.sizeScale;
1457
1458 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001459 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001460 float xTemp = x;
1461 x = y;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001462 y = mDisplayWidth - xTemp;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001463 break;
1464 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001465 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001466 x = mDisplayWidth - x;
1467 y = mDisplayHeight - y;
1468 break;
1469 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001470 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001471 float xTemp = x;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001472 x = mDisplayHeight - y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001473 y = xTemp;
1474 break;
1475 }
1476 }
1477
1478 pointerIds[pointerCount] = int32_t(id);
1479
1480 pointerCoords[pointerCount].x = x;
1481 pointerCoords[pointerCount].y = y;
1482 pointerCoords[pointerCount].pressure = pressure;
1483 pointerCoords[pointerCount].size = size;
1484
1485 pointerCount += 1;
1486 }
1487
1488 // Check edge flags by looking only at the first pointer since the flags are
1489 // global to the event.
1490 // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
1491 int32_t motionEventEdgeFlags = 0;
1492 if (motionEventAction == MOTION_EVENT_ACTION_DOWN) {
1493 if (pointerCoords[0].x <= 0) {
1494 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_LEFT;
1495 } else if (pointerCoords[0].x >= orientedWidth) {
1496 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_RIGHT;
1497 }
1498 if (pointerCoords[0].y <= 0) {
1499 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_TOP;
1500 } else if (pointerCoords[0].y >= orientedHeight) {
1501 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_BOTTOM;
1502 }
1503 }
1504
1505 nsecs_t downTime = device->touchScreen.downTime;
1506 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TOUCH, policyFlags,
1507 motionEventAction, globalMetaState(), motionEventEdgeFlags,
1508 pointerCount, pointerIds, pointerCoords,
1509 0, 0, downTime);
1510}
1511
1512void InputReader::onTrackballStateChanged(nsecs_t when,
1513 InputDevice* device) {
1514 static const uint32_t DELTA_FIELDS =
1515 InputDevice::TrackballState::Accumulator::FIELD_REL_X
1516 | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
1517
1518 /* Refresh display properties so we can trackball moves according to display orientation */
1519
1520 if (! refreshDisplayProperties()) {
1521 return;
1522 }
1523
1524 /* Update device state */
1525
1526 uint32_t fields = device->trackball.accumulator.fields;
1527 bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001528 bool deltaChanged = fields & DELTA_FIELDS;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001529
1530 bool down;
1531 if (downChanged) {
1532 if (device->trackball.accumulator.btnMouse) {
1533 device->trackball.current.down = true;
1534 device->trackball.current.downTime = when;
1535 down = true;
1536 } else {
1537 device->trackball.current.down = false;
1538 down = false;
1539 }
1540 } else {
1541 down = device->trackball.current.down;
1542 }
1543
1544 /* Apply policy */
1545
1546 int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
1547
1548 uint32_t policyFlags = 0;
1549 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1550 return; // event dropped
1551 }
1552
1553 /* Enqueue motion event for dispatch */
1554
1555 int32_t motionEventAction;
1556 if (downChanged) {
1557 motionEventAction = down ? MOTION_EVENT_ACTION_DOWN : MOTION_EVENT_ACTION_UP;
1558 } else {
1559 motionEventAction = MOTION_EVENT_ACTION_MOVE;
1560 }
1561
1562 int32_t pointerId = 0;
1563 PointerCoords pointerCoords;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001564 pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
1565 ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
1566 pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
1567 ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001568 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
1569 pointerCoords.size = 0;
1570
1571 float temp;
1572 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001573 case InputReaderPolicyInterface::ROTATION_90:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001574 temp = pointerCoords.x;
1575 pointerCoords.x = pointerCoords.y;
1576 pointerCoords.y = - temp;
1577 break;
1578
Jeff Brown9c3cda02010-06-15 01:31:58 -07001579 case InputReaderPolicyInterface::ROTATION_180:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001580 pointerCoords.x = - pointerCoords.x;
1581 pointerCoords.y = - pointerCoords.y;
1582 break;
1583
Jeff Brown9c3cda02010-06-15 01:31:58 -07001584 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001585 temp = pointerCoords.x;
1586 pointerCoords.x = - pointerCoords.y;
1587 pointerCoords.y = temp;
1588 break;
1589 }
1590
1591 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TRACKBALL, policyFlags,
1592 motionEventAction, globalMetaState(), MOTION_EVENT_EDGE_FLAG_NONE,
1593 1, & pointerId, & pointerCoords,
1594 device->trackball.precalculated.xPrecision,
1595 device->trackball.precalculated.yPrecision,
1596 device->trackball.current.downTime);
1597}
1598
1599void InputReader::onConfigurationChanged(nsecs_t when) {
1600 // Reset global meta state because it depends on the list of all configured devices.
1601 resetGlobalMetaState();
1602
1603 // Reset virtual keys, just in case.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001604 updateExportedVirtualKeyState();
1605
1606 // Update input configuration.
1607 updateExportedInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001608
1609 // Enqueue configuration changed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001610 mDispatcher->notifyConfigurationChanged(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001611}
1612
1613bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
1614 int32_t policyActions, uint32_t* policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001615 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001616 mDispatcher->notifyAppSwitchComing(when);
1617 }
1618
Jeff Brown9c3cda02010-06-15 01:31:58 -07001619 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001620 *policyFlags |= POLICY_FLAG_WOKE_HERE;
1621 }
1622
Jeff Brown9c3cda02010-06-15 01:31:58 -07001623 if (policyActions & InputReaderPolicyInterface::ACTION_BRIGHT_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001624 *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
1625 }
1626
Jeff Brown349703e2010-06-22 01:27:15 -07001627 if (policyActions & InputReaderPolicyInterface::ACTION_INTERCEPT_DISPATCH) {
1628 *policyFlags |= POLICY_FLAG_INTERCEPT_DISPATCH;
1629 }
1630
Jeff Brown9c3cda02010-06-15 01:31:58 -07001631 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001632}
1633
1634void InputReader::resetDisplayProperties() {
1635 mDisplayWidth = mDisplayHeight = -1;
1636 mDisplayOrientation = -1;
1637}
1638
1639bool InputReader::refreshDisplayProperties() {
1640 int32_t newWidth, newHeight, newOrientation;
1641 if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
1642 if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
1643 LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
1644 mDisplayWidth, mDisplayHeight, newWidth, newHeight);
1645
1646 mDisplayWidth = newWidth;
1647 mDisplayHeight = newHeight;
1648
1649 for (size_t i = 0; i < mDevices.size(); i++) {
1650 configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
1651 }
1652 }
1653
1654 mDisplayOrientation = newOrientation;
1655 return true;
1656 } else {
1657 resetDisplayProperties();
1658 return false;
1659 }
1660}
1661
1662InputDevice* InputReader::getDevice(int32_t deviceId) {
1663 ssize_t index = mDevices.indexOfKey(deviceId);
1664 return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
1665}
1666
1667InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
1668 InputDevice* device = getDevice(deviceId);
1669 return device && ! device->ignored ? device : NULL;
1670}
1671
1672void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
1673 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
1674 String8 name = mEventHub->getDeviceName(deviceId);
1675 InputDevice* device = new InputDevice(deviceId, classes, name);
1676
1677 if (classes != 0) {
1678 LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
1679 device->name.string(), device->classes);
1680
1681 configureDevice(device);
1682 } else {
1683 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
1684 device->name.string());
1685
1686 device->ignored = true;
1687 }
1688
1689 device->reset();
1690
1691 mDevices.add(deviceId, device);
1692
1693 if (! device->ignored) {
1694 onConfigurationChanged(when);
1695 }
1696}
1697
1698void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
1699 mDevices.removeItem(device->id);
1700
1701 if (! device->ignored) {
1702 LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
1703 device->name.string(), device->classes);
1704
1705 onConfigurationChanged(when);
1706 } else {
1707 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
1708 device->name.string());
1709 }
1710
1711 delete device;
1712}
1713
1714void InputReader::configureDevice(InputDevice* device) {
1715 if (device->isMultiTouchScreen()) {
1716 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
1717 & device->touchScreen.parameters.xAxis);
1718 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
1719 & device->touchScreen.parameters.yAxis);
1720 configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
1721 & device->touchScreen.parameters.pressureAxis);
1722 configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
1723 & device->touchScreen.parameters.sizeAxis);
1724 } else if (device->isSingleTouchScreen()) {
1725 configureAbsoluteAxisInfo(device, ABS_X, "X",
1726 & device->touchScreen.parameters.xAxis);
1727 configureAbsoluteAxisInfo(device, ABS_Y, "Y",
1728 & device->touchScreen.parameters.yAxis);
1729 configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
1730 & device->touchScreen.parameters.pressureAxis);
1731 configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
1732 & device->touchScreen.parameters.sizeAxis);
1733 }
1734
1735 if (device->isTouchScreen()) {
1736 device->touchScreen.parameters.useBadTouchFilter =
1737 mPolicy->filterTouchEvents();
1738 device->touchScreen.parameters.useAveragingTouchFilter =
1739 mPolicy->filterTouchEvents();
1740 device->touchScreen.parameters.useJumpyTouchFilter =
1741 mPolicy->filterJumpyTouchEvents();
1742
1743 device->touchScreen.precalculated.pressureScale =
1744 1.0f / device->touchScreen.parameters.pressureAxis.range;
1745 device->touchScreen.precalculated.sizeScale =
1746 1.0f / device->touchScreen.parameters.sizeAxis.range;
1747 }
1748
1749 if (device->isTrackball()) {
1750 device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1751 device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1752 device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1753 device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1754 }
1755
1756 configureDeviceForCurrentDisplaySize(device);
1757}
1758
1759void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
1760 if (device->isTouchScreen()) {
1761 if (mDisplayWidth < 0) {
1762 LOGD("Skipping part of touch screen configuration since display size is unknown.");
1763 } else {
1764 LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
1765 device->name.string());
1766 configureVirtualKeys(device);
1767
1768 device->touchScreen.precalculated.xScale =
1769 float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
1770 device->touchScreen.precalculated.yScale =
1771 float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
1772 }
1773 }
1774}
1775
1776void InputReader::configureVirtualKeys(InputDevice* device) {
1777 device->touchScreen.virtualKeys.clear();
1778
Jeff Brown9c3cda02010-06-15 01:31:58 -07001779 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001780 mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
1781 if (virtualKeyDefinitions.size() == 0) {
1782 return;
1783 }
1784
1785 device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1786
1787 int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
1788 int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
1789 int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
1790 int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
1791
1792 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001793 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001794 virtualKeyDefinitions[i];
1795
1796 device->touchScreen.virtualKeys.add();
1797 InputDevice::VirtualKey& virtualKey =
1798 device->touchScreen.virtualKeys.editTop();
1799
1800 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1801 int32_t keyCode;
1802 uint32_t flags;
1803 if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
1804 & keyCode, & flags)) {
1805 LOGI(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1806 device->touchScreen.virtualKeys.pop(); // drop the key
1807 continue;
1808 }
1809
1810 virtualKey.keyCode = keyCode;
1811 virtualKey.flags = flags;
1812
1813 // convert the key definition's display coordinates into touch coordinates for a hit box
1814 int32_t halfWidth = virtualKeyDefinition.width / 2;
1815 int32_t halfHeight = virtualKeyDefinition.height / 2;
1816
1817 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1818 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1819 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1820 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1821 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1822 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1823 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1824 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1825
1826 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1827 virtualKey.scanCode, virtualKey.keyCode,
1828 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1829 }
1830}
1831
1832void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
1833 int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
1834 if (! mEventHub->getAbsoluteInfo(device->id, axis,
1835 & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
1836 out->range = out->maxValue - out->minValue;
1837 if (out->range != 0) {
1838 LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
1839 name, out->minValue, out->maxValue, out->flat, out->fuzz);
1840 return;
1841 }
1842 }
1843
1844 out->minValue = 0;
1845 out->maxValue = 0;
1846 out->flat = 0;
1847 out->fuzz = 0;
1848 out->range = 0;
1849 LOGI(" %s: unknown axis values, setting to zero", name);
1850}
1851
Jeff Brown9c3cda02010-06-15 01:31:58 -07001852void InputReader::configureExcludedDevices() {
1853 Vector<String8> excludedDeviceNames;
1854 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
1855
1856 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
1857 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
1858 }
1859}
1860
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001861void InputReader::resetGlobalMetaState() {
1862 mGlobalMetaState = -1;
1863}
1864
1865int32_t InputReader::globalMetaState() {
1866 if (mGlobalMetaState == -1) {
1867 mGlobalMetaState = 0;
1868 for (size_t i = 0; i < mDevices.size(); i++) {
1869 InputDevice* device = mDevices.valueAt(i);
1870 if (device->isKeyboard()) {
1871 mGlobalMetaState |= device->keyboard.current.metaState;
1872 }
1873 }
1874 }
1875 return mGlobalMetaState;
1876}
1877
Jeff Brown9c3cda02010-06-15 01:31:58 -07001878void InputReader::updateExportedVirtualKeyState() {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001879 int32_t keyCode = -1, scanCode = -1;
1880
1881 for (size_t i = 0; i < mDevices.size(); i++) {
1882 InputDevice* device = mDevices.valueAt(i);
1883 if (device->isTouchScreen()) {
1884 if (device->touchScreen.currentVirtualKey.down) {
1885 keyCode = device->touchScreen.currentVirtualKey.keyCode;
1886 scanCode = device->touchScreen.currentVirtualKey.scanCode;
1887 }
1888 }
1889 }
1890
Jeff Brown9c3cda02010-06-15 01:31:58 -07001891 { // acquire exported state lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001892 AutoMutex _l(mExportedStateLock);
1893
Jeff Brown9c3cda02010-06-15 01:31:58 -07001894 mExportedVirtualKeyCode = keyCode;
1895 mExportedVirtualScanCode = scanCode;
1896 } // release exported state lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001897}
1898
1899bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001900 { // acquire exported state lock
1901 AutoMutex _l(mExportedStateLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001902
Jeff Brown9c3cda02010-06-15 01:31:58 -07001903 *outKeyCode = mExportedVirtualKeyCode;
1904 *outScanCode = mExportedVirtualScanCode;
1905 return mExportedVirtualKeyCode != -1;
1906 } // release exported state lock
1907}
1908
1909void InputReader::updateExportedInputConfiguration() {
1910 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
1911 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
1912 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
1913
1914 for (size_t i = 0; i < mDevices.size(); i++) {
1915 InputDevice* device = mDevices.valueAt(i);
1916 int32_t deviceClasses = device->classes;
1917
1918 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
1919 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
1920 }
1921 if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
1922 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
1923 }
1924 if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
1925 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
1926 } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
1927 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
1928 }
1929 }
1930
1931 { // acquire exported state lock
1932 AutoMutex _l(mExportedStateLock);
1933
1934 mExportedInputConfiguration.touchScreen = touchScreenConfig;
1935 mExportedInputConfiguration.keyboard = keyboardConfig;
1936 mExportedInputConfiguration.navigation = navigationConfig;
1937 } // release exported state lock
1938}
1939
1940void InputReader::getCurrentInputConfiguration(InputConfiguration* outConfiguration) const {
1941 { // acquire exported state lock
1942 AutoMutex _l(mExportedStateLock);
1943
1944 *outConfiguration = mExportedInputConfiguration;
1945 } // release exported state lock
1946}
1947
1948int32_t InputReader::getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
1949 int32_t scanCode) const {
1950 { // acquire exported state lock
1951 AutoMutex _l(mExportedStateLock);
1952
1953 if (mExportedVirtualScanCode == scanCode) {
1954 return KEY_STATE_VIRTUAL;
1955 }
1956 } // release exported state lock
1957
1958 return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
1959}
1960
1961int32_t InputReader::getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
1962 int32_t keyCode) const {
1963 { // acquire exported state lock
1964 AutoMutex _l(mExportedStateLock);
1965
1966 if (mExportedVirtualKeyCode == keyCode) {
1967 return KEY_STATE_VIRTUAL;
1968 }
1969 } // release exported state lock
1970
1971 return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
1972}
1973
1974int32_t InputReader::getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
1975 int32_t sw) const {
1976 return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
1977}
1978
1979bool InputReader::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
1980 return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001981}
1982
1983
1984// --- InputReaderThread ---
1985
1986InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
1987 Thread(/*canCallJava*/ true), mReader(reader) {
1988}
1989
1990InputReaderThread::~InputReaderThread() {
1991}
1992
1993bool InputReaderThread::threadLoop() {
1994 mReader->loopOnce();
1995 return true;
1996}
1997
1998} // namespace android