blob: 0a21db7ccf5e0d5f9f6d6c6198cc098aaeb19895 [file] [log] [blame]
Jeff Browne839a582010-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 Brown50de30a2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Browne839a582010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown50de30a2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Browne839a582010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown50de30a2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Browne839a582010-04-22 18:58:52 -070021
Jeff Brownf4a4ec22010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Browne839a582010-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 Browne839a582010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
32
Jeff Brown54bc2812010-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
Jeff Brown54bc2812010-06-15 01:31:58 -070036
Jeff Browne839a582010-04-22 18:58:52 -070037namespace android {
38
39// --- Static Functions ---
40
41template<typename T>
42inline static T abs(const T& value) {
43 return value < 0 ? - value : value;
44}
45
46template<typename T>
47inline static T min(const T& a, const T& b) {
48 return a < b ? a : b;
49}
50
Jeff Brownf4a4ec22010-06-16 01:53:36 -070051template<typename T>
52inline static void swap(T& a, T& b) {
53 T temp = a;
54 a = b;
55 b = temp;
56}
57
58
Jeff Browne839a582010-04-22 18:58:52 -070059int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
60 int32_t mask;
61 switch (keyCode) {
Jeff Brown8575a872010-06-30 16:10:35 -070062 case AKEYCODE_ALT_LEFT:
Jeff Browne839a582010-04-22 18:58:52 -070063 mask = META_ALT_LEFT_ON;
64 break;
Jeff Brown8575a872010-06-30 16:10:35 -070065 case AKEYCODE_ALT_RIGHT:
Jeff Browne839a582010-04-22 18:58:52 -070066 mask = META_ALT_RIGHT_ON;
67 break;
Jeff Brown8575a872010-06-30 16:10:35 -070068 case AKEYCODE_SHIFT_LEFT:
Jeff Browne839a582010-04-22 18:58:52 -070069 mask = META_SHIFT_LEFT_ON;
70 break;
Jeff Brown8575a872010-06-30 16:10:35 -070071 case AKEYCODE_SHIFT_RIGHT:
Jeff Browne839a582010-04-22 18:58:52 -070072 mask = META_SHIFT_RIGHT_ON;
73 break;
Jeff Brown8575a872010-06-30 16:10:35 -070074 case AKEYCODE_SYM:
Jeff Browne839a582010-04-22 18:58:52 -070075 mask = META_SYM_ON;
76 break;
77 default:
78 return oldMetaState;
79 }
80
81 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
82 & ~ (META_ALT_ON | META_SHIFT_ON);
83
84 if (newMetaState & (META_ALT_LEFT_ON | META_ALT_RIGHT_ON)) {
85 newMetaState |= META_ALT_ON;
86 }
87
88 if (newMetaState & (META_SHIFT_LEFT_ON | META_SHIFT_RIGHT_ON)) {
89 newMetaState |= META_SHIFT_ON;
90 }
91
92 return newMetaState;
93}
94
95static const int32_t keyCodeRotationMap[][4] = {
96 // key codes enumerated counter-clockwise with the original (unrotated) key first
97 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brown8575a872010-06-30 16:10:35 -070098 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
99 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
100 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
101 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Browne839a582010-04-22 18:58:52 -0700102};
103static const int keyCodeRotationMapSize =
104 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
105
106int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700107 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Browne839a582010-04-22 18:58:52 -0700108 for (int i = 0; i < keyCodeRotationMapSize; i++) {
109 if (keyCode == keyCodeRotationMap[i][0]) {
110 return keyCodeRotationMap[i][orientation];
111 }
112 }
113 }
114 return keyCode;
115}
116
117
Jeff Browne839a582010-04-22 18:58:52 -0700118// --- InputReader ---
119
120InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown54bc2812010-06-15 01:31:58 -0700121 const sp<InputReaderPolicyInterface>& policy,
Jeff Browne839a582010-04-22 18:58:52 -0700122 const sp<InputDispatcherInterface>& dispatcher) :
123 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700124 configureExcludedDevices();
Jeff Browne839a582010-04-22 18:58:52 -0700125 resetGlobalMetaState();
126 resetDisplayProperties();
Jeff Brown54bc2812010-06-15 01:31:58 -0700127 updateExportedVirtualKeyState();
Jeff Browne839a582010-04-22 18:58:52 -0700128}
129
130InputReader::~InputReader() {
131 for (size_t i = 0; i < mDevices.size(); i++) {
132 delete mDevices.valueAt(i);
133 }
134}
135
136void InputReader::loopOnce() {
137 RawEvent rawEvent;
138 mEventHub->getEvent(& rawEvent.deviceId, & rawEvent.type, & rawEvent.scanCode,
139 & rawEvent.keyCode, & rawEvent.flags, & rawEvent.value, & rawEvent.when);
140
141 // Replace the event timestamp so it is in same timebase as java.lang.System.nanoTime()
142 // and android.os.SystemClock.uptimeMillis() as expected by the rest of the system.
143 rawEvent.when = systemTime(SYSTEM_TIME_MONOTONIC);
144
145#if DEBUG_RAW_EVENTS
146 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
147 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
148 rawEvent.value);
149#endif
150
151 process(& rawEvent);
152}
153
154void InputReader::process(const RawEvent* rawEvent) {
155 switch (rawEvent->type) {
156 case EventHubInterface::DEVICE_ADDED:
157 handleDeviceAdded(rawEvent);
158 break;
159
160 case EventHubInterface::DEVICE_REMOVED:
161 handleDeviceRemoved(rawEvent);
162 break;
163
164 case EV_SYN:
165 handleSync(rawEvent);
166 break;
167
168 case EV_KEY:
169 handleKey(rawEvent);
170 break;
171
172 case EV_REL:
173 handleRelativeMotion(rawEvent);
174 break;
175
176 case EV_ABS:
177 handleAbsoluteMotion(rawEvent);
178 break;
179
180 case EV_SW:
181 handleSwitch(rawEvent);
182 break;
183 }
184}
185
186void InputReader::handleDeviceAdded(const RawEvent* rawEvent) {
187 InputDevice* device = getDevice(rawEvent->deviceId);
188 if (device) {
189 LOGW("Ignoring spurious device added event for deviceId %d.", rawEvent->deviceId);
190 return;
191 }
192
193 addDevice(rawEvent->when, rawEvent->deviceId);
194}
195
196void InputReader::handleDeviceRemoved(const RawEvent* rawEvent) {
197 InputDevice* device = getDevice(rawEvent->deviceId);
198 if (! device) {
199 LOGW("Ignoring spurious device removed event for deviceId %d.", rawEvent->deviceId);
200 return;
201 }
202
203 removeDevice(rawEvent->when, device);
204}
205
206void InputReader::handleSync(const RawEvent* rawEvent) {
207 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
208 if (! device) return;
209
210 if (rawEvent->scanCode == SYN_MT_REPORT) {
211 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
212 // We drop pointers with pressure <= 0 since that indicates they are not down.
213 if (device->isMultiTouchScreen()) {
214 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
215
216 if (device->multiTouchScreen.accumulator.pointers[pointerIndex].fields) {
217 if (pointerIndex == MAX_POINTERS) {
218 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
219 MAX_POINTERS);
220 } else {
221 pointerIndex += 1;
222 device->multiTouchScreen.accumulator.pointerCount = pointerIndex;
223 }
224 }
225
226 device->multiTouchScreen.accumulator.pointers[pointerIndex].clear();
227 }
228 } else if (rawEvent->scanCode == SYN_REPORT) {
229 // General Sync: The driver has returned all data for the current event update.
230 if (device->isMultiTouchScreen()) {
231 if (device->multiTouchScreen.accumulator.isDirty()) {
232 onMultiTouchScreenStateChanged(rawEvent->when, device);
233 device->multiTouchScreen.accumulator.clear();
234 }
235 } else if (device->isSingleTouchScreen()) {
236 if (device->singleTouchScreen.accumulator.isDirty()) {
237 onSingleTouchScreenStateChanged(rawEvent->when, device);
238 device->singleTouchScreen.accumulator.clear();
239 }
240 }
241
242 if (device->trackball.accumulator.isDirty()) {
243 onTrackballStateChanged(rawEvent->when, device);
244 device->trackball.accumulator.clear();
245 }
246 }
247}
248
249void InputReader::handleKey(const RawEvent* rawEvent) {
250 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
251 if (! device) return;
252
253 bool down = rawEvent->value != 0;
254 int32_t scanCode = rawEvent->scanCode;
255
Jeff Brown8575a872010-06-30 16:10:35 -0700256 if (device->isSingleTouchScreen()) {
Jeff Browne839a582010-04-22 18:58:52 -0700257 switch (rawEvent->scanCode) {
258 case BTN_TOUCH:
259 device->singleTouchScreen.accumulator.fields |=
260 InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
261 device->singleTouchScreen.accumulator.btnTouch = down;
Jeff Brown8575a872010-06-30 16:10:35 -0700262 return;
Jeff Browne839a582010-04-22 18:58:52 -0700263 }
Jeff Brown8575a872010-06-30 16:10:35 -0700264 }
265
266 if (device->isTrackball()) {
Jeff Browne839a582010-04-22 18:58:52 -0700267 switch (rawEvent->scanCode) {
268 case BTN_MOUSE:
269 device->trackball.accumulator.fields |=
270 InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
271 device->trackball.accumulator.btnMouse = down;
Jeff Brown8575a872010-06-30 16:10:35 -0700272 return;
Jeff Browne839a582010-04-22 18:58:52 -0700273 }
274 }
Jeff Brown8575a872010-06-30 16:10:35 -0700275
276 if (device->isKeyboard()) {
277 int32_t keyCode = rawEvent->keyCode;
278 onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
279 }
Jeff Browne839a582010-04-22 18:58:52 -0700280}
281
282void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
283 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
284 if (! device) return;
285
286 if (device->isTrackball()) {
287 switch (rawEvent->scanCode) {
288 case REL_X:
289 device->trackball.accumulator.fields |=
290 InputDevice::TrackballState::Accumulator::FIELD_REL_X;
291 device->trackball.accumulator.relX = rawEvent->value;
292 break;
293 case REL_Y:
294 device->trackball.accumulator.fields |=
295 InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
296 device->trackball.accumulator.relY = rawEvent->value;
297 break;
298 }
299 }
300}
301
302void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
303 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
304 if (! device) return;
305
306 if (device->isMultiTouchScreen()) {
307 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
308 InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
309 & device->multiTouchScreen.accumulator.pointers[pointerIndex];
310
311 switch (rawEvent->scanCode) {
312 case ABS_MT_POSITION_X:
313 pointer->fields |=
314 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
315 pointer->absMTPositionX = rawEvent->value;
316 break;
317 case ABS_MT_POSITION_Y:
318 pointer->fields |=
319 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
320 pointer->absMTPositionY = rawEvent->value;
321 break;
322 case ABS_MT_TOUCH_MAJOR:
323 pointer->fields |=
324 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
325 pointer->absMTTouchMajor = rawEvent->value;
326 break;
327 case ABS_MT_WIDTH_MAJOR:
328 pointer->fields |=
329 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
330 pointer->absMTWidthMajor = rawEvent->value;
331 break;
332 case ABS_MT_TRACKING_ID:
333 pointer->fields |=
334 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
335 pointer->absMTTrackingId = rawEvent->value;
336 break;
337 }
338 } else if (device->isSingleTouchScreen()) {
339 switch (rawEvent->scanCode) {
340 case ABS_X:
341 device->singleTouchScreen.accumulator.fields |=
342 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
343 device->singleTouchScreen.accumulator.absX = rawEvent->value;
344 break;
345 case ABS_Y:
346 device->singleTouchScreen.accumulator.fields |=
347 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
348 device->singleTouchScreen.accumulator.absY = rawEvent->value;
349 break;
350 case ABS_PRESSURE:
351 device->singleTouchScreen.accumulator.fields |=
352 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
353 device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
354 break;
355 case ABS_TOOL_WIDTH:
356 device->singleTouchScreen.accumulator.fields |=
357 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
358 device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
359 break;
360 }
361 }
362}
363
364void InputReader::handleSwitch(const RawEvent* rawEvent) {
365 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
366 if (! device) return;
367
Jeff Brown54bc2812010-06-15 01:31:58 -0700368 onSwitch(rawEvent->when, device, rawEvent->scanCode, rawEvent->value);
Jeff Browne839a582010-04-22 18:58:52 -0700369}
370
371void InputReader::onKey(nsecs_t when, InputDevice* device,
372 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
373 /* Refresh display properties so we can rotate key codes according to display orientation */
374
375 if (! refreshDisplayProperties()) {
376 return;
377 }
378
379 /* Update device state */
380
381 int32_t oldMetaState = device->keyboard.current.metaState;
382 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
383 if (oldMetaState != newMetaState) {
384 device->keyboard.current.metaState = newMetaState;
385 resetGlobalMetaState();
386 }
387
388 // FIXME if we send a down event about a rotated key press we should ensure that we send
389 // a corresponding up event about the rotated key press even if the orientation
390 // has changed in the meantime
391 keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
392
393 if (down) {
394 device->keyboard.current.downTime = when;
395 }
396
397 /* Apply policy */
398
399 int32_t policyActions = mPolicy->interceptKey(when, device->id,
400 down, keyCode, scanCode, policyFlags);
401
402 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
403 return; // event dropped
404 }
405
406 /* Enqueue key event for dispatch */
407
408 int32_t keyEventAction;
409 if (down) {
410 device->keyboard.current.downTime = when;
411 keyEventAction = KEY_EVENT_ACTION_DOWN;
412 } else {
413 keyEventAction = KEY_EVENT_ACTION_UP;
414 }
415
416 int32_t keyEventFlags = KEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown54bc2812010-06-15 01:31:58 -0700417 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Browne839a582010-04-22 18:58:52 -0700418 keyEventFlags = keyEventFlags | KEY_EVENT_FLAG_WOKE_HERE;
419 }
420
421 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
422 keyEventAction, keyEventFlags, keyCode, scanCode,
423 device->keyboard.current.metaState,
424 device->keyboard.current.downTime);
425}
426
Jeff Brown54bc2812010-06-15 01:31:58 -0700427void InputReader::onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode,
428 int32_t switchValue) {
429 int32_t policyActions = mPolicy->interceptSwitch(when, switchCode, switchValue);
430
431 uint32_t policyFlags = 0;
432 applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags);
Jeff Browne839a582010-04-22 18:58:52 -0700433}
434
435void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
436 InputDevice* device) {
437 static const uint32_t REQUIRED_FIELDS =
438 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
439 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
440 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
441 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
442
443 /* Refresh display properties so we can map touch screen coords into display coords */
444
445 if (! refreshDisplayProperties()) {
446 return;
447 }
448
449 /* Update device state */
450
451 InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
452 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
453
454 uint32_t inCount = in->accumulator.pointerCount;
455 uint32_t outCount = 0;
456 bool havePointerIds = true;
457
458 out->clear();
459
460 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
461 uint32_t fields = in->accumulator.pointers[inIndex].fields;
462
463 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
464#if DEBUG_POINTERS
465 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
466 inIndex, fields);
467 continue;
468#endif
469 }
470
471 if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
472 // Pointer is not down. Drop it.
473 continue;
474 }
475
476 // FIXME assignment of pressure may be incorrect, probably better to let
477 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
478 // isn't quite right either. Should be using touch for that.
479 out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
480 out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
481 out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
482 out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
483
484 if (havePointerIds) {
485 if (fields & InputDevice::MultiTouchScreenState::Accumulator::
486 FIELD_ABS_MT_TRACKING_ID) {
487 uint32_t id = uint32_t(in->accumulator.pointers[inIndex].absMTTrackingId);
488
489 if (id > MAX_POINTER_ID) {
490#if DEBUG_POINTERS
491 LOGD("Pointers: Ignoring driver provided pointer id %d because "
492 "it is larger than max supported id %d for optimizations",
493 id, MAX_POINTER_ID);
494#endif
495 havePointerIds = false;
496 }
497 else {
498 out->pointers[outCount].id = id;
499 out->idToIndex[id] = outCount;
500 out->idBits.markBit(id);
501 }
502 } else {
503 havePointerIds = false;
504 }
505 }
506
507 outCount += 1;
508 }
509
510 out->pointerCount = outCount;
511
512 onTouchScreenChanged(when, device, havePointerIds);
513}
514
515void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
516 InputDevice* device) {
Jeff Browne839a582010-04-22 18:58:52 -0700517 /* Refresh display properties so we can map touch screen coords into display coords */
518
519 if (! refreshDisplayProperties()) {
520 return;
521 }
522
523 /* Update device state */
524
525 InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
526 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
527
528 uint32_t fields = in->accumulator.fields;
529
530 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
531 in->current.down = in->accumulator.btnTouch;
532 }
533
Jeff Brown50de30a2010-06-22 01:27:15 -0700534 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
Jeff Browne839a582010-04-22 18:58:52 -0700535 in->current.x = in->accumulator.absX;
Jeff Brown50de30a2010-06-22 01:27:15 -0700536 }
537
538 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
Jeff Browne839a582010-04-22 18:58:52 -0700539 in->current.y = in->accumulator.absY;
Jeff Brown50de30a2010-06-22 01:27:15 -0700540 }
541
542 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
Jeff Browne839a582010-04-22 18:58:52 -0700543 in->current.pressure = in->accumulator.absPressure;
Jeff Brown50de30a2010-06-22 01:27:15 -0700544 }
545
546 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Browne839a582010-04-22 18:58:52 -0700547 in->current.size = in->accumulator.absToolWidth;
548 }
549
550 out->clear();
551
552 if (in->current.down) {
553 out->pointerCount = 1;
554 out->pointers[0].id = 0;
555 out->pointers[0].x = in->current.x;
556 out->pointers[0].y = in->current.y;
557 out->pointers[0].pressure = in->current.pressure;
558 out->pointers[0].size = in->current.size;
559 out->idToIndex[0] = 0;
560 out->idBits.markBit(0);
561 }
562
563 onTouchScreenChanged(when, device, true);
564}
565
566void InputReader::onTouchScreenChanged(nsecs_t when,
567 InputDevice* device, bool havePointerIds) {
568 /* Apply policy */
569
570 int32_t policyActions = mPolicy->interceptTouch(when);
571
572 uint32_t policyFlags = 0;
573 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
574 device->touchScreen.lastTouch.clear();
575 return; // event dropped
576 }
577
578 /* Preprocess pointer data */
579
580 if (device->touchScreen.parameters.useBadTouchFilter) {
581 if (device->touchScreen.applyBadTouchFilter()) {
582 havePointerIds = false;
583 }
584 }
585
586 if (device->touchScreen.parameters.useJumpyTouchFilter) {
587 if (device->touchScreen.applyJumpyTouchFilter()) {
588 havePointerIds = false;
589 }
590 }
591
592 if (! havePointerIds) {
593 device->touchScreen.calculatePointerIds();
594 }
595
596 InputDevice::TouchData temp;
597 InputDevice::TouchData* savedTouch;
598 if (device->touchScreen.parameters.useAveragingTouchFilter) {
599 temp.copyFrom(device->touchScreen.currentTouch);
600 savedTouch = & temp;
601
602 device->touchScreen.applyAveragingTouchFilter();
603 } else {
604 savedTouch = & device->touchScreen.currentTouch;
605 }
606
607 /* Process virtual keys or touches */
608
609 if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
610 dispatchTouches(when, device, policyFlags);
611 }
612
613 // Copy current touch to last touch in preparation for the next cycle.
614 device->touchScreen.lastTouch.copyFrom(*savedTouch);
615}
616
617bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
618 InputDevice* device, uint32_t policyFlags) {
Jeff Brownf16c26d2010-07-02 15:37:36 -0700619 switch (device->touchScreen.currentVirtualKey.status) {
620 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED:
Jeff Browne839a582010-04-22 18:58:52 -0700621 if (device->touchScreen.currentTouch.pointerCount == 0) {
Jeff Brownf16c26d2010-07-02 15:37:36 -0700622 // Pointer went up after virtual key canceled.
623 device->touchScreen.currentVirtualKey.status =
624 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
625 }
626 return true; // consumed
Jeff Browne839a582010-04-22 18:58:52 -0700627
Jeff Brownf16c26d2010-07-02 15:37:36 -0700628 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN:
629 if (device->touchScreen.currentTouch.pointerCount == 0) {
630 // Pointer went up while virtual key was down.
631 device->touchScreen.currentVirtualKey.status =
632 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
Jeff Browne839a582010-04-22 18:58:52 -0700633#if DEBUG_VIRTUAL_KEYS
634 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
635 device->touchScreen.currentVirtualKey.keyCode,
636 device->touchScreen.currentVirtualKey.scanCode);
637#endif
Jeff Browne839a582010-04-22 18:58:52 -0700638 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
639 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
640 return true; // consumed
641 }
642
Jeff Brownf16c26d2010-07-02 15:37:36 -0700643 if (device->touchScreen.currentTouch.pointerCount == 1) {
644 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
645 if (virtualKey
646 && virtualKey->keyCode == device->touchScreen.currentVirtualKey.keyCode) {
647 // Pointer is still within the space of the virtual key.
648 return true; // consumed
649 }
Jeff Browne839a582010-04-22 18:58:52 -0700650 }
Jeff Browne839a582010-04-22 18:58:52 -0700651
Jeff Brownf16c26d2010-07-02 15:37:36 -0700652 // Pointer left virtual key area or another pointer also went down.
653 // Send key cancellation.
654 device->touchScreen.currentVirtualKey.status =
655 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED;
Jeff Browne839a582010-04-22 18:58:52 -0700656#if DEBUG_VIRTUAL_KEYS
Jeff Brownf16c26d2010-07-02 15:37:36 -0700657 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
658 device->touchScreen.currentVirtualKey.keyCode,
659 device->touchScreen.currentVirtualKey.scanCode);
Jeff Browne839a582010-04-22 18:58:52 -0700660#endif
Jeff Brownf16c26d2010-07-02 15:37:36 -0700661 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_UP,
662 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY
663 | KEY_EVENT_FLAG_CANCELED);
664 return true; // consumed
Jeff Browne839a582010-04-22 18:58:52 -0700665
Jeff Brownf16c26d2010-07-02 15:37:36 -0700666 default:
667 if (device->touchScreen.currentTouch.pointerCount == 1
668 && device->touchScreen.lastTouch.pointerCount == 0) {
669 // Pointer just went down. Check for virtual key hit.
670 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
671 if (virtualKey) {
672 device->touchScreen.currentVirtualKey.status =
673 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN;
Jeff Browne839a582010-04-22 18:58:52 -0700674 device->touchScreen.currentVirtualKey.downTime = when;
Jeff Brownf16c26d2010-07-02 15:37:36 -0700675 device->touchScreen.currentVirtualKey.keyCode = virtualKey->keyCode;
676 device->touchScreen.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Browne839a582010-04-22 18:58:52 -0700677#if DEBUG_VIRTUAL_KEYS
Jeff Brownf16c26d2010-07-02 15:37:36 -0700678 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
679 device->touchScreen.currentVirtualKey.keyCode,
680 device->touchScreen.currentVirtualKey.scanCode);
Jeff Browne839a582010-04-22 18:58:52 -0700681#endif
Jeff Browne839a582010-04-22 18:58:52 -0700682 dispatchVirtualKey(when, device, policyFlags, KEY_EVENT_ACTION_DOWN,
683 KEY_EVENT_FLAG_FROM_SYSTEM | KEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
684 return true; // consumed
685 }
686 }
Jeff Brownf16c26d2010-07-02 15:37:36 -0700687 return false; // not consumed
Jeff Browne839a582010-04-22 18:58:52 -0700688 }
Jeff Browne839a582010-04-22 18:58:52 -0700689}
690
691void InputReader::dispatchVirtualKey(nsecs_t when,
692 InputDevice* device, uint32_t policyFlags,
693 int32_t keyEventAction, int32_t keyEventFlags) {
Jeff Brown50de30a2010-06-22 01:27:15 -0700694 updateExportedVirtualKeyState();
695
Jeff Browne839a582010-04-22 18:58:52 -0700696 int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
697 int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
698 nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
699 int32_t metaState = globalMetaState();
700
Jeff Brownf16c26d2010-07-02 15:37:36 -0700701 if (keyEventAction == KEY_EVENT_ACTION_DOWN) {
702 mPolicy->virtualKeyDownFeedback();
703 }
Jeff Browne839a582010-04-22 18:58:52 -0700704
Jeff Brown50de30a2010-06-22 01:27:15 -0700705 int32_t policyActions = mPolicy->interceptKey(when, device->id,
706 keyEventAction == KEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
707
708 if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
709 mDispatcher->notifyKey(when, device->id, INPUT_EVENT_NATURE_KEY, policyFlags,
710 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
711 }
Jeff Browne839a582010-04-22 18:58:52 -0700712}
713
714void InputReader::dispatchTouches(nsecs_t when,
715 InputDevice* device, uint32_t policyFlags) {
716 uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
717 uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
718 if (currentPointerCount == 0 && lastPointerCount == 0) {
719 return; // nothing to do!
720 }
721
722 BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
723 BitSet32 lastIdBits = device->touchScreen.lastTouch.idBits;
724
725 if (currentIdBits == lastIdBits) {
726 // No pointer id changes so this is a move event.
727 // The dispatcher takes care of batching moves so we don't have to deal with that here.
728 int32_t motionEventAction = MOTION_EVENT_ACTION_MOVE;
729 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
730 currentIdBits, motionEventAction);
731 } else {
732 // There may be pointers going up and pointers going down at the same time when pointer
733 // ids are reported by the device driver.
734 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
735 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
736 BitSet32 activeIdBits(lastIdBits.value);
737
738 while (! upIdBits.isEmpty()) {
739 uint32_t upId = upIdBits.firstMarkedBit();
740 upIdBits.clearBit(upId);
741 BitSet32 oldActiveIdBits = activeIdBits;
742 activeIdBits.clearBit(upId);
743
744 int32_t motionEventAction;
745 if (activeIdBits.isEmpty()) {
746 motionEventAction = MOTION_EVENT_ACTION_UP;
747 } else {
748 motionEventAction = MOTION_EVENT_ACTION_POINTER_UP
749 | (upId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
750 }
751
752 dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
753 oldActiveIdBits, motionEventAction);
754 }
755
756 while (! downIdBits.isEmpty()) {
757 uint32_t downId = downIdBits.firstMarkedBit();
758 downIdBits.clearBit(downId);
759 BitSet32 oldActiveIdBits = activeIdBits;
760 activeIdBits.markBit(downId);
761
762 int32_t motionEventAction;
763 if (oldActiveIdBits.isEmpty()) {
764 motionEventAction = MOTION_EVENT_ACTION_DOWN;
765 device->touchScreen.downTime = when;
766 } else {
767 motionEventAction = MOTION_EVENT_ACTION_POINTER_DOWN
768 | (downId << MOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
769 }
770
771 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
772 activeIdBits, motionEventAction);
773 }
774 }
775}
776
777void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
778 InputDevice::TouchData* touch, BitSet32 idBits,
779 int32_t motionEventAction) {
780 int32_t orientedWidth, orientedHeight;
781 switch (mDisplayOrientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700782 case InputReaderPolicyInterface::ROTATION_90:
783 case InputReaderPolicyInterface::ROTATION_270:
Jeff Browne839a582010-04-22 18:58:52 -0700784 orientedWidth = mDisplayHeight;
785 orientedHeight = mDisplayWidth;
786 break;
787 default:
788 orientedWidth = mDisplayWidth;
789 orientedHeight = mDisplayHeight;
790 break;
791 }
792
793 uint32_t pointerCount = 0;
794 int32_t pointerIds[MAX_POINTERS];
795 PointerCoords pointerCoords[MAX_POINTERS];
796
Jeff Brown4036f7f2010-06-29 16:52:21 -0700797 const InputDevice::TouchScreenState::Precalculated& precalculated =
798 device->touchScreen.precalculated;
799
Jeff Browne839a582010-04-22 18:58:52 -0700800 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
801 // display coordinates (PointerCoords) and adjust for display orientation.
802 while (! idBits.isEmpty()) {
803 uint32_t id = idBits.firstMarkedBit();
804 idBits.clearBit(id);
805 uint32_t index = touch->idToIndex[id];
806
Jeff Brown4036f7f2010-06-29 16:52:21 -0700807 float x = float(touch->pointers[index].x
808 - precalculated.xOrigin) * precalculated.xScale;
809 float y = float(touch->pointers[index].y
810 - precalculated.yOrigin) * precalculated.yScale;
811 float pressure = float(touch->pointers[index].pressure
812 - precalculated.pressureOrigin) * precalculated.pressureScale;
813 float size = float(touch->pointers[index].size
814 - precalculated.sizeOrigin) * precalculated.sizeScale;
Jeff Browne839a582010-04-22 18:58:52 -0700815
816 switch (mDisplayOrientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700817 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Browne839a582010-04-22 18:58:52 -0700818 float xTemp = x;
819 x = y;
Jeff Brown51d45a72010-06-17 20:52:56 -0700820 y = mDisplayWidth - xTemp;
Jeff Browne839a582010-04-22 18:58:52 -0700821 break;
822 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700823 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Browne839a582010-04-22 18:58:52 -0700824 x = mDisplayWidth - x;
825 y = mDisplayHeight - y;
826 break;
827 }
Jeff Brown54bc2812010-06-15 01:31:58 -0700828 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Browne839a582010-04-22 18:58:52 -0700829 float xTemp = x;
Jeff Brown51d45a72010-06-17 20:52:56 -0700830 x = mDisplayHeight - y;
Jeff Browne839a582010-04-22 18:58:52 -0700831 y = xTemp;
832 break;
833 }
834 }
835
836 pointerIds[pointerCount] = int32_t(id);
837
838 pointerCoords[pointerCount].x = x;
839 pointerCoords[pointerCount].y = y;
840 pointerCoords[pointerCount].pressure = pressure;
841 pointerCoords[pointerCount].size = size;
842
843 pointerCount += 1;
844 }
845
846 // Check edge flags by looking only at the first pointer since the flags are
847 // global to the event.
848 // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
849 int32_t motionEventEdgeFlags = 0;
850 if (motionEventAction == MOTION_EVENT_ACTION_DOWN) {
851 if (pointerCoords[0].x <= 0) {
852 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_LEFT;
853 } else if (pointerCoords[0].x >= orientedWidth) {
854 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_RIGHT;
855 }
856 if (pointerCoords[0].y <= 0) {
857 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_TOP;
858 } else if (pointerCoords[0].y >= orientedHeight) {
859 motionEventEdgeFlags |= MOTION_EVENT_EDGE_FLAG_BOTTOM;
860 }
861 }
862
863 nsecs_t downTime = device->touchScreen.downTime;
864 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TOUCH, policyFlags,
865 motionEventAction, globalMetaState(), motionEventEdgeFlags,
866 pointerCount, pointerIds, pointerCoords,
867 0, 0, downTime);
868}
869
870void InputReader::onTrackballStateChanged(nsecs_t when,
871 InputDevice* device) {
872 static const uint32_t DELTA_FIELDS =
873 InputDevice::TrackballState::Accumulator::FIELD_REL_X
874 | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
875
876 /* Refresh display properties so we can trackball moves according to display orientation */
877
878 if (! refreshDisplayProperties()) {
879 return;
880 }
881
882 /* Update device state */
883
884 uint32_t fields = device->trackball.accumulator.fields;
885 bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
Jeff Brown51d45a72010-06-17 20:52:56 -0700886 bool deltaChanged = fields & DELTA_FIELDS;
Jeff Browne839a582010-04-22 18:58:52 -0700887
888 bool down;
889 if (downChanged) {
890 if (device->trackball.accumulator.btnMouse) {
891 device->trackball.current.down = true;
892 device->trackball.current.downTime = when;
893 down = true;
894 } else {
895 device->trackball.current.down = false;
896 down = false;
897 }
898 } else {
899 down = device->trackball.current.down;
900 }
901
902 /* Apply policy */
903
904 int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
905
906 uint32_t policyFlags = 0;
907 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
908 return; // event dropped
909 }
910
911 /* Enqueue motion event for dispatch */
912
913 int32_t motionEventAction;
914 if (downChanged) {
915 motionEventAction = down ? MOTION_EVENT_ACTION_DOWN : MOTION_EVENT_ACTION_UP;
916 } else {
917 motionEventAction = MOTION_EVENT_ACTION_MOVE;
918 }
919
920 int32_t pointerId = 0;
921 PointerCoords pointerCoords;
Jeff Brown51d45a72010-06-17 20:52:56 -0700922 pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
923 ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
924 pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
925 ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
Jeff Browne839a582010-04-22 18:58:52 -0700926 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
927 pointerCoords.size = 0;
928
929 float temp;
930 switch (mDisplayOrientation) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700931 case InputReaderPolicyInterface::ROTATION_90:
Jeff Browne839a582010-04-22 18:58:52 -0700932 temp = pointerCoords.x;
933 pointerCoords.x = pointerCoords.y;
934 pointerCoords.y = - temp;
935 break;
936
Jeff Brown54bc2812010-06-15 01:31:58 -0700937 case InputReaderPolicyInterface::ROTATION_180:
Jeff Browne839a582010-04-22 18:58:52 -0700938 pointerCoords.x = - pointerCoords.x;
939 pointerCoords.y = - pointerCoords.y;
940 break;
941
Jeff Brown54bc2812010-06-15 01:31:58 -0700942 case InputReaderPolicyInterface::ROTATION_270:
Jeff Browne839a582010-04-22 18:58:52 -0700943 temp = pointerCoords.x;
944 pointerCoords.x = - pointerCoords.y;
945 pointerCoords.y = temp;
946 break;
947 }
948
949 mDispatcher->notifyMotion(when, device->id, INPUT_EVENT_NATURE_TRACKBALL, policyFlags,
950 motionEventAction, globalMetaState(), MOTION_EVENT_EDGE_FLAG_NONE,
951 1, & pointerId, & pointerCoords,
952 device->trackball.precalculated.xPrecision,
953 device->trackball.precalculated.yPrecision,
954 device->trackball.current.downTime);
955}
956
957void InputReader::onConfigurationChanged(nsecs_t when) {
958 // Reset global meta state because it depends on the list of all configured devices.
959 resetGlobalMetaState();
960
961 // Reset virtual keys, just in case.
Jeff Brown54bc2812010-06-15 01:31:58 -0700962 updateExportedVirtualKeyState();
963
964 // Update input configuration.
965 updateExportedInputConfiguration();
Jeff Browne839a582010-04-22 18:58:52 -0700966
967 // Enqueue configuration changed.
Jeff Brown54bc2812010-06-15 01:31:58 -0700968 mDispatcher->notifyConfigurationChanged(when);
Jeff Browne839a582010-04-22 18:58:52 -0700969}
970
971bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
972 int32_t policyActions, uint32_t* policyFlags) {
Jeff Brown54bc2812010-06-15 01:31:58 -0700973 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
Jeff Browne839a582010-04-22 18:58:52 -0700974 mDispatcher->notifyAppSwitchComing(when);
975 }
976
Jeff Brown54bc2812010-06-15 01:31:58 -0700977 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Browne839a582010-04-22 18:58:52 -0700978 *policyFlags |= POLICY_FLAG_WOKE_HERE;
979 }
980
Jeff Brown54bc2812010-06-15 01:31:58 -0700981 if (policyActions & InputReaderPolicyInterface::ACTION_BRIGHT_HERE) {
Jeff Browne839a582010-04-22 18:58:52 -0700982 *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
983 }
984
Jeff Brown54bc2812010-06-15 01:31:58 -0700985 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Browne839a582010-04-22 18:58:52 -0700986}
987
988void InputReader::resetDisplayProperties() {
989 mDisplayWidth = mDisplayHeight = -1;
990 mDisplayOrientation = -1;
991}
992
993bool InputReader::refreshDisplayProperties() {
994 int32_t newWidth, newHeight, newOrientation;
995 if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
996 if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
997 LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
998 mDisplayWidth, mDisplayHeight, newWidth, newHeight);
999
1000 mDisplayWidth = newWidth;
1001 mDisplayHeight = newHeight;
1002
1003 for (size_t i = 0; i < mDevices.size(); i++) {
1004 configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
1005 }
1006 }
1007
Jeff Brown4036f7f2010-06-29 16:52:21 -07001008 if (newOrientation != mDisplayOrientation) {
1009 LOGD("Display orientation changed to %d", mDisplayOrientation);
1010
1011 mDisplayOrientation = newOrientation;
1012 }
Jeff Browne839a582010-04-22 18:58:52 -07001013 return true;
1014 } else {
1015 resetDisplayProperties();
1016 return false;
1017 }
1018}
1019
1020InputDevice* InputReader::getDevice(int32_t deviceId) {
1021 ssize_t index = mDevices.indexOfKey(deviceId);
1022 return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
1023}
1024
1025InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
1026 InputDevice* device = getDevice(deviceId);
1027 return device && ! device->ignored ? device : NULL;
1028}
1029
1030void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
1031 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
1032 String8 name = mEventHub->getDeviceName(deviceId);
1033 InputDevice* device = new InputDevice(deviceId, classes, name);
1034
1035 if (classes != 0) {
1036 LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
1037 device->name.string(), device->classes);
1038
1039 configureDevice(device);
1040 } else {
1041 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
1042 device->name.string());
1043
1044 device->ignored = true;
1045 }
1046
1047 device->reset();
1048
1049 mDevices.add(deviceId, device);
1050
1051 if (! device->ignored) {
1052 onConfigurationChanged(when);
1053 }
1054}
1055
1056void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
1057 mDevices.removeItem(device->id);
1058
1059 if (! device->ignored) {
1060 LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
1061 device->name.string(), device->classes);
1062
1063 onConfigurationChanged(when);
1064 } else {
1065 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
1066 device->name.string());
1067 }
1068
1069 delete device;
1070}
1071
1072void InputReader::configureDevice(InputDevice* device) {
1073 if (device->isMultiTouchScreen()) {
1074 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
1075 & device->touchScreen.parameters.xAxis);
1076 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
1077 & device->touchScreen.parameters.yAxis);
1078 configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
1079 & device->touchScreen.parameters.pressureAxis);
1080 configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
1081 & device->touchScreen.parameters.sizeAxis);
1082 } else if (device->isSingleTouchScreen()) {
1083 configureAbsoluteAxisInfo(device, ABS_X, "X",
1084 & device->touchScreen.parameters.xAxis);
1085 configureAbsoluteAxisInfo(device, ABS_Y, "Y",
1086 & device->touchScreen.parameters.yAxis);
1087 configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
1088 & device->touchScreen.parameters.pressureAxis);
1089 configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
1090 & device->touchScreen.parameters.sizeAxis);
1091 }
1092
1093 if (device->isTouchScreen()) {
1094 device->touchScreen.parameters.useBadTouchFilter =
1095 mPolicy->filterTouchEvents();
1096 device->touchScreen.parameters.useAveragingTouchFilter =
1097 mPolicy->filterTouchEvents();
1098 device->touchScreen.parameters.useJumpyTouchFilter =
1099 mPolicy->filterJumpyTouchEvents();
1100
Jeff Brown4036f7f2010-06-29 16:52:21 -07001101 if (device->touchScreen.parameters.pressureAxis.valid) {
1102 device->touchScreen.precalculated.pressureOrigin =
1103 device->touchScreen.parameters.pressureAxis.minValue;
1104 device->touchScreen.precalculated.pressureScale =
1105 1.0f / device->touchScreen.parameters.pressureAxis.range;
1106 } else {
1107 device->touchScreen.precalculated.pressureOrigin = 0;
1108 device->touchScreen.precalculated.pressureScale = 1.0f;
1109 }
1110
1111 if (device->touchScreen.parameters.sizeAxis.valid) {
1112 device->touchScreen.precalculated.sizeOrigin =
1113 device->touchScreen.parameters.sizeAxis.minValue;
1114 device->touchScreen.precalculated.sizeScale =
1115 1.0f / device->touchScreen.parameters.sizeAxis.range;
1116 } else {
1117 device->touchScreen.precalculated.sizeOrigin = 0;
1118 device->touchScreen.precalculated.sizeScale = 1.0f;
1119 }
Jeff Browne839a582010-04-22 18:58:52 -07001120 }
1121
1122 if (device->isTrackball()) {
1123 device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1124 device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1125 device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1126 device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1127 }
1128
1129 configureDeviceForCurrentDisplaySize(device);
1130}
1131
1132void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
1133 if (device->isTouchScreen()) {
Jeff Brown4036f7f2010-06-29 16:52:21 -07001134 if (device->touchScreen.parameters.xAxis.valid
1135 && device->touchScreen.parameters.yAxis.valid) {
1136 device->touchScreen.precalculated.xOrigin =
1137 device->touchScreen.parameters.xAxis.minValue;
1138 device->touchScreen.precalculated.yOrigin =
1139 device->touchScreen.parameters.yAxis.minValue;
Jeff Browne839a582010-04-22 18:58:52 -07001140
Jeff Brown4036f7f2010-06-29 16:52:21 -07001141 if (mDisplayWidth < 0) {
1142 LOGD("Skipping part of touch screen configuration since display size is unknown.");
1143
1144 device->touchScreen.precalculated.xScale = 1.0f;
1145 device->touchScreen.precalculated.yScale = 1.0f;
1146 } else {
1147 LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
1148 device->name.string());
1149
1150 device->touchScreen.precalculated.xScale =
1151 float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
1152 device->touchScreen.precalculated.yScale =
1153 float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
1154
1155 configureVirtualKeys(device);
1156 }
1157 } else {
1158 device->touchScreen.precalculated.xOrigin = 0;
1159 device->touchScreen.precalculated.xScale = 1.0f;
1160 device->touchScreen.precalculated.yOrigin = 0;
1161 device->touchScreen.precalculated.yScale = 1.0f;
Jeff Browne839a582010-04-22 18:58:52 -07001162 }
1163 }
1164}
1165
1166void InputReader::configureVirtualKeys(InputDevice* device) {
Jeff Brown4036f7f2010-06-29 16:52:21 -07001167 assert(device->touchScreen.parameters.xAxis.valid
1168 && device->touchScreen.parameters.yAxis.valid);
1169
Jeff Browne839a582010-04-22 18:58:52 -07001170 device->touchScreen.virtualKeys.clear();
1171
Jeff Brown54bc2812010-06-15 01:31:58 -07001172 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Browne839a582010-04-22 18:58:52 -07001173 mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
1174 if (virtualKeyDefinitions.size() == 0) {
1175 return;
1176 }
1177
1178 device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1179
1180 int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
1181 int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
1182 int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
1183 int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
1184
1185 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown54bc2812010-06-15 01:31:58 -07001186 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
Jeff Browne839a582010-04-22 18:58:52 -07001187 virtualKeyDefinitions[i];
1188
1189 device->touchScreen.virtualKeys.add();
1190 InputDevice::VirtualKey& virtualKey =
1191 device->touchScreen.virtualKeys.editTop();
1192
1193 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1194 int32_t keyCode;
1195 uint32_t flags;
1196 if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
1197 & keyCode, & flags)) {
Jeff Brownf16c26d2010-07-02 15:37:36 -07001198 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
Jeff Browne839a582010-04-22 18:58:52 -07001199 device->touchScreen.virtualKeys.pop(); // drop the key
1200 continue;
1201 }
1202
1203 virtualKey.keyCode = keyCode;
1204 virtualKey.flags = flags;
1205
1206 // convert the key definition's display coordinates into touch coordinates for a hit box
1207 int32_t halfWidth = virtualKeyDefinition.width / 2;
1208 int32_t halfHeight = virtualKeyDefinition.height / 2;
1209
1210 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1211 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1212 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1213 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1214 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1215 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1216 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1217 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1218
1219 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1220 virtualKey.scanCode, virtualKey.keyCode,
1221 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1222 }
1223}
1224
1225void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
1226 int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
1227 if (! mEventHub->getAbsoluteInfo(device->id, axis,
1228 & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
1229 out->range = out->maxValue - out->minValue;
1230 if (out->range != 0) {
1231 LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
1232 name, out->minValue, out->maxValue, out->flat, out->fuzz);
Jeff Brown4036f7f2010-06-29 16:52:21 -07001233 out->valid = true;
Jeff Browne839a582010-04-22 18:58:52 -07001234 return;
1235 }
1236 }
1237
Jeff Brown4036f7f2010-06-29 16:52:21 -07001238 out->valid = false;
Jeff Browne839a582010-04-22 18:58:52 -07001239 out->minValue = 0;
1240 out->maxValue = 0;
1241 out->flat = 0;
1242 out->fuzz = 0;
1243 out->range = 0;
Jeff Brown4036f7f2010-06-29 16:52:21 -07001244 LOGI(" %s: unknown axis values, marking as invalid", name);
Jeff Browne839a582010-04-22 18:58:52 -07001245}
1246
Jeff Brown54bc2812010-06-15 01:31:58 -07001247void InputReader::configureExcludedDevices() {
1248 Vector<String8> excludedDeviceNames;
1249 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
1250
1251 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
1252 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
1253 }
1254}
1255
Jeff Browne839a582010-04-22 18:58:52 -07001256void InputReader::resetGlobalMetaState() {
1257 mGlobalMetaState = -1;
1258}
1259
1260int32_t InputReader::globalMetaState() {
1261 if (mGlobalMetaState == -1) {
1262 mGlobalMetaState = 0;
1263 for (size_t i = 0; i < mDevices.size(); i++) {
1264 InputDevice* device = mDevices.valueAt(i);
1265 if (device->isKeyboard()) {
1266 mGlobalMetaState |= device->keyboard.current.metaState;
1267 }
1268 }
1269 }
1270 return mGlobalMetaState;
1271}
1272
Jeff Brown54bc2812010-06-15 01:31:58 -07001273void InputReader::updateExportedVirtualKeyState() {
Jeff Browne839a582010-04-22 18:58:52 -07001274 int32_t keyCode = -1, scanCode = -1;
1275
1276 for (size_t i = 0; i < mDevices.size(); i++) {
1277 InputDevice* device = mDevices.valueAt(i);
1278 if (device->isTouchScreen()) {
Jeff Brownf16c26d2010-07-02 15:37:36 -07001279 if (device->touchScreen.currentVirtualKey.status
1280 == InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN) {
Jeff Browne839a582010-04-22 18:58:52 -07001281 keyCode = device->touchScreen.currentVirtualKey.keyCode;
1282 scanCode = device->touchScreen.currentVirtualKey.scanCode;
1283 }
1284 }
1285 }
1286
Jeff Brown54bc2812010-06-15 01:31:58 -07001287 { // acquire exported state lock
Jeff Browne839a582010-04-22 18:58:52 -07001288 AutoMutex _l(mExportedStateLock);
1289
Jeff Brown54bc2812010-06-15 01:31:58 -07001290 mExportedVirtualKeyCode = keyCode;
1291 mExportedVirtualScanCode = scanCode;
1292 } // release exported state lock
Jeff Browne839a582010-04-22 18:58:52 -07001293}
1294
1295bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
Jeff Brown54bc2812010-06-15 01:31:58 -07001296 { // acquire exported state lock
1297 AutoMutex _l(mExportedStateLock);
Jeff Browne839a582010-04-22 18:58:52 -07001298
Jeff Brown54bc2812010-06-15 01:31:58 -07001299 *outKeyCode = mExportedVirtualKeyCode;
1300 *outScanCode = mExportedVirtualScanCode;
1301 return mExportedVirtualKeyCode != -1;
1302 } // release exported state lock
1303}
1304
1305void InputReader::updateExportedInputConfiguration() {
1306 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
1307 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
1308 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
1309
1310 for (size_t i = 0; i < mDevices.size(); i++) {
1311 InputDevice* device = mDevices.valueAt(i);
1312 int32_t deviceClasses = device->classes;
1313
1314 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
1315 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
1316 }
1317 if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
1318 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
1319 }
1320 if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
1321 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
1322 } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
1323 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
1324 }
1325 }
1326
1327 { // acquire exported state lock
1328 AutoMutex _l(mExportedStateLock);
1329
1330 mExportedInputConfiguration.touchScreen = touchScreenConfig;
1331 mExportedInputConfiguration.keyboard = keyboardConfig;
1332 mExportedInputConfiguration.navigation = navigationConfig;
1333 } // release exported state lock
1334}
1335
1336void InputReader::getCurrentInputConfiguration(InputConfiguration* outConfiguration) const {
1337 { // acquire exported state lock
1338 AutoMutex _l(mExportedStateLock);
1339
1340 *outConfiguration = mExportedInputConfiguration;
1341 } // release exported state lock
1342}
1343
1344int32_t InputReader::getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
1345 int32_t scanCode) const {
1346 { // acquire exported state lock
1347 AutoMutex _l(mExportedStateLock);
1348
1349 if (mExportedVirtualScanCode == scanCode) {
1350 return KEY_STATE_VIRTUAL;
1351 }
1352 } // release exported state lock
1353
1354 return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
1355}
1356
1357int32_t InputReader::getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
1358 int32_t keyCode) const {
1359 { // acquire exported state lock
1360 AutoMutex _l(mExportedStateLock);
1361
1362 if (mExportedVirtualKeyCode == keyCode) {
1363 return KEY_STATE_VIRTUAL;
1364 }
1365 } // release exported state lock
1366
1367 return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
1368}
1369
1370int32_t InputReader::getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
1371 int32_t sw) const {
1372 return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
1373}
1374
1375bool InputReader::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
1376 return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
Jeff Browne839a582010-04-22 18:58:52 -07001377}
1378
1379
1380// --- InputReaderThread ---
1381
1382InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
1383 Thread(/*canCallJava*/ true), mReader(reader) {
1384}
1385
1386InputReaderThread::~InputReaderThread() {
1387}
1388
1389bool InputReaderThread::threadLoop() {
1390 mReader->loopOnce();
1391 return true;
1392}
1393
1394} // namespace android