blob: 899027c9b92089202b8ba7ca4bb6452da275684f [file] [log] [blame]
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700252 heapSize += 1;
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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
749
750// --- InputDevice::SingleTouchScreenState ---
751
752void InputDevice::SingleTouchScreenState::reset() {
753 accumulator.clear();
754 current.down = false;
755 current.x = 0;
756 current.y = 0;
757 current.pressure = 0;
758 current.size = 0;
759}
760
761
762// --- InputDevice::MultiTouchScreenState ---
763
764void InputDevice::MultiTouchScreenState::reset() {
765 accumulator.clear();
766}
767
768
769// --- InputReader ---
770
771InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700772 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700773 const sp<InputDispatcherInterface>& dispatcher) :
774 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700775 configureExcludedDevices();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700776 resetGlobalMetaState();
777 resetDisplayProperties();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700778 updateExportedVirtualKeyState();
Jeff Brown46b9ac02010-04-22 18:58:52 -0700779}
780
781InputReader::~InputReader() {
782 for (size_t i = 0; i < mDevices.size(); i++) {
783 delete mDevices.valueAt(i);
784 }
785}
786
787void InputReader::loopOnce() {
788 RawEvent rawEvent;
789 mEventHub->getEvent(& rawEvent.deviceId, & rawEvent.type, & rawEvent.scanCode,
790 & rawEvent.keyCode, & rawEvent.flags, & rawEvent.value, & rawEvent.when);
791
792 // Replace the event timestamp so it is in same timebase as java.lang.System.nanoTime()
793 // and android.os.SystemClock.uptimeMillis() as expected by the rest of the system.
794 rawEvent.when = systemTime(SYSTEM_TIME_MONOTONIC);
795
796#if DEBUG_RAW_EVENTS
797 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
798 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
799 rawEvent.value);
800#endif
801
802 process(& rawEvent);
803}
804
805void InputReader::process(const RawEvent* rawEvent) {
806 switch (rawEvent->type) {
807 case EventHubInterface::DEVICE_ADDED:
808 handleDeviceAdded(rawEvent);
809 break;
810
811 case EventHubInterface::DEVICE_REMOVED:
812 handleDeviceRemoved(rawEvent);
813 break;
814
815 case EV_SYN:
816 handleSync(rawEvent);
817 break;
818
819 case EV_KEY:
820 handleKey(rawEvent);
821 break;
822
823 case EV_REL:
824 handleRelativeMotion(rawEvent);
825 break;
826
827 case EV_ABS:
828 handleAbsoluteMotion(rawEvent);
829 break;
830
831 case EV_SW:
832 handleSwitch(rawEvent);
833 break;
834 }
835}
836
837void InputReader::handleDeviceAdded(const RawEvent* rawEvent) {
838 InputDevice* device = getDevice(rawEvent->deviceId);
839 if (device) {
840 LOGW("Ignoring spurious device added event for deviceId %d.", rawEvent->deviceId);
841 return;
842 }
843
844 addDevice(rawEvent->when, rawEvent->deviceId);
845}
846
847void InputReader::handleDeviceRemoved(const RawEvent* rawEvent) {
848 InputDevice* device = getDevice(rawEvent->deviceId);
849 if (! device) {
850 LOGW("Ignoring spurious device removed event for deviceId %d.", rawEvent->deviceId);
851 return;
852 }
853
854 removeDevice(rawEvent->when, device);
855}
856
857void InputReader::handleSync(const RawEvent* rawEvent) {
858 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
859 if (! device) return;
860
861 if (rawEvent->scanCode == SYN_MT_REPORT) {
862 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
863 // We drop pointers with pressure <= 0 since that indicates they are not down.
864 if (device->isMultiTouchScreen()) {
865 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
866
867 if (device->multiTouchScreen.accumulator.pointers[pointerIndex].fields) {
868 if (pointerIndex == MAX_POINTERS) {
869 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
870 MAX_POINTERS);
871 } else {
872 pointerIndex += 1;
873 device->multiTouchScreen.accumulator.pointerCount = pointerIndex;
874 }
875 }
876
877 device->multiTouchScreen.accumulator.pointers[pointerIndex].clear();
878 }
879 } else if (rawEvent->scanCode == SYN_REPORT) {
880 // General Sync: The driver has returned all data for the current event update.
881 if (device->isMultiTouchScreen()) {
882 if (device->multiTouchScreen.accumulator.isDirty()) {
883 onMultiTouchScreenStateChanged(rawEvent->when, device);
884 device->multiTouchScreen.accumulator.clear();
885 }
886 } else if (device->isSingleTouchScreen()) {
887 if (device->singleTouchScreen.accumulator.isDirty()) {
888 onSingleTouchScreenStateChanged(rawEvent->when, device);
889 device->singleTouchScreen.accumulator.clear();
890 }
891 }
892
893 if (device->trackball.accumulator.isDirty()) {
894 onTrackballStateChanged(rawEvent->when, device);
895 device->trackball.accumulator.clear();
896 }
897 }
898}
899
900void InputReader::handleKey(const RawEvent* rawEvent) {
901 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
902 if (! device) return;
903
904 bool down = rawEvent->value != 0;
905 int32_t scanCode = rawEvent->scanCode;
906
907 if (device->isKeyboard() && (scanCode < BTN_FIRST || scanCode > BTN_LAST)) {
908 int32_t keyCode = rawEvent->keyCode;
909 onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
910 } else if (device->isSingleTouchScreen()) {
911 switch (rawEvent->scanCode) {
912 case BTN_TOUCH:
913 device->singleTouchScreen.accumulator.fields |=
914 InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
915 device->singleTouchScreen.accumulator.btnTouch = down;
916 break;
917 }
918 } else if (device->isTrackball()) {
919 switch (rawEvent->scanCode) {
920 case BTN_MOUSE:
921 device->trackball.accumulator.fields |=
922 InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
923 device->trackball.accumulator.btnMouse = down;
924
925 // send the down immediately
926 // XXX this emulates the old behavior of KeyInputQueue, unclear whether it is
927 // necessary or if we can wait until the next sync
928 onTrackballStateChanged(rawEvent->when, device);
929 device->trackball.accumulator.clear();
930 break;
931 }
932 }
933}
934
935void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
936 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
937 if (! device) return;
938
939 if (device->isTrackball()) {
940 switch (rawEvent->scanCode) {
941 case REL_X:
942 device->trackball.accumulator.fields |=
943 InputDevice::TrackballState::Accumulator::FIELD_REL_X;
944 device->trackball.accumulator.relX = rawEvent->value;
945 break;
946 case REL_Y:
947 device->trackball.accumulator.fields |=
948 InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
949 device->trackball.accumulator.relY = rawEvent->value;
950 break;
951 }
952 }
953}
954
955void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
956 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
957 if (! device) return;
958
959 if (device->isMultiTouchScreen()) {
960 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
961 InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
962 & device->multiTouchScreen.accumulator.pointers[pointerIndex];
963
964 switch (rawEvent->scanCode) {
965 case ABS_MT_POSITION_X:
966 pointer->fields |=
967 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
968 pointer->absMTPositionX = rawEvent->value;
969 break;
970 case ABS_MT_POSITION_Y:
971 pointer->fields |=
972 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
973 pointer->absMTPositionY = rawEvent->value;
974 break;
975 case ABS_MT_TOUCH_MAJOR:
976 pointer->fields |=
977 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
978 pointer->absMTTouchMajor = rawEvent->value;
979 break;
980 case ABS_MT_WIDTH_MAJOR:
981 pointer->fields |=
982 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
983 pointer->absMTWidthMajor = rawEvent->value;
984 break;
985 case ABS_MT_TRACKING_ID:
986 pointer->fields |=
987 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
988 pointer->absMTTrackingId = rawEvent->value;
989 break;
990 }
991 } else if (device->isSingleTouchScreen()) {
992 switch (rawEvent->scanCode) {
993 case ABS_X:
994 device->singleTouchScreen.accumulator.fields |=
995 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
996 device->singleTouchScreen.accumulator.absX = rawEvent->value;
997 break;
998 case ABS_Y:
999 device->singleTouchScreen.accumulator.fields |=
1000 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
1001 device->singleTouchScreen.accumulator.absY = rawEvent->value;
1002 break;
1003 case ABS_PRESSURE:
1004 device->singleTouchScreen.accumulator.fields |=
1005 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
1006 device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
1007 break;
1008 case ABS_TOOL_WIDTH:
1009 device->singleTouchScreen.accumulator.fields |=
1010 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
1011 device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
1012 break;
1013 }
1014 }
1015}
1016
1017void InputReader::handleSwitch(const RawEvent* rawEvent) {
1018 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
1019 if (! device) return;
1020
Jeff Brown9c3cda02010-06-15 01:31:58 -07001021 onSwitch(rawEvent->when, device, rawEvent->scanCode, rawEvent->value);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001022}
1023
1024void InputReader::onKey(nsecs_t when, InputDevice* device,
1025 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
1026 /* Refresh display properties so we can rotate key codes according to display orientation */
1027
1028 if (! refreshDisplayProperties()) {
1029 return;
1030 }
1031
1032 /* Update device state */
1033
1034 int32_t oldMetaState = device->keyboard.current.metaState;
1035 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
1036 if (oldMetaState != newMetaState) {
1037 device->keyboard.current.metaState = newMetaState;
1038 resetGlobalMetaState();
1039 }
1040
1041 // FIXME if we send a down event about a rotated key press we should ensure that we send
1042 // a corresponding up event about the rotated key press even if the orientation
1043 // has changed in the meantime
1044 keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
1045
1046 if (down) {
1047 device->keyboard.current.downTime = when;
1048 }
1049
1050 /* Apply policy */
1051
1052 int32_t policyActions = mPolicy->interceptKey(when, device->id,
1053 down, keyCode, scanCode, policyFlags);
1054
1055 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1056 return; // event dropped
1057 }
1058
1059 /* Enqueue key event for dispatch */
1060
1061 int32_t keyEventAction;
1062 if (down) {
1063 device->keyboard.current.downTime = when;
1064 keyEventAction = KEY_EVENT_ACTION_DOWN;
1065 } else {
1066 keyEventAction = KEY_EVENT_ACTION_UP;
1067 }
1068
1069 int32_t keyEventFlags = KEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001070 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001071 keyEventFlags = keyEventFlags | KEY_EVENT_FLAG_WOKE_HERE;
1072 }
1073
1074 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
1075 keyEventAction, keyEventFlags, keyCode, scanCode,
1076 device->keyboard.current.metaState,
1077 device->keyboard.current.downTime);
1078}
1079
Jeff Brown9c3cda02010-06-15 01:31:58 -07001080void InputReader::onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode,
1081 int32_t switchValue) {
1082 int32_t policyActions = mPolicy->interceptSwitch(when, switchCode, switchValue);
1083
1084 uint32_t policyFlags = 0;
1085 applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001086}
1087
1088void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
1089 InputDevice* device) {
1090 static const uint32_t REQUIRED_FIELDS =
1091 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
1092 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
1093 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
1094 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
1095
1096 /* Refresh display properties so we can map touch screen coords into display coords */
1097
1098 if (! refreshDisplayProperties()) {
1099 return;
1100 }
1101
1102 /* Update device state */
1103
1104 InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
1105 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
1106
1107 uint32_t inCount = in->accumulator.pointerCount;
1108 uint32_t outCount = 0;
1109 bool havePointerIds = true;
1110
1111 out->clear();
1112
1113 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
1114 uint32_t fields = in->accumulator.pointers[inIndex].fields;
1115
1116 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
1117#if DEBUG_POINTERS
1118 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
1119 inIndex, fields);
1120 continue;
1121#endif
1122 }
1123
1124 if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
1125 // Pointer is not down. Drop it.
1126 continue;
1127 }
1128
1129 // FIXME assignment of pressure may be incorrect, probably better to let
1130 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
1131 // isn't quite right either. Should be using touch for that.
1132 out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
1133 out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
1134 out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
1135 out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
1136
1137 if (havePointerIds) {
1138 if (fields & InputDevice::MultiTouchScreenState::Accumulator::
1139 FIELD_ABS_MT_TRACKING_ID) {
1140 uint32_t id = uint32_t(in->accumulator.pointers[inIndex].absMTTrackingId);
1141
1142 if (id > MAX_POINTER_ID) {
1143#if DEBUG_POINTERS
1144 LOGD("Pointers: Ignoring driver provided pointer id %d because "
1145 "it is larger than max supported id %d for optimizations",
1146 id, MAX_POINTER_ID);
1147#endif
1148 havePointerIds = false;
1149 }
1150 else {
1151 out->pointers[outCount].id = id;
1152 out->idToIndex[id] = outCount;
1153 out->idBits.markBit(id);
1154 }
1155 } else {
1156 havePointerIds = false;
1157 }
1158 }
1159
1160 outCount += 1;
1161 }
1162
1163 out->pointerCount = outCount;
1164
1165 onTouchScreenChanged(when, device, havePointerIds);
1166}
1167
1168void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
1169 InputDevice* device) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001170 /* Refresh display properties so we can map touch screen coords into display coords */
1171
1172 if (! refreshDisplayProperties()) {
1173 return;
1174 }
1175
1176 /* Update device state */
1177
1178 InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
1179 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
1180
1181 uint32_t fields = in->accumulator.fields;
1182
1183 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
1184 in->current.down = in->accumulator.btnTouch;
1185 }
1186
Jeff Brown349703e2010-06-22 01:27:15 -07001187 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001188 in->current.x = in->accumulator.absX;
Jeff Brown349703e2010-06-22 01:27:15 -07001189 }
1190
1191 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001192 in->current.y = in->accumulator.absY;
Jeff Brown349703e2010-06-22 01:27:15 -07001193 }
1194
1195 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001196 in->current.pressure = in->accumulator.absPressure;
Jeff Brown349703e2010-06-22 01:27:15 -07001197 }
1198
1199 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001200 in->current.size = in->accumulator.absToolWidth;
1201 }
1202
1203 out->clear();
1204
1205 if (in->current.down) {
1206 out->pointerCount = 1;
1207 out->pointers[0].id = 0;
1208 out->pointers[0].x = in->current.x;
1209 out->pointers[0].y = in->current.y;
1210 out->pointers[0].pressure = in->current.pressure;
1211 out->pointers[0].size = in->current.size;
1212 out->idToIndex[0] = 0;
1213 out->idBits.markBit(0);
1214 }
1215
1216 onTouchScreenChanged(when, device, true);
1217}
1218
1219void InputReader::onTouchScreenChanged(nsecs_t when,
1220 InputDevice* device, bool havePointerIds) {
1221 /* Apply policy */
1222
1223 int32_t policyActions = mPolicy->interceptTouch(when);
1224
1225 uint32_t policyFlags = 0;
1226 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1227 device->touchScreen.lastTouch.clear();
1228 return; // event dropped
1229 }
1230
1231 /* Preprocess pointer data */
1232
1233 if (device->touchScreen.parameters.useBadTouchFilter) {
1234 if (device->touchScreen.applyBadTouchFilter()) {
1235 havePointerIds = false;
1236 }
1237 }
1238
1239 if (device->touchScreen.parameters.useJumpyTouchFilter) {
1240 if (device->touchScreen.applyJumpyTouchFilter()) {
1241 havePointerIds = false;
1242 }
1243 }
1244
1245 if (! havePointerIds) {
1246 device->touchScreen.calculatePointerIds();
1247 }
1248
1249 InputDevice::TouchData temp;
1250 InputDevice::TouchData* savedTouch;
1251 if (device->touchScreen.parameters.useAveragingTouchFilter) {
1252 temp.copyFrom(device->touchScreen.currentTouch);
1253 savedTouch = & temp;
1254
1255 device->touchScreen.applyAveragingTouchFilter();
1256 } else {
1257 savedTouch = & device->touchScreen.currentTouch;
1258 }
1259
1260 /* Process virtual keys or touches */
1261
1262 if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
1263 dispatchTouches(when, device, policyFlags);
1264 }
1265
1266 // Copy current touch to last touch in preparation for the next cycle.
1267 device->touchScreen.lastTouch.copyFrom(*savedTouch);
1268}
1269
1270bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
1271 InputDevice* device, uint32_t policyFlags) {
1272 if (device->touchScreen.currentVirtualKey.down) {
1273 if (device->touchScreen.currentTouch.pointerCount == 0) {
1274 // Pointer went up while virtual key was down. Send key up event.
1275 device->touchScreen.currentVirtualKey.down = false;
1276
1277#if DEBUG_VIRTUAL_KEYS
1278 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
1279 device->touchScreen.currentVirtualKey.keyCode,
1280 device->touchScreen.currentVirtualKey.scanCode);
1281#endif
1282
1283 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
1284 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
1285 return true; // consumed
1286 }
1287
1288 int32_t x = device->touchScreen.currentTouch.pointers[0].x;
1289 int32_t y = device->touchScreen.currentTouch.pointers[0].y;
Jeff Brown5c225b12010-06-16 01:53:36 -07001290 if (device->touchScreen.isPointInsideDisplay(x, y)
1291 || device->touchScreen.currentTouch.pointerCount != 1) {
1292 // Pointer moved inside the display area or another pointer also went down.
1293 // Send key cancellation.
Jeff Brown46b9ac02010-04-22 18:58:52 -07001294 device->touchScreen.currentVirtualKey.down = false;
1295
1296#if DEBUG_VIRTUAL_KEYS
1297 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
1298 device->touchScreen.currentVirtualKey.keyCode,
1299 device->touchScreen.currentVirtualKey.scanCode);
1300#endif
1301
1302 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
1303 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
1304 | KEY_EVENT_FLAG_CANCELED);
1305
1306 // Clear the last touch data so we will consider the pointer as having just been
1307 // pressed down when generating subsequent motion events.
1308 device->touchScreen.lastTouch.clear();
1309 return false; // not consumed
1310 }
Jeff Brown5c225b12010-06-16 01:53:36 -07001311 } else if (device->touchScreen.currentTouch.pointerCount == 1
Jeff Brown46b9ac02010-04-22 18:58:52 -07001312 && device->touchScreen.lastTouch.pointerCount == 0) {
1313 int32_t x = device->touchScreen.currentTouch.pointers[0].x;
1314 int32_t y = device->touchScreen.currentTouch.pointers[0].y;
1315 for (size_t i = 0; i < device->touchScreen.virtualKeys.size(); i++) {
1316 const InputDevice::VirtualKey& virtualKey = device->touchScreen.virtualKeys[i];
1317
1318#if DEBUG_VIRTUAL_KEYS
1319 LOGD("VirtualKeys: Hit test (%d, %d): keyCode=%d, scanCode=%d, "
1320 "left=%d, top=%d, right=%d, bottom=%d",
1321 x, y,
1322 virtualKey.keyCode, virtualKey.scanCode,
1323 virtualKey.hitLeft, virtualKey.hitTop,
1324 virtualKey.hitRight, virtualKey.hitBottom);
1325#endif
1326
1327 if (virtualKey.isHit(x, y)) {
1328 device->touchScreen.currentVirtualKey.down = true;
1329 device->touchScreen.currentVirtualKey.downTime = when;
1330 device->touchScreen.currentVirtualKey.keyCode = virtualKey.keyCode;
1331 device->touchScreen.currentVirtualKey.scanCode = virtualKey.scanCode;
1332
1333#if DEBUG_VIRTUAL_KEYS
1334 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
1335 device->touchScreen.currentVirtualKey.keyCode,
1336 device->touchScreen.currentVirtualKey.scanCode);
1337#endif
1338
1339 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
1340 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
1341 return true; // consumed
1342 }
1343 }
1344 }
1345
1346 return false; // not consumed
1347}
1348
1349void InputReader::dispatchVirtualKey(nsecs_t when,
1350 InputDevice* device, uint32_t policyFlags,
1351 int32_t keyEventAction, int32_t keyEventFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -07001352 updateExportedVirtualKeyState();
1353
Jeff Brown46b9ac02010-04-22 18:58:52 -07001354 int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
1355 int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
1356 nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
1357 int32_t metaState = globalMetaState();
1358
Jeff Brown46b9ac02010-04-22 18:58:52 -07001359 mPolicy->virtualKeyFeedback(when, device->id, keyEventAction, keyEventFlags,
1360 keyCode, scanCode, metaState, downTime);
1361
Jeff Brown349703e2010-06-22 01:27:15 -07001362 int32_t policyActions = mPolicy->interceptKey(when, device->id,
1363 keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
1364
1365 if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1366 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
1367 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
1368 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001369}
1370
1371void InputReader::dispatchTouches(nsecs_t when,
1372 InputDevice* device, uint32_t policyFlags) {
1373 uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
1374 uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
1375 if (currentPointerCount == 0 && lastPointerCount == 0) {
1376 return; // nothing to do!
1377 }
1378
1379 BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
1380 BitSet32 lastIdBits = device->touchScreen.lastTouch.idBits;
1381
1382 if (currentIdBits == lastIdBits) {
1383 // No pointer id changes so this is a move event.
1384 // The dispatcher takes care of batching moves so we don't have to deal with that here.
1385 int32_t motionEventAction = MOTION_EVENT_ACTION_MOVE;
1386 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
1387 currentIdBits, motionEventAction);
1388 } else {
1389 // There may be pointers going up and pointers going down at the same time when pointer
1390 // ids are reported by the device driver.
1391 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
1392 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
1393 BitSet32 activeIdBits(lastIdBits.value);
1394
1395 while (! upIdBits.isEmpty()) {
1396 uint32_t upId = upIdBits.firstMarkedBit();
1397 upIdBits.clearBit(upId);
1398 BitSet32 oldActiveIdBits = activeIdBits;
1399 activeIdBits.clearBit(upId);
1400
1401 int32_t motionEventAction;
1402 if (activeIdBits.isEmpty()) {
1403 motionEventAction = MOTION_EVENT_ACTION_UP;
1404 } else {
1405 motionEventAction = MOTION_EVENT_ACTION_POINTER_UP
1406 | (upId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1407 }
1408
1409 dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
1410 oldActiveIdBits, motionEventAction);
1411 }
1412
1413 while (! downIdBits.isEmpty()) {
1414 uint32_t downId = downIdBits.firstMarkedBit();
1415 downIdBits.clearBit(downId);
1416 BitSet32 oldActiveIdBits = activeIdBits;
1417 activeIdBits.markBit(downId);
1418
1419 int32_t motionEventAction;
1420 if (oldActiveIdBits.isEmpty()) {
1421 motionEventAction = MOTION_EVENT_ACTION_DOWN;
1422 device->touchScreen.downTime = when;
1423 } else {
1424 motionEventAction = MOTION_EVENT_ACTION_POINTER_DOWN
1425 | (downId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
1426 }
1427
1428 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
1429 activeIdBits, motionEventAction);
1430 }
1431 }
1432}
1433
1434void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
1435 InputDevice::TouchData* touch, BitSet32 idBits,
1436 int32_t motionEventAction) {
1437 int32_t orientedWidth, orientedHeight;
1438 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001439 case InputReaderPolicyInterface::ROTATION_90:
1440 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001441 orientedWidth = mDisplayHeight;
1442 orientedHeight = mDisplayWidth;
1443 break;
1444 default:
1445 orientedWidth = mDisplayWidth;
1446 orientedHeight = mDisplayHeight;
1447 break;
1448 }
1449
1450 uint32_t pointerCount = 0;
1451 int32_t pointerIds[MAX_POINTERS];
1452 PointerCoords pointerCoords[MAX_POINTERS];
1453
Jeff Brown0b72e822010-06-29 16:52:21 -07001454 const InputDevice::TouchScreenState::Precalculated& precalculated =
1455 device->touchScreen.precalculated;
1456
Jeff Brown46b9ac02010-04-22 18:58:52 -07001457 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
1458 // display coordinates (PointerCoords) and adjust for display orientation.
1459 while (! idBits.isEmpty()) {
1460 uint32_t id = idBits.firstMarkedBit();
1461 idBits.clearBit(id);
1462 uint32_t index = touch->idToIndex[id];
1463
Jeff Brown0b72e822010-06-29 16:52:21 -07001464 float x = float(touch->pointers[index].x
1465 - precalculated.xOrigin) * precalculated.xScale;
1466 float y = float(touch->pointers[index].y
1467 - precalculated.yOrigin) * precalculated.yScale;
1468 float pressure = float(touch->pointers[index].pressure
1469 - precalculated.pressureOrigin) * precalculated.pressureScale;
1470 float size = float(touch->pointers[index].size
1471 - precalculated.sizeOrigin) * precalculated.sizeScale;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001472
1473 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001474 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001475 float xTemp = x;
1476 x = y;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001477 y = mDisplayWidth - xTemp;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001478 break;
1479 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001480 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001481 x = mDisplayWidth - x;
1482 y = mDisplayHeight - y;
1483 break;
1484 }
Jeff Brown9c3cda02010-06-15 01:31:58 -07001485 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001486 float xTemp = x;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001487 x = mDisplayHeight - y;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001488 y = xTemp;
1489 break;
1490 }
1491 }
1492
1493 pointerIds[pointerCount] = int32_t(id);
1494
1495 pointerCoords[pointerCount].x = x;
1496 pointerCoords[pointerCount].y = y;
1497 pointerCoords[pointerCount].pressure = pressure;
1498 pointerCoords[pointerCount].size = size;
1499
1500 pointerCount += 1;
1501 }
1502
1503 // Check edge flags by looking only at the first pointer since the flags are
1504 // global to the event.
1505 // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
1506 int32_t motionEventEdgeFlags = 0;
1507 if (motionEventAction == MOTION_EVENT_ACTION_DOWN) {
1508 if (pointerCoords[0].x <= 0) {
1509 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_LEFT;
1510 } else if (pointerCoords[0].x >= orientedWidth) {
1511 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_RIGHT;
1512 }
1513 if (pointerCoords[0].y <= 0) {
1514 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_TOP;
1515 } else if (pointerCoords[0].y >= orientedHeight) {
1516 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_BOTTOM;
1517 }
1518 }
1519
1520 nsecs_t downTime = device->touchScreen.downTime;
1521 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TOUCH, policyFlags,
1522 motionEventAction, globalMetaState(), motionEventEdgeFlags,
1523 pointerCount, pointerIds, pointerCoords,
1524 0, 0, downTime);
1525}
1526
1527void InputReader::onTrackballStateChanged(nsecs_t when,
1528 InputDevice* device) {
1529 static const uint32_t DELTA_FIELDS =
1530 InputDevice::TrackballState::Accumulator::FIELD_REL_X
1531 | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
1532
1533 /* Refresh display properties so we can trackball moves according to display orientation */
1534
1535 if (! refreshDisplayProperties()) {
1536 return;
1537 }
1538
1539 /* Update device state */
1540
1541 uint32_t fields = device->trackball.accumulator.fields;
1542 bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001543 bool deltaChanged = fields & DELTA_FIELDS;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001544
1545 bool down;
1546 if (downChanged) {
1547 if (device->trackball.accumulator.btnMouse) {
1548 device->trackball.current.down = true;
1549 device->trackball.current.downTime = when;
1550 down = true;
1551 } else {
1552 device->trackball.current.down = false;
1553 down = false;
1554 }
1555 } else {
1556 down = device->trackball.current.down;
1557 }
1558
1559 /* Apply policy */
1560
1561 int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
1562
1563 uint32_t policyFlags = 0;
1564 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
1565 return; // event dropped
1566 }
1567
1568 /* Enqueue motion event for dispatch */
1569
1570 int32_t motionEventAction;
1571 if (downChanged) {
1572 motionEventAction = down ? MOTION_EVENT_ACTION_DOWN : MOTION_EVENT_ACTION_UP;
1573 } else {
1574 motionEventAction = MOTION_EVENT_ACTION_MOVE;
1575 }
1576
1577 int32_t pointerId = 0;
1578 PointerCoords pointerCoords;
Jeff Brown7fbdc842010-06-17 20:52:56 -07001579 pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
1580 ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
1581 pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
1582 ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001583 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
1584 pointerCoords.size = 0;
1585
1586 float temp;
1587 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001588 case InputReaderPolicyInterface::ROTATION_90:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001589 temp = pointerCoords.x;
1590 pointerCoords.x = pointerCoords.y;
1591 pointerCoords.y = - temp;
1592 break;
1593
Jeff Brown9c3cda02010-06-15 01:31:58 -07001594 case InputReaderPolicyInterface::ROTATION_180:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001595 pointerCoords.x = - pointerCoords.x;
1596 pointerCoords.y = - pointerCoords.y;
1597 break;
1598
Jeff Brown9c3cda02010-06-15 01:31:58 -07001599 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001600 temp = pointerCoords.x;
1601 pointerCoords.x = - pointerCoords.y;
1602 pointerCoords.y = temp;
1603 break;
1604 }
1605
1606 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TRACKBALL, policyFlags,
1607 motionEventAction, globalMetaState(), MOTION_EVENT_EDGE_FLAG_NONE,
1608 1, & pointerId, & pointerCoords,
1609 device->trackball.precalculated.xPrecision,
1610 device->trackball.precalculated.yPrecision,
1611 device->trackball.current.downTime);
1612}
1613
1614void InputReader::onConfigurationChanged(nsecs_t when) {
1615 // Reset global meta state because it depends on the list of all configured devices.
1616 resetGlobalMetaState();
1617
1618 // Reset virtual keys, just in case.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001619 updateExportedVirtualKeyState();
1620
1621 // Update input configuration.
1622 updateExportedInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001623
1624 // Enqueue configuration changed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001625 mDispatcher->notifyConfigurationChanged(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001626}
1627
1628bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
1629 int32_t policyActions, uint32_t* policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001630 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001631 mDispatcher->notifyAppSwitchComing(when);
1632 }
1633
Jeff Brown9c3cda02010-06-15 01:31:58 -07001634 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001635 *policyFlags |= POLICY_FLAG_WOKE_HERE;
1636 }
1637
Jeff Brown9c3cda02010-06-15 01:31:58 -07001638 if (policyActions & InputReaderPolicyInterface::ACTION_BRIGHT_HERE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001639 *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
1640 }
1641
Jeff Brown9c3cda02010-06-15 01:31:58 -07001642 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001643}
1644
1645void InputReader::resetDisplayProperties() {
1646 mDisplayWidth = mDisplayHeight = -1;
1647 mDisplayOrientation = -1;
1648}
1649
1650bool InputReader::refreshDisplayProperties() {
1651 int32_t newWidth, newHeight, newOrientation;
1652 if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
1653 if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
1654 LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
1655 mDisplayWidth, mDisplayHeight, newWidth, newHeight);
1656
1657 mDisplayWidth = newWidth;
1658 mDisplayHeight = newHeight;
1659
1660 for (size_t i = 0; i < mDevices.size(); i++) {
1661 configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
1662 }
1663 }
1664
Jeff Brown0b72e822010-06-29 16:52:21 -07001665 if (newOrientation != mDisplayOrientation) {
1666 LOGD("Display orientation changed to %d", mDisplayOrientation);
1667
1668 mDisplayOrientation = newOrientation;
1669 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001670 return true;
1671 } else {
1672 resetDisplayProperties();
1673 return false;
1674 }
1675}
1676
1677InputDevice* InputReader::getDevice(int32_t deviceId) {
1678 ssize_t index = mDevices.indexOfKey(deviceId);
1679 return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
1680}
1681
1682InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
1683 InputDevice* device = getDevice(deviceId);
1684 return device && ! device->ignored ? device : NULL;
1685}
1686
1687void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
1688 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
1689 String8 name = mEventHub->getDeviceName(deviceId);
1690 InputDevice* device = new InputDevice(deviceId, classes, name);
1691
1692 if (classes != 0) {
1693 LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
1694 device->name.string(), device->classes);
1695
1696 configureDevice(device);
1697 } else {
1698 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
1699 device->name.string());
1700
1701 device->ignored = true;
1702 }
1703
1704 device->reset();
1705
1706 mDevices.add(deviceId, device);
1707
1708 if (! device->ignored) {
1709 onConfigurationChanged(when);
1710 }
1711}
1712
1713void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
1714 mDevices.removeItem(device->id);
1715
1716 if (! device->ignored) {
1717 LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
1718 device->name.string(), device->classes);
1719
1720 onConfigurationChanged(when);
1721 } else {
1722 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
1723 device->name.string());
1724 }
1725
1726 delete device;
1727}
1728
1729void InputReader::configureDevice(InputDevice* device) {
1730 if (device->isMultiTouchScreen()) {
1731 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
1732 & device->touchScreen.parameters.xAxis);
1733 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
1734 & device->touchScreen.parameters.yAxis);
1735 configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
1736 & device->touchScreen.parameters.pressureAxis);
1737 configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
1738 & device->touchScreen.parameters.sizeAxis);
1739 } else if (device->isSingleTouchScreen()) {
1740 configureAbsoluteAxisInfo(device, ABS_X, "X",
1741 & device->touchScreen.parameters.xAxis);
1742 configureAbsoluteAxisInfo(device, ABS_Y, "Y",
1743 & device->touchScreen.parameters.yAxis);
1744 configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
1745 & device->touchScreen.parameters.pressureAxis);
1746 configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
1747 & device->touchScreen.parameters.sizeAxis);
1748 }
1749
1750 if (device->isTouchScreen()) {
1751 device->touchScreen.parameters.useBadTouchFilter =
1752 mPolicy->filterTouchEvents();
1753 device->touchScreen.parameters.useAveragingTouchFilter =
1754 mPolicy->filterTouchEvents();
1755 device->touchScreen.parameters.useJumpyTouchFilter =
1756 mPolicy->filterJumpyTouchEvents();
1757
Jeff Brown0b72e822010-06-29 16:52:21 -07001758 if (device->touchScreen.parameters.pressureAxis.valid) {
1759 device->touchScreen.precalculated.pressureOrigin =
1760 device->touchScreen.parameters.pressureAxis.minValue;
1761 device->touchScreen.precalculated.pressureScale =
1762 1.0f / device->touchScreen.parameters.pressureAxis.range;
1763 } else {
1764 device->touchScreen.precalculated.pressureOrigin = 0;
1765 device->touchScreen.precalculated.pressureScale = 1.0f;
1766 }
1767
1768 if (device->touchScreen.parameters.sizeAxis.valid) {
1769 device->touchScreen.precalculated.sizeOrigin =
1770 device->touchScreen.parameters.sizeAxis.minValue;
1771 device->touchScreen.precalculated.sizeScale =
1772 1.0f / device->touchScreen.parameters.sizeAxis.range;
1773 } else {
1774 device->touchScreen.precalculated.sizeOrigin = 0;
1775 device->touchScreen.precalculated.sizeScale = 1.0f;
1776 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001777 }
1778
1779 if (device->isTrackball()) {
1780 device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1781 device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1782 device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1783 device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1784 }
1785
1786 configureDeviceForCurrentDisplaySize(device);
1787}
1788
1789void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
1790 if (device->isTouchScreen()) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001791 if (device->touchScreen.parameters.xAxis.valid
1792 && device->touchScreen.parameters.yAxis.valid) {
1793 device->touchScreen.precalculated.xOrigin =
1794 device->touchScreen.parameters.xAxis.minValue;
1795 device->touchScreen.precalculated.yOrigin =
1796 device->touchScreen.parameters.yAxis.minValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001797
Jeff Brown0b72e822010-06-29 16:52:21 -07001798 if (mDisplayWidth < 0) {
1799 LOGD("Skipping part of touch screen configuration since display size is unknown.");
1800
1801 device->touchScreen.precalculated.xScale = 1.0f;
1802 device->touchScreen.precalculated.yScale = 1.0f;
1803 } else {
1804 LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
1805 device->name.string());
1806
1807 device->touchScreen.precalculated.xScale =
1808 float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
1809 device->touchScreen.precalculated.yScale =
1810 float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
1811
1812 configureVirtualKeys(device);
1813 }
1814 } else {
1815 device->touchScreen.precalculated.xOrigin = 0;
1816 device->touchScreen.precalculated.xScale = 1.0f;
1817 device->touchScreen.precalculated.yOrigin = 0;
1818 device->touchScreen.precalculated.yScale = 1.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001819 }
1820 }
1821}
1822
1823void InputReader::configureVirtualKeys(InputDevice* device) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001824 assert(device->touchScreen.parameters.xAxis.valid
1825 && device->touchScreen.parameters.yAxis.valid);
1826
Jeff Brown46b9ac02010-04-22 18:58:52 -07001827 device->touchScreen.virtualKeys.clear();
1828
Jeff Brown9c3cda02010-06-15 01:31:58 -07001829 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001830 mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
1831 if (virtualKeyDefinitions.size() == 0) {
1832 return;
1833 }
1834
1835 device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1836
1837 int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
1838 int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
1839 int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
1840 int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
1841
1842 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001843 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown46b9ac02010-04-22 18:58:52 -07001844 virtualKeyDefinitions[i];
1845
1846 device->touchScreen.virtualKeys.add();
1847 InputDevice::VirtualKey& virtualKey =
1848 device->touchScreen.virtualKeys.editTop();
1849
1850 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1851 int32_t keyCode;
1852 uint32_t flags;
1853 if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
1854 & keyCode, & flags)) {
1855 LOGI(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
1856 device->touchScreen.virtualKeys.pop(); // drop the key
1857 continue;
1858 }
1859
1860 virtualKey.keyCode = keyCode;
1861 virtualKey.flags = flags;
1862
1863 // convert the key definition's display coordinates into touch coordinates for a hit box
1864 int32_t halfWidth = virtualKeyDefinition.width / 2;
1865 int32_t halfHeight = virtualKeyDefinition.height / 2;
1866
1867 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1868 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1869 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1870 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1871 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1872 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1873 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1874 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1875
1876 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1877 virtualKey.scanCode, virtualKey.keyCode,
1878 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1879 }
1880}
1881
1882void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
1883 int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
1884 if (! mEventHub->getAbsoluteInfo(device->id, axis,
1885 & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
1886 out->range = out->maxValue - out->minValue;
1887 if (out->range != 0) {
1888 LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
1889 name, out->minValue, out->maxValue, out->flat, out->fuzz);
Jeff Brown0b72e822010-06-29 16:52:21 -07001890 out->valid = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001891 return;
1892 }
1893 }
1894
Jeff Brown0b72e822010-06-29 16:52:21 -07001895 out->valid = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001896 out->minValue = 0;
1897 out->maxValue = 0;
1898 out->flat = 0;
1899 out->fuzz = 0;
1900 out->range = 0;
Jeff Brown0b72e822010-06-29 16:52:21 -07001901 LOGI(" %s: unknown axis values, marking as invalid", name);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001902}
1903
Jeff Brown9c3cda02010-06-15 01:31:58 -07001904void InputReader::configureExcludedDevices() {
1905 Vector<String8> excludedDeviceNames;
1906 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
1907
1908 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
1909 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
1910 }
1911}
1912
Jeff Brown46b9ac02010-04-22 18:58:52 -07001913void InputReader::resetGlobalMetaState() {
1914 mGlobalMetaState = -1;
1915}
1916
1917int32_t InputReader::globalMetaState() {
1918 if (mGlobalMetaState == -1) {
1919 mGlobalMetaState = 0;
1920 for (size_t i = 0; i < mDevices.size(); i++) {
1921 InputDevice* device = mDevices.valueAt(i);
1922 if (device->isKeyboard()) {
1923 mGlobalMetaState |= device->keyboard.current.metaState;
1924 }
1925 }
1926 }
1927 return mGlobalMetaState;
1928}
1929
Jeff Brown9c3cda02010-06-15 01:31:58 -07001930void InputReader::updateExportedVirtualKeyState() {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001931 int32_t keyCode = -1, scanCode = -1;
1932
1933 for (size_t i = 0; i < mDevices.size(); i++) {
1934 InputDevice* device = mDevices.valueAt(i);
1935 if (device->isTouchScreen()) {
1936 if (device->touchScreen.currentVirtualKey.down) {
1937 keyCode = device->touchScreen.currentVirtualKey.keyCode;
1938 scanCode = device->touchScreen.currentVirtualKey.scanCode;
1939 }
1940 }
1941 }
1942
Jeff Brown9c3cda02010-06-15 01:31:58 -07001943 { // acquire exported state lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07001944 AutoMutex _l(mExportedStateLock);
1945
Jeff Brown9c3cda02010-06-15 01:31:58 -07001946 mExportedVirtualKeyCode = keyCode;
1947 mExportedVirtualScanCode = scanCode;
1948 } // release exported state lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07001949}
1950
1951bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001952 { // acquire exported state lock
1953 AutoMutex _l(mExportedStateLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001954
Jeff Brown9c3cda02010-06-15 01:31:58 -07001955 *outKeyCode = mExportedVirtualKeyCode;
1956 *outScanCode = mExportedVirtualScanCode;
1957 return mExportedVirtualKeyCode != -1;
1958 } // release exported state lock
1959}
1960
1961void InputReader::updateExportedInputConfiguration() {
1962 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
1963 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
1964 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
1965
1966 for (size_t i = 0; i < mDevices.size(); i++) {
1967 InputDevice* device = mDevices.valueAt(i);
1968 int32_t deviceClasses = device->classes;
1969
1970 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
1971 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
1972 }
1973 if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
1974 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
1975 }
1976 if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
1977 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
1978 } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
1979 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
1980 }
1981 }
1982
1983 { // acquire exported state lock
1984 AutoMutex _l(mExportedStateLock);
1985
1986 mExportedInputConfiguration.touchScreen = touchScreenConfig;
1987 mExportedInputConfiguration.keyboard = keyboardConfig;
1988 mExportedInputConfiguration.navigation = navigationConfig;
1989 } // release exported state lock
1990}
1991
1992void InputReader::getCurrentInputConfiguration(InputConfiguration* outConfiguration) const {
1993 { // acquire exported state lock
1994 AutoMutex _l(mExportedStateLock);
1995
1996 *outConfiguration = mExportedInputConfiguration;
1997 } // release exported state lock
1998}
1999
2000int32_t InputReader::getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
2001 int32_t scanCode) const {
2002 { // acquire exported state lock
2003 AutoMutex _l(mExportedStateLock);
2004
2005 if (mExportedVirtualScanCode == scanCode) {
2006 return KEY_STATE_VIRTUAL;
2007 }
2008 } // release exported state lock
2009
2010 return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
2011}
2012
2013int32_t InputReader::getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
2014 int32_t keyCode) const {
2015 { // acquire exported state lock
2016 AutoMutex _l(mExportedStateLock);
2017
2018 if (mExportedVirtualKeyCode == keyCode) {
2019 return KEY_STATE_VIRTUAL;
2020 }
2021 } // release exported state lock
2022
2023 return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
2024}
2025
2026int32_t InputReader::getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
2027 int32_t sw) const {
2028 return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
2029}
2030
2031bool InputReader::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
2032 return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07002033}
2034
2035
2036// --- InputReaderThread ---
2037
2038InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
2039 Thread(/*canCallJava*/ true), mReader(reader) {
2040}
2041
2042InputReaderThread::~InputReaderThread() {
2043}
2044
2045bool InputReaderThread::threadLoop() {
2046 mReader->loopOnce();
2047 return true;
2048}
2049
2050} // namespace android