blob: 30e391ff61d6e8e9324c502f4ba7ee837b436066 [file] [log] [blame]
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070021
Jeff Brown5c225b12010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070032#include <math.h>
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070033
Jeff Brown9c3cda02010-06-15 01:31:58 -070034/** Amount that trackball needs to move in order to generate a key event. */
35#define TRACKBALL_MOVEMENT_THRESHOLD 6
36
Jeff Brown9c3cda02010-06-15 01:31:58 -070037
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070038namespace android {
39
40// --- Static Functions ---
41
42template<typename T>
43inline static T abs(const T& value) {
44 return value < 0 ? - value : value;
45}
46
47template<typename T>
48inline static T min(const T& a, const T& b) {
49 return a < b ? a : b;
50}
51
Jeff Brown5c225b12010-06-16 01:53:36 -070052template<typename T>
53inline static void swap(T& a, T& b) {
54 T temp = a;
55 a = b;
56 b = temp;
57}
58
59
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070060int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
61 int32_t mask;
62 switch (keyCode) {
Jeff Brownfd0358292010-06-30 16:10:35 -070063 case AKEYCODE_ALT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070064 mask = AMETA_ALT_LEFT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070065 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070066 case AKEYCODE_ALT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070067 mask = AMETA_ALT_RIGHT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070068 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070069 case AKEYCODE_SHIFT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070070 mask = AMETA_SHIFT_LEFT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070071 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070072 case AKEYCODE_SHIFT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070073 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070074 break;
Jeff Brownfd0358292010-06-30 16:10:35 -070075 case AKEYCODE_SYM:
Jeff Brownc5ed5912010-07-14 18:48:53 -070076 mask = AMETA_SYM_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070077 break;
78 default:
79 return oldMetaState;
80 }
81
82 int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
Jeff Brownc5ed5912010-07-14 18:48:53 -070083 & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070084
Jeff Brownc5ed5912010-07-14 18:48:53 -070085 if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
86 newMetaState |= AMETA_ALT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070087 }
88
Jeff Brownc5ed5912010-07-14 18:48:53 -070089 if (newMetaState & (AMETA_SHIFT_LEFT_ON | AMETA_SHIFT_RIGHT_ON)) {
90 newMetaState |= AMETA_SHIFT_ON;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -070091 }
92
93 return newMetaState;
94}
95
96static const int32_t keyCodeRotationMap[][4] = {
97 // key codes enumerated counter-clockwise with the original (unrotated) key first
98 // no rotation, 90 degree rotation, 180 degree rotation, 270 degree rotation
Jeff Brownfd0358292010-06-30 16:10:35 -070099 { AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT },
100 { AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN },
101 { AKEYCODE_DPAD_UP, AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT },
102 { AKEYCODE_DPAD_LEFT, AKEYCODE_DPAD_DOWN, AKEYCODE_DPAD_RIGHT, AKEYCODE_DPAD_UP },
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700103};
104static const int keyCodeRotationMapSize =
105 sizeof(keyCodeRotationMap) / sizeof(keyCodeRotationMap[0]);
106
107int32_t rotateKeyCode(int32_t keyCode, int32_t orientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700108 if (orientation != InputReaderPolicyInterface::ROTATION_0) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700109 for (int i = 0; i < keyCodeRotationMapSize; i++) {
110 if (keyCode == keyCodeRotationMap[i][0]) {
111 return keyCodeRotationMap[i][orientation];
112 }
113 }
114 }
115 return keyCode;
116}
117
118
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700119// --- InputReader ---
120
121InputReader::InputReader(const sp<EventHubInterface>& eventHub,
Jeff Brown9c3cda02010-06-15 01:31:58 -0700122 const sp<InputReaderPolicyInterface>& policy,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700123 const sp<InputDispatcherInterface>& dispatcher) :
124 mEventHub(eventHub), mPolicy(policy), mDispatcher(dispatcher) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700125 configureExcludedDevices();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700126 resetGlobalMetaState();
127 resetDisplayProperties();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700128 updateExportedVirtualKeyState();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700129}
130
131InputReader::~InputReader() {
132 for (size_t i = 0; i < mDevices.size(); i++) {
133 delete mDevices.valueAt(i);
134 }
135}
136
137void InputReader::loopOnce() {
138 RawEvent rawEvent;
139 mEventHub->getEvent(& rawEvent.deviceId, & rawEvent.type, & rawEvent.scanCode,
140 & rawEvent.keyCode, & rawEvent.flags, & rawEvent.value, & rawEvent.when);
141
142 // Replace the event timestamp so it is in same timebase as java.lang.System.nanoTime()
143 // and android.os.SystemClock.uptimeMillis() as expected by the rest of the system.
144 rawEvent.when = systemTime(SYSTEM_TIME_MONOTONIC);
145
146#if DEBUG_RAW_EVENTS
147 LOGD("Input event: device=0x%x type=0x%x scancode=%d keycode=%d value=%d",
148 rawEvent.deviceId, rawEvent.type, rawEvent.scanCode, rawEvent.keyCode,
149 rawEvent.value);
150#endif
151
152 process(& rawEvent);
153}
154
155void InputReader::process(const RawEvent* rawEvent) {
156 switch (rawEvent->type) {
157 case EventHubInterface::DEVICE_ADDED:
158 handleDeviceAdded(rawEvent);
159 break;
160
161 case EventHubInterface::DEVICE_REMOVED:
162 handleDeviceRemoved(rawEvent);
163 break;
164
165 case EV_SYN:
166 handleSync(rawEvent);
167 break;
168
169 case EV_KEY:
170 handleKey(rawEvent);
171 break;
172
173 case EV_REL:
174 handleRelativeMotion(rawEvent);
175 break;
176
177 case EV_ABS:
178 handleAbsoluteMotion(rawEvent);
179 break;
180
181 case EV_SW:
182 handleSwitch(rawEvent);
183 break;
184 }
185}
186
187void InputReader::handleDeviceAdded(const RawEvent* rawEvent) {
188 InputDevice* device = getDevice(rawEvent->deviceId);
189 if (device) {
190 LOGW("Ignoring spurious device added event for deviceId %d.", rawEvent->deviceId);
191 return;
192 }
193
194 addDevice(rawEvent->when, rawEvent->deviceId);
195}
196
197void InputReader::handleDeviceRemoved(const RawEvent* rawEvent) {
198 InputDevice* device = getDevice(rawEvent->deviceId);
199 if (! device) {
200 LOGW("Ignoring spurious device removed event for deviceId %d.", rawEvent->deviceId);
201 return;
202 }
203
204 removeDevice(rawEvent->when, device);
205}
206
207void InputReader::handleSync(const RawEvent* rawEvent) {
208 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
209 if (! device) return;
210
211 if (rawEvent->scanCode == SYN_MT_REPORT) {
212 // MultiTouch Sync: The driver has returned all data for *one* of the pointers.
213 // We drop pointers with pressure <= 0 since that indicates they are not down.
214 if (device->isMultiTouchScreen()) {
215 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
216
217 if (device->multiTouchScreen.accumulator.pointers[pointerIndex].fields) {
218 if (pointerIndex == MAX_POINTERS) {
219 LOGW("MultiTouch device driver returned more than maximum of %d pointers.",
220 MAX_POINTERS);
221 } else {
222 pointerIndex += 1;
223 device->multiTouchScreen.accumulator.pointerCount = pointerIndex;
224 }
225 }
226
227 device->multiTouchScreen.accumulator.pointers[pointerIndex].clear();
228 }
229 } else if (rawEvent->scanCode == SYN_REPORT) {
230 // General Sync: The driver has returned all data for the current event update.
231 if (device->isMultiTouchScreen()) {
232 if (device->multiTouchScreen.accumulator.isDirty()) {
233 onMultiTouchScreenStateChanged(rawEvent->when, device);
234 device->multiTouchScreen.accumulator.clear();
235 }
236 } else if (device->isSingleTouchScreen()) {
237 if (device->singleTouchScreen.accumulator.isDirty()) {
238 onSingleTouchScreenStateChanged(rawEvent->when, device);
239 device->singleTouchScreen.accumulator.clear();
240 }
241 }
242
243 if (device->trackball.accumulator.isDirty()) {
244 onTrackballStateChanged(rawEvent->when, device);
245 device->trackball.accumulator.clear();
246 }
247 }
248}
249
250void InputReader::handleKey(const RawEvent* rawEvent) {
251 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
252 if (! device) return;
253
254 bool down = rawEvent->value != 0;
255 int32_t scanCode = rawEvent->scanCode;
256
Jeff Brownfd0358292010-06-30 16:10:35 -0700257 if (device->isSingleTouchScreen()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700258 switch (rawEvent->scanCode) {
259 case BTN_TOUCH:
260 device->singleTouchScreen.accumulator.fields |=
261 InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH;
262 device->singleTouchScreen.accumulator.btnTouch = down;
Jeff Brownfd0358292010-06-30 16:10:35 -0700263 return;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700264 }
Jeff Brownfd0358292010-06-30 16:10:35 -0700265 }
266
267 if (device->isTrackball()) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700268 switch (rawEvent->scanCode) {
269 case BTN_MOUSE:
270 device->trackball.accumulator.fields |=
271 InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
272 device->trackball.accumulator.btnMouse = down;
Jeff Brownd3616592010-07-16 17:21:06 -0700273
274 // Process the trackball change now since we may not receive a sync immediately.
275 onTrackballStateChanged(rawEvent->when, device);
276 device->trackball.accumulator.clear();
Jeff Brownfd0358292010-06-30 16:10:35 -0700277 return;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700278 }
279 }
Jeff Brownfd0358292010-06-30 16:10:35 -0700280
281 if (device->isKeyboard()) {
282 int32_t keyCode = rawEvent->keyCode;
283 onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
284 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700285}
286
287void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
288 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
289 if (! device) return;
290
291 if (device->isTrackball()) {
292 switch (rawEvent->scanCode) {
293 case REL_X:
294 device->trackball.accumulator.fields |=
295 InputDevice::TrackballState::Accumulator::FIELD_REL_X;
296 device->trackball.accumulator.relX = rawEvent->value;
297 break;
298 case REL_Y:
299 device->trackball.accumulator.fields |=
300 InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
301 device->trackball.accumulator.relY = rawEvent->value;
302 break;
303 }
304 }
305}
306
307void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
308 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
309 if (! device) return;
310
311 if (device->isMultiTouchScreen()) {
312 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
313 InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
314 & device->multiTouchScreen.accumulator.pointers[pointerIndex];
315
316 switch (rawEvent->scanCode) {
317 case ABS_MT_POSITION_X:
318 pointer->fields |=
319 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
320 pointer->absMTPositionX = rawEvent->value;
321 break;
322 case ABS_MT_POSITION_Y:
323 pointer->fields |=
324 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
325 pointer->absMTPositionY = rawEvent->value;
326 break;
327 case ABS_MT_TOUCH_MAJOR:
328 pointer->fields |=
329 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
330 pointer->absMTTouchMajor = rawEvent->value;
331 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700332 case ABS_MT_TOUCH_MINOR:
333 pointer->fields |=
334 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
335 pointer->absMTTouchMinor = rawEvent->value;
336 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700337 case ABS_MT_WIDTH_MAJOR:
338 pointer->fields |=
339 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
340 pointer->absMTWidthMajor = rawEvent->value;
341 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700342 case ABS_MT_WIDTH_MINOR:
343 pointer->fields |=
344 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
345 pointer->absMTWidthMinor = rawEvent->value;
346 break;
347 case ABS_MT_ORIENTATION:
348 pointer->fields |=
349 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_ORIENTATION;
350 pointer->absMTOrientation = rawEvent->value;
351 break;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700352 case ABS_MT_TRACKING_ID:
353 pointer->fields |=
354 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
355 pointer->absMTTrackingId = rawEvent->value;
356 break;
357 }
358 } else if (device->isSingleTouchScreen()) {
359 switch (rawEvent->scanCode) {
360 case ABS_X:
361 device->singleTouchScreen.accumulator.fields |=
362 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
363 device->singleTouchScreen.accumulator.absX = rawEvent->value;
364 break;
365 case ABS_Y:
366 device->singleTouchScreen.accumulator.fields |=
367 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
368 device->singleTouchScreen.accumulator.absY = rawEvent->value;
369 break;
370 case ABS_PRESSURE:
371 device->singleTouchScreen.accumulator.fields |=
372 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
373 device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
374 break;
375 case ABS_TOOL_WIDTH:
376 device->singleTouchScreen.accumulator.fields |=
377 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
378 device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
379 break;
380 }
381 }
382}
383
384void InputReader::handleSwitch(const RawEvent* rawEvent) {
385 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
386 if (! device) return;
387
Jeff Brown9c3cda02010-06-15 01:31:58 -0700388 onSwitch(rawEvent->when, device, rawEvent->scanCode, rawEvent->value);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700389}
390
391void InputReader::onKey(nsecs_t when, InputDevice* device,
392 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
393 /* Refresh display properties so we can rotate key codes according to display orientation */
394
395 if (! refreshDisplayProperties()) {
396 return;
397 }
398
399 /* Update device state */
400
401 int32_t oldMetaState = device->keyboard.current.metaState;
402 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
403 if (oldMetaState != newMetaState) {
404 device->keyboard.current.metaState = newMetaState;
405 resetGlobalMetaState();
406 }
407
408 // FIXME if we send a down event about a rotated key press we should ensure that we send
409 // a corresponding up event about the rotated key press even if the orientation
410 // has changed in the meantime
411 keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
412
413 if (down) {
414 device->keyboard.current.downTime = when;
415 }
416
417 /* Apply policy */
418
419 int32_t policyActions = mPolicy->interceptKey(when, device->id,
420 down, keyCode, scanCode, policyFlags);
421
422 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
423 return; // event dropped
424 }
425
426 /* Enqueue key event for dispatch */
427
428 int32_t keyEventAction;
429 if (down) {
430 device->keyboard.current.downTime = when;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700431 keyEventAction = AKEY_EVENT_ACTION_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700432 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700433 keyEventAction = AKEY_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700434 }
435
Jeff Brownc5ed5912010-07-14 18:48:53 -0700436 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700437 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700438 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700439 }
440
Jeff Brownc5ed5912010-07-14 18:48:53 -0700441 mDispatcher->notifyKey(when, device->id, AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700442 keyEventAction, keyEventFlags, keyCode, scanCode,
443 device->keyboard.current.metaState,
444 device->keyboard.current.downTime);
445}
446
Jeff Brown9c3cda02010-06-15 01:31:58 -0700447void InputReader::onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode,
448 int32_t switchValue) {
449 int32_t policyActions = mPolicy->interceptSwitch(when, switchCode, switchValue);
450
451 uint32_t policyFlags = 0;
452 applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700453}
454
455void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
456 InputDevice* device) {
457 static const uint32_t REQUIRED_FIELDS =
458 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
459 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
460 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
461 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
462
463 /* Refresh display properties so we can map touch screen coords into display coords */
464
465 if (! refreshDisplayProperties()) {
466 return;
467 }
468
469 /* Update device state */
470
471 InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
472 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
473
474 uint32_t inCount = in->accumulator.pointerCount;
475 uint32_t outCount = 0;
476 bool havePointerIds = true;
477
478 out->clear();
479
480 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
481 uint32_t fields = in->accumulator.pointers[inIndex].fields;
482
483 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
484#if DEBUG_POINTERS
485 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
486 inIndex, fields);
487 continue;
488#endif
489 }
490
491 if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
492 // Pointer is not down. Drop it.
493 continue;
494 }
495
Jeff Brownc5ed5912010-07-14 18:48:53 -0700496 out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
497 out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
498
499 out->pointers[outCount].touchMajor = in->accumulator.pointers[inIndex].absMTTouchMajor;
500 out->pointers[outCount].touchMinor = (fields
501 & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
502 ? in->accumulator.pointers[inIndex].absMTTouchMinor
503 : in->accumulator.pointers[inIndex].absMTTouchMajor;
504
505 out->pointers[outCount].toolMajor = in->accumulator.pointers[inIndex].absMTWidthMajor;
506 out->pointers[outCount].toolMinor = (fields
507 & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
508 ? in->accumulator.pointers[inIndex].absMTWidthMinor
509 : in->accumulator.pointers[inIndex].absMTWidthMajor;
510
511 out->pointers[outCount].orientation = (fields
512 & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
513 ? in->accumulator.pointers[inIndex].absMTOrientation : 0;
514
515 // Derive an approximation of pressure and size.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700516 // FIXME assignment of pressure may be incorrect, probably better to let
517 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
518 // isn't quite right either. Should be using touch for that.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700519 out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
520 out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
521
522 if (havePointerIds) {
523 if (fields & InputDevice::MultiTouchScreenState::Accumulator::
524 FIELD_ABS_MT_TRACKING_ID) {
525 uint32_t id = uint32_t(in->accumulator.pointers[inIndex].absMTTrackingId);
526
527 if (id > MAX_POINTER_ID) {
528#if DEBUG_POINTERS
529 LOGD("Pointers: Ignoring driver provided pointer id %d because "
530 "it is larger than max supported id %d for optimizations",
531 id, MAX_POINTER_ID);
532#endif
533 havePointerIds = false;
534 }
535 else {
536 out->pointers[outCount].id = id;
537 out->idToIndex[id] = outCount;
538 out->idBits.markBit(id);
539 }
540 } else {
541 havePointerIds = false;
542 }
543 }
544
545 outCount += 1;
546 }
547
548 out->pointerCount = outCount;
549
550 onTouchScreenChanged(when, device, havePointerIds);
551}
552
553void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
554 InputDevice* device) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700555 /* Refresh display properties so we can map touch screen coords into display coords */
556
557 if (! refreshDisplayProperties()) {
558 return;
559 }
560
561 /* Update device state */
562
563 InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
564 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
565
566 uint32_t fields = in->accumulator.fields;
567
568 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
569 in->current.down = in->accumulator.btnTouch;
570 }
571
Jeff Brown349703e2010-06-22 01:27:15 -0700572 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700573 in->current.x = in->accumulator.absX;
Jeff Brown349703e2010-06-22 01:27:15 -0700574 }
575
576 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700577 in->current.y = in->accumulator.absY;
Jeff Brown349703e2010-06-22 01:27:15 -0700578 }
579
580 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700581 in->current.pressure = in->accumulator.absPressure;
Jeff Brown349703e2010-06-22 01:27:15 -0700582 }
583
584 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700585 in->current.size = in->accumulator.absToolWidth;
586 }
587
588 out->clear();
589
590 if (in->current.down) {
591 out->pointerCount = 1;
592 out->pointers[0].id = 0;
593 out->pointers[0].x = in->current.x;
594 out->pointers[0].y = in->current.y;
595 out->pointers[0].pressure = in->current.pressure;
596 out->pointers[0].size = in->current.size;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700597 out->pointers[0].touchMajor = in->current.pressure;
598 out->pointers[0].touchMinor = in->current.pressure;
599 out->pointers[0].toolMajor = in->current.size;
600 out->pointers[0].toolMinor = in->current.size;
601 out->pointers[0].orientation = 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700602 out->idToIndex[0] = 0;
603 out->idBits.markBit(0);
604 }
605
606 onTouchScreenChanged(when, device, true);
607}
608
609void InputReader::onTouchScreenChanged(nsecs_t when,
610 InputDevice* device, bool havePointerIds) {
611 /* Apply policy */
612
613 int32_t policyActions = mPolicy->interceptTouch(when);
614
615 uint32_t policyFlags = 0;
616 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
617 device->touchScreen.lastTouch.clear();
618 return; // event dropped
619 }
620
621 /* Preprocess pointer data */
622
623 if (device->touchScreen.parameters.useBadTouchFilter) {
624 if (device->touchScreen.applyBadTouchFilter()) {
625 havePointerIds = false;
626 }
627 }
628
629 if (device->touchScreen.parameters.useJumpyTouchFilter) {
630 if (device->touchScreen.applyJumpyTouchFilter()) {
631 havePointerIds = false;
632 }
633 }
634
635 if (! havePointerIds) {
636 device->touchScreen.calculatePointerIds();
637 }
638
639 InputDevice::TouchData temp;
640 InputDevice::TouchData* savedTouch;
641 if (device->touchScreen.parameters.useAveragingTouchFilter) {
642 temp.copyFrom(device->touchScreen.currentTouch);
643 savedTouch = & temp;
644
645 device->touchScreen.applyAveragingTouchFilter();
646 } else {
647 savedTouch = & device->touchScreen.currentTouch;
648 }
649
650 /* Process virtual keys or touches */
651
652 if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
653 dispatchTouches(when, device, policyFlags);
654 }
655
656 // Copy current touch to last touch in preparation for the next cycle.
657 device->touchScreen.lastTouch.copyFrom(*savedTouch);
658}
659
660bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
661 InputDevice* device, uint32_t policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700662 switch (device->touchScreen.currentVirtualKey.status) {
663 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700664 if (device->touchScreen.currentTouch.pointerCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700665 // Pointer went up after virtual key canceled.
666 device->touchScreen.currentVirtualKey.status =
667 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
668 }
669 return true; // consumed
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700670
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700671 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN:
672 if (device->touchScreen.currentTouch.pointerCount == 0) {
673 // Pointer went up while virtual key was down.
674 device->touchScreen.currentVirtualKey.status =
675 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700676#if DEBUG_VIRTUAL_KEYS
677 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
678 device->touchScreen.currentVirtualKey.keyCode,
679 device->touchScreen.currentVirtualKey.scanCode);
680#endif
Jeff Brownc5ed5912010-07-14 18:48:53 -0700681 dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_UP,
682 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700683 return true; // consumed
684 }
685
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700686 if (device->touchScreen.currentTouch.pointerCount == 1) {
687 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
688 if (virtualKey
689 && virtualKey->keyCode == device->touchScreen.currentVirtualKey.keyCode) {
690 // Pointer is still within the space of the virtual key.
691 return true; // consumed
692 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700693 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700694
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700695 // Pointer left virtual key area or another pointer also went down.
696 // Send key cancellation.
697 device->touchScreen.currentVirtualKey.status =
698 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700699#if DEBUG_VIRTUAL_KEYS
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700700 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
701 device->touchScreen.currentVirtualKey.keyCode,
702 device->touchScreen.currentVirtualKey.scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700703#endif
Jeff Brownc5ed5912010-07-14 18:48:53 -0700704 dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_UP,
705 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
706 | AKEY_EVENT_FLAG_CANCELED);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700707 return true; // consumed
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700708
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700709 default:
710 if (device->touchScreen.currentTouch.pointerCount == 1
711 && device->touchScreen.lastTouch.pointerCount == 0) {
712 // Pointer just went down. Check for virtual key hit.
713 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
714 if (virtualKey) {
715 device->touchScreen.currentVirtualKey.status =
716 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700717 device->touchScreen.currentVirtualKey.downTime = when;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700718 device->touchScreen.currentVirtualKey.keyCode = virtualKey->keyCode;
719 device->touchScreen.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700720#if DEBUG_VIRTUAL_KEYS
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700721 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
722 device->touchScreen.currentVirtualKey.keyCode,
723 device->touchScreen.currentVirtualKey.scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700724#endif
Jeff Brownc5ed5912010-07-14 18:48:53 -0700725 dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_DOWN,
726 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700727 return true; // consumed
728 }
729 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700730 return false; // not consumed
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700731 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700732}
733
734void InputReader::dispatchVirtualKey(nsecs_t when,
735 InputDevice* device, uint32_t policyFlags,
736 int32_t keyEventAction, int32_t keyEventFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -0700737 updateExportedVirtualKeyState();
738
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700739 int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
740 int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
741 nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
742 int32_t metaState = globalMetaState();
743
Jeff Brownc5ed5912010-07-14 18:48:53 -0700744 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700745 mPolicy->virtualKeyDownFeedback();
746 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700747
Jeff Brown349703e2010-06-22 01:27:15 -0700748 int32_t policyActions = mPolicy->interceptKey(when, device->id,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700749 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -0700750
751 if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700752 mDispatcher->notifyKey(when, device->id, AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700753 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
754 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700755}
756
757void InputReader::dispatchTouches(nsecs_t when,
758 InputDevice* device, uint32_t policyFlags) {
759 uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
760 uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
761 if (currentPointerCount == 0 && lastPointerCount == 0) {
762 return; // nothing to do!
763 }
764
765 BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
766 BitSet32 lastIdBits = device->touchScreen.lastTouch.idBits;
767
768 if (currentIdBits == lastIdBits) {
769 // No pointer id changes so this is a move event.
770 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700771 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700772 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -0700773 currentIdBits, -1, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700774 } else {
775 // There may be pointers going up and pointers going down at the same time when pointer
776 // ids are reported by the device driver.
777 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
778 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
779 BitSet32 activeIdBits(lastIdBits.value);
780
781 while (! upIdBits.isEmpty()) {
782 uint32_t upId = upIdBits.firstMarkedBit();
783 upIdBits.clearBit(upId);
784 BitSet32 oldActiveIdBits = activeIdBits;
785 activeIdBits.clearBit(upId);
786
787 int32_t motionEventAction;
788 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700789 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700790 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -0700791 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700792 }
793
794 dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -0700795 oldActiveIdBits, upId, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700796 }
797
798 while (! downIdBits.isEmpty()) {
799 uint32_t downId = downIdBits.firstMarkedBit();
800 downIdBits.clearBit(downId);
801 BitSet32 oldActiveIdBits = activeIdBits;
802 activeIdBits.markBit(downId);
803
804 int32_t motionEventAction;
805 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700806 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700807 device->touchScreen.downTime = when;
808 } else {
Jeff Brown00ba8842010-07-16 15:01:56 -0700809 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700810 }
811
812 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
Jeff Brown00ba8842010-07-16 15:01:56 -0700813 activeIdBits, downId, motionEventAction);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700814 }
815 }
816}
817
818void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
Jeff Brown00ba8842010-07-16 15:01:56 -0700819 InputDevice::TouchData* touch, BitSet32 idBits, uint32_t changedId,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700820 int32_t motionEventAction) {
821 int32_t orientedWidth, orientedHeight;
822 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700823 case InputReaderPolicyInterface::ROTATION_90:
824 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700825 orientedWidth = mDisplayHeight;
826 orientedHeight = mDisplayWidth;
827 break;
828 default:
829 orientedWidth = mDisplayWidth;
830 orientedHeight = mDisplayHeight;
831 break;
832 }
833
834 uint32_t pointerCount = 0;
835 int32_t pointerIds[MAX_POINTERS];
836 PointerCoords pointerCoords[MAX_POINTERS];
837
Jeff Brown0b72e822010-06-29 16:52:21 -0700838 const InputDevice::TouchScreenState::Precalculated& precalculated =
839 device->touchScreen.precalculated;
840
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700841 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
842 // display coordinates (PointerCoords) and adjust for display orientation.
843 while (! idBits.isEmpty()) {
844 uint32_t id = idBits.firstMarkedBit();
845 idBits.clearBit(id);
846 uint32_t index = touch->idToIndex[id];
847
Jeff Brown0b72e822010-06-29 16:52:21 -0700848 float x = float(touch->pointers[index].x
849 - precalculated.xOrigin) * precalculated.xScale;
850 float y = float(touch->pointers[index].y
851 - precalculated.yOrigin) * precalculated.yScale;
852 float pressure = float(touch->pointers[index].pressure
853 - precalculated.pressureOrigin) * precalculated.pressureScale;
854 float size = float(touch->pointers[index].size
855 - precalculated.sizeOrigin) * precalculated.sizeScale;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700856
Jeff Brownc5ed5912010-07-14 18:48:53 -0700857 float orientation = float(touch->pointers[index].orientation)
858 * precalculated.orientationScale;
859
860 bool vertical = abs(orientation) <= M_PI / 8;
861
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700862 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700863 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700864 float xTemp = x;
865 x = y;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700866 y = mDisplayWidth - xTemp;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700867 vertical = ! vertical;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700868 break;
869 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700870 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700871 x = mDisplayWidth - x;
872 y = mDisplayHeight - y;
873 break;
874 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700875 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700876 float xTemp = x;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700877 x = mDisplayHeight - y;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700878 y = xTemp;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700879 vertical = ! vertical;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700880 break;
881 }
882 }
883
Jeff Brownc5ed5912010-07-14 18:48:53 -0700884 float touchMajor, touchMinor, toolMajor, toolMinor;
885 if (vertical) {
886 touchMajor = float(touch->pointers[index].touchMajor) * precalculated.yScale;
887 touchMinor = float(touch->pointers[index].touchMinor) * precalculated.xScale;
888 toolMajor = float(touch->pointers[index].toolMajor) * precalculated.yScale;
889 toolMinor = float(touch->pointers[index].toolMinor) * precalculated.xScale;
890 } else {
891 touchMajor = float(touch->pointers[index].touchMajor) * precalculated.xScale;
892 touchMinor = float(touch->pointers[index].touchMinor) * precalculated.yScale;
893 toolMajor = float(touch->pointers[index].toolMajor) * precalculated.xScale;
894 toolMinor = float(touch->pointers[index].toolMinor) * precalculated.yScale;
895 }
896
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700897 pointerIds[pointerCount] = int32_t(id);
898
899 pointerCoords[pointerCount].x = x;
900 pointerCoords[pointerCount].y = y;
901 pointerCoords[pointerCount].pressure = pressure;
902 pointerCoords[pointerCount].size = size;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700903 pointerCoords[pointerCount].touchMajor = touchMajor;
904 pointerCoords[pointerCount].touchMinor = touchMinor;
905 pointerCoords[pointerCount].toolMajor = toolMajor;
906 pointerCoords[pointerCount].toolMinor = toolMinor;
907 pointerCoords[pointerCount].orientation = orientation;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700908
Jeff Brown00ba8842010-07-16 15:01:56 -0700909 if (id == changedId) {
910 motionEventAction |= pointerCount << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT;
911 }
912
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700913 pointerCount += 1;
914 }
915
916 // Check edge flags by looking only at the first pointer since the flags are
917 // global to the event.
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700918 int32_t motionEventEdgeFlags = 0;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700919 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700920 if (pointerCoords[0].x <= 0) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700921 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700922 } else if (pointerCoords[0].x >= orientedWidth) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700923 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700924 }
925 if (pointerCoords[0].y <= 0) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700926 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700927 } else if (pointerCoords[0].y >= orientedHeight) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700928 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700929 }
930 }
931
932 nsecs_t downTime = device->touchScreen.downTime;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700933 mDispatcher->notifyMotion(when, device->id, AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700934 motionEventAction, globalMetaState(), motionEventEdgeFlags,
935 pointerCount, pointerIds, pointerCoords,
936 0, 0, downTime);
937}
938
939void InputReader::onTrackballStateChanged(nsecs_t when,
940 InputDevice* device) {
941 static const uint32_t DELTA_FIELDS =
942 InputDevice::TrackballState::Accumulator::FIELD_REL_X
943 | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
944
945 /* Refresh display properties so we can trackball moves according to display orientation */
946
947 if (! refreshDisplayProperties()) {
948 return;
949 }
950
951 /* Update device state */
952
953 uint32_t fields = device->trackball.accumulator.fields;
954 bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700955 bool deltaChanged = fields & DELTA_FIELDS;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700956
957 bool down;
958 if (downChanged) {
959 if (device->trackball.accumulator.btnMouse) {
960 device->trackball.current.down = true;
961 device->trackball.current.downTime = when;
962 down = true;
963 } else {
964 device->trackball.current.down = false;
965 down = false;
966 }
967 } else {
968 down = device->trackball.current.down;
969 }
970
971 /* Apply policy */
972
973 int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
974
975 uint32_t policyFlags = 0;
976 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
977 return; // event dropped
978 }
979
980 /* Enqueue motion event for dispatch */
981
982 int32_t motionEventAction;
983 if (downChanged) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700984 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700985 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700986 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700987 }
988
989 int32_t pointerId = 0;
990 PointerCoords pointerCoords;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700991 pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
992 ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
993 pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
994 ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -0700995 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
996 pointerCoords.size = 0;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700997 pointerCoords.touchMajor = 0;
998 pointerCoords.touchMinor = 0;
999 pointerCoords.toolMajor = 0;
1000 pointerCoords.toolMinor = 0;
1001 pointerCoords.orientation = 0;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001002
1003 float temp;
1004 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001005 case InputReaderPolicyInterface::ROTATION_90:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001006 temp = pointerCoords.x;
1007 pointerCoords.x = pointerCoords.y;
1008 pointerCoords.y = - temp;
1009 break;
1010
Jeff Brown9c3cda02010-06-15 01:31:58 -07001011 case InputReaderPolicyInterface::ROTATION_180:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001012 pointerCoords.x = - pointerCoords.x;
1013 pointerCoords.y = - pointerCoords.y;
1014 break;
1015
Jeff Brown9c3cda02010-06-15 01:31:58 -07001016 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001017 temp = pointerCoords.x;
1018 pointerCoords.x = - pointerCoords.y;
1019 pointerCoords.y = temp;
1020 break;
1021 }
1022
Jeff Brownc5ed5912010-07-14 18:48:53 -07001023 mDispatcher->notifyMotion(when, device->id, AINPUT_SOURCE_TRACKBALL, policyFlags,
1024 motionEventAction, globalMetaState(), AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001025 1, & pointerId, & pointerCoords,
1026 device->trackball.precalculated.xPrecision,
1027 device->trackball.precalculated.yPrecision,
1028 device->trackball.current.downTime);
1029}
1030
1031void InputReader::onConfigurationChanged(nsecs_t when) {
1032 // Reset global meta state because it depends on the list of all configured devices.
1033 resetGlobalMetaState();
1034
1035 // Reset virtual keys, just in case.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001036 updateExportedVirtualKeyState();
1037
1038 // Update input configuration.
1039 updateExportedInputConfiguration();
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001040
1041 // Enqueue configuration changed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001042 mDispatcher->notifyConfigurationChanged(when);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001043}
1044
1045bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
1046 int32_t policyActions, uint32_t* policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001047 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001048 mDispatcher->notifyAppSwitchComing(when);
1049 }
1050
Jeff Brown9c3cda02010-06-15 01:31:58 -07001051 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001052 *policyFlags |= POLICY_FLAG_WOKE_HERE;
1053 }
1054
Jeff Brown9c3cda02010-06-15 01:31:58 -07001055 if (policyActions & InputReaderPolicyInterface::ACTION_BRIGHT_HERE) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001056 *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
1057 }
1058
Jeff Brown9c3cda02010-06-15 01:31:58 -07001059 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001060}
1061
1062void InputReader::resetDisplayProperties() {
1063 mDisplayWidth = mDisplayHeight = -1;
1064 mDisplayOrientation = -1;
1065}
1066
1067bool InputReader::refreshDisplayProperties() {
1068 int32_t newWidth, newHeight, newOrientation;
1069 if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
1070 if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
1071 LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
1072 mDisplayWidth, mDisplayHeight, newWidth, newHeight);
1073
1074 mDisplayWidth = newWidth;
1075 mDisplayHeight = newHeight;
1076
1077 for (size_t i = 0; i < mDevices.size(); i++) {
1078 configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
1079 }
1080 }
1081
Jeff Brown0b72e822010-06-29 16:52:21 -07001082 if (newOrientation != mDisplayOrientation) {
1083 LOGD("Display orientation changed to %d", mDisplayOrientation);
1084
1085 mDisplayOrientation = newOrientation;
1086 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001087 return true;
1088 } else {
1089 resetDisplayProperties();
1090 return false;
1091 }
1092}
1093
1094InputDevice* InputReader::getDevice(int32_t deviceId) {
1095 ssize_t index = mDevices.indexOfKey(deviceId);
1096 return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
1097}
1098
1099InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
1100 InputDevice* device = getDevice(deviceId);
1101 return device && ! device->ignored ? device : NULL;
1102}
1103
1104void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
1105 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
1106 String8 name = mEventHub->getDeviceName(deviceId);
1107 InputDevice* device = new InputDevice(deviceId, classes, name);
1108
1109 if (classes != 0) {
1110 LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
1111 device->name.string(), device->classes);
1112
1113 configureDevice(device);
1114 } else {
1115 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
1116 device->name.string());
1117
1118 device->ignored = true;
1119 }
1120
1121 device->reset();
1122
1123 mDevices.add(deviceId, device);
1124
1125 if (! device->ignored) {
1126 onConfigurationChanged(when);
1127 }
1128}
1129
1130void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
1131 mDevices.removeItem(device->id);
1132
1133 if (! device->ignored) {
1134 LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
1135 device->name.string(), device->classes);
1136
1137 onConfigurationChanged(when);
1138 } else {
1139 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
1140 device->name.string());
1141 }
1142
1143 delete device;
1144}
1145
1146void InputReader::configureDevice(InputDevice* device) {
1147 if (device->isMultiTouchScreen()) {
1148 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
1149 & device->touchScreen.parameters.xAxis);
1150 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
1151 & device->touchScreen.parameters.yAxis);
1152 configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
1153 & device->touchScreen.parameters.pressureAxis);
1154 configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
1155 & device->touchScreen.parameters.sizeAxis);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001156 configureAbsoluteAxisInfo(device, ABS_MT_ORIENTATION, "Orientation",
1157 & device->touchScreen.parameters.orientationAxis);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001158 } else if (device->isSingleTouchScreen()) {
1159 configureAbsoluteAxisInfo(device, ABS_X, "X",
1160 & device->touchScreen.parameters.xAxis);
1161 configureAbsoluteAxisInfo(device, ABS_Y, "Y",
1162 & device->touchScreen.parameters.yAxis);
1163 configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
1164 & device->touchScreen.parameters.pressureAxis);
1165 configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
1166 & device->touchScreen.parameters.sizeAxis);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001167 device->touchScreen.parameters.orientationAxis.valid = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001168 }
1169
1170 if (device->isTouchScreen()) {
1171 device->touchScreen.parameters.useBadTouchFilter =
1172 mPolicy->filterTouchEvents();
1173 device->touchScreen.parameters.useAveragingTouchFilter =
1174 mPolicy->filterTouchEvents();
1175 device->touchScreen.parameters.useJumpyTouchFilter =
1176 mPolicy->filterJumpyTouchEvents();
1177
Jeff Brown0b72e822010-06-29 16:52:21 -07001178 if (device->touchScreen.parameters.pressureAxis.valid) {
1179 device->touchScreen.precalculated.pressureOrigin =
1180 device->touchScreen.parameters.pressureAxis.minValue;
1181 device->touchScreen.precalculated.pressureScale =
1182 1.0f / device->touchScreen.parameters.pressureAxis.range;
1183 } else {
1184 device->touchScreen.precalculated.pressureOrigin = 0;
1185 device->touchScreen.precalculated.pressureScale = 1.0f;
1186 }
1187
1188 if (device->touchScreen.parameters.sizeAxis.valid) {
1189 device->touchScreen.precalculated.sizeOrigin =
1190 device->touchScreen.parameters.sizeAxis.minValue;
1191 device->touchScreen.precalculated.sizeScale =
1192 1.0f / device->touchScreen.parameters.sizeAxis.range;
1193 } else {
1194 device->touchScreen.precalculated.sizeOrigin = 0;
1195 device->touchScreen.precalculated.sizeScale = 1.0f;
1196 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001197
1198 if (device->touchScreen.parameters.orientationAxis.valid
1199 && device->touchScreen.parameters.orientationAxis.maxValue > 0) {
1200 device->touchScreen.precalculated.orientationScale =
1201 M_PI_4 / device->touchScreen.parameters.orientationAxis.maxValue;
1202 } else {
1203 device->touchScreen.precalculated.orientationScale = 0.0f;
1204 }
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001205 }
1206
1207 if (device->isTrackball()) {
1208 device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1209 device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1210 device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1211 device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1212 }
1213
1214 configureDeviceForCurrentDisplaySize(device);
1215}
1216
1217void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
1218 if (device->isTouchScreen()) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001219 if (device->touchScreen.parameters.xAxis.valid
1220 && device->touchScreen.parameters.yAxis.valid) {
1221 device->touchScreen.precalculated.xOrigin =
1222 device->touchScreen.parameters.xAxis.minValue;
1223 device->touchScreen.precalculated.yOrigin =
1224 device->touchScreen.parameters.yAxis.minValue;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001225
Jeff Brown0b72e822010-06-29 16:52:21 -07001226 if (mDisplayWidth < 0) {
1227 LOGD("Skipping part of touch screen configuration since display size is unknown.");
1228
1229 device->touchScreen.precalculated.xScale = 1.0f;
1230 device->touchScreen.precalculated.yScale = 1.0f;
1231 } else {
1232 LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
1233 device->name.string());
1234
1235 device->touchScreen.precalculated.xScale =
1236 float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
1237 device->touchScreen.precalculated.yScale =
1238 float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
1239
1240 configureVirtualKeys(device);
1241 }
1242 } else {
1243 device->touchScreen.precalculated.xOrigin = 0;
1244 device->touchScreen.precalculated.xScale = 1.0f;
1245 device->touchScreen.precalculated.yOrigin = 0;
1246 device->touchScreen.precalculated.yScale = 1.0f;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001247 }
1248 }
1249}
1250
1251void InputReader::configureVirtualKeys(InputDevice* device) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001252 assert(device->touchScreen.parameters.xAxis.valid
1253 && device->touchScreen.parameters.yAxis.valid);
1254
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001255 device->touchScreen.virtualKeys.clear();
1256
Jeff Brown9c3cda02010-06-15 01:31:58 -07001257 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001258 mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
1259 if (virtualKeyDefinitions.size() == 0) {
1260 return;
1261 }
1262
1263 device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1264
1265 int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
1266 int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
1267 int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
1268 int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
1269
1270 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001271 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001272 virtualKeyDefinitions[i];
1273
1274 device->touchScreen.virtualKeys.add();
1275 InputDevice::VirtualKey& virtualKey =
1276 device->touchScreen.virtualKeys.editTop();
1277
1278 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1279 int32_t keyCode;
1280 uint32_t flags;
1281 if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
1282 & keyCode, & flags)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001283 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001284 device->touchScreen.virtualKeys.pop(); // drop the key
1285 continue;
1286 }
1287
1288 virtualKey.keyCode = keyCode;
1289 virtualKey.flags = flags;
1290
1291 // convert the key definition's display coordinates into touch coordinates for a hit box
1292 int32_t halfWidth = virtualKeyDefinition.width / 2;
1293 int32_t halfHeight = virtualKeyDefinition.height / 2;
1294
1295 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1296 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1297 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1298 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1299 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1300 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1301 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1302 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1303
1304 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1305 virtualKey.scanCode, virtualKey.keyCode,
1306 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1307 }
1308}
1309
1310void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
1311 int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
1312 if (! mEventHub->getAbsoluteInfo(device->id, axis,
1313 & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
1314 out->range = out->maxValue - out->minValue;
1315 if (out->range != 0) {
1316 LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
1317 name, out->minValue, out->maxValue, out->flat, out->fuzz);
Jeff Brown0b72e822010-06-29 16:52:21 -07001318 out->valid = true;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001319 return;
1320 }
1321 }
1322
Jeff Brown0b72e822010-06-29 16:52:21 -07001323 out->valid = false;
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001324 out->minValue = 0;
1325 out->maxValue = 0;
1326 out->flat = 0;
1327 out->fuzz = 0;
1328 out->range = 0;
Jeff Brown0b72e822010-06-29 16:52:21 -07001329 LOGI(" %s: unknown axis values, marking as invalid", name);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001330}
1331
Jeff Brown9c3cda02010-06-15 01:31:58 -07001332void InputReader::configureExcludedDevices() {
1333 Vector<String8> excludedDeviceNames;
1334 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
1335
1336 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
1337 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
1338 }
1339}
1340
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001341void InputReader::resetGlobalMetaState() {
1342 mGlobalMetaState = -1;
1343}
1344
1345int32_t InputReader::globalMetaState() {
1346 if (mGlobalMetaState == -1) {
1347 mGlobalMetaState = 0;
1348 for (size_t i = 0; i < mDevices.size(); i++) {
1349 InputDevice* device = mDevices.valueAt(i);
1350 if (device->isKeyboard()) {
1351 mGlobalMetaState |= device->keyboard.current.metaState;
1352 }
1353 }
1354 }
1355 return mGlobalMetaState;
1356}
1357
Jeff Brown9c3cda02010-06-15 01:31:58 -07001358void InputReader::updateExportedVirtualKeyState() {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001359 int32_t keyCode = -1, scanCode = -1;
1360
1361 for (size_t i = 0; i < mDevices.size(); i++) {
1362 InputDevice* device = mDevices.valueAt(i);
1363 if (device->isTouchScreen()) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001364 if (device->touchScreen.currentVirtualKey.status
1365 == InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN) {
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001366 keyCode = device->touchScreen.currentVirtualKey.keyCode;
1367 scanCode = device->touchScreen.currentVirtualKey.scanCode;
1368 }
1369 }
1370 }
1371
Jeff Brown9c3cda02010-06-15 01:31:58 -07001372 { // acquire exported state lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001373 AutoMutex _l(mExportedStateLock);
1374
Jeff Brown9c3cda02010-06-15 01:31:58 -07001375 mExportedVirtualKeyCode = keyCode;
1376 mExportedVirtualScanCode = scanCode;
1377 } // release exported state lock
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001378}
1379
1380bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001381 { // acquire exported state lock
1382 AutoMutex _l(mExportedStateLock);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001383
Jeff Brown9c3cda02010-06-15 01:31:58 -07001384 *outKeyCode = mExportedVirtualKeyCode;
1385 *outScanCode = mExportedVirtualScanCode;
1386 return mExportedVirtualKeyCode != -1;
1387 } // release exported state lock
1388}
1389
1390void InputReader::updateExportedInputConfiguration() {
1391 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
1392 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
1393 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
1394
1395 for (size_t i = 0; i < mDevices.size(); i++) {
1396 InputDevice* device = mDevices.valueAt(i);
1397 int32_t deviceClasses = device->classes;
1398
1399 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
1400 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
1401 }
1402 if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
1403 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
1404 }
1405 if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
1406 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
1407 } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
1408 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
1409 }
1410 }
1411
1412 { // acquire exported state lock
1413 AutoMutex _l(mExportedStateLock);
1414
1415 mExportedInputConfiguration.touchScreen = touchScreenConfig;
1416 mExportedInputConfiguration.keyboard = keyboardConfig;
1417 mExportedInputConfiguration.navigation = navigationConfig;
1418 } // release exported state lock
1419}
1420
1421void InputReader::getCurrentInputConfiguration(InputConfiguration* outConfiguration) const {
1422 { // acquire exported state lock
1423 AutoMutex _l(mExportedStateLock);
1424
1425 *outConfiguration = mExportedInputConfiguration;
1426 } // release exported state lock
1427}
1428
1429int32_t InputReader::getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
1430 int32_t scanCode) const {
1431 { // acquire exported state lock
1432 AutoMutex _l(mExportedStateLock);
1433
1434 if (mExportedVirtualScanCode == scanCode) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001435 return AKEY_STATE_VIRTUAL;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001436 }
1437 } // release exported state lock
1438
1439 return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
1440}
1441
1442int32_t InputReader::getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
1443 int32_t keyCode) const {
1444 { // acquire exported state lock
1445 AutoMutex _l(mExportedStateLock);
1446
1447 if (mExportedVirtualKeyCode == keyCode) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001448 return AKEY_STATE_VIRTUAL;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001449 }
1450 } // release exported state lock
1451
1452 return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
1453}
1454
1455int32_t InputReader::getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
1456 int32_t sw) const {
1457 return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
1458}
1459
1460bool InputReader::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
1461 return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
Jeff Brown46b9ac0a2010-04-22 18:58:52 -07001462}
1463
1464
1465// --- InputReaderThread ---
1466
1467InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
1468 Thread(/*canCallJava*/ true), mReader(reader) {
1469}
1470
1471InputReaderThread::~InputReaderThread() {
1472}
1473
1474bool InputReaderThread::threadLoop() {
1475 mReader->loopOnce();
1476 return true;
1477}
1478
1479} // namespace android