blob: cd4654a6899fc36057a6f89ed8750565321f2cd8 [file] [log] [blame]
Jeff Brown46b9ac02010-04-22 18:58:52 -07001//
2// Copyright 2010 The Android Open Source Project
3//
4// The input reader.
5//
6#define LOG_TAG "InputReader"
7
8//#define LOG_NDEBUG 0
9
10// Log debug messages for each raw event received from the EventHub.
11#define DEBUG_RAW_EVENTS 0
12
13// Log debug messages about touch screen filtering hacks.
Jeff Brown349703e2010-06-22 01:27:15 -070014#define DEBUG_HACKS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070015
16// Log debug messages about virtual key processing.
Jeff Brown349703e2010-06-22 01:27:15 -070017#define DEBUG_VIRTUAL_KEYS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070018
19// Log debug messages about pointers.
Jeff Brown349703e2010-06-22 01:27:15 -070020#define DEBUG_POINTERS 0
Jeff Brown46b9ac02010-04-22 18:58:52 -070021
Jeff Brown5c225b12010-06-16 01:53:36 -070022// Log debug messages about pointer assignment calculations.
23#define DEBUG_POINTER_ASSIGNMENT 0
24
Jeff Brown46b9ac02010-04-22 18:58:52 -070025#include <cutils/log.h>
26#include <ui/InputReader.h>
27
28#include <stddef.h>
29#include <unistd.h>
Jeff Brown46b9ac02010-04-22 18:58:52 -070030#include <errno.h>
31#include <limits.h>
Jeff Brownc5ed5912010-07-14 18:48:53 -070032#include <math.h>
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -070060int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
61 int32_t mask;
62 switch (keyCode) {
Jeff Brownfd035822010-06-30 16:10:35 -070063 case AKEYCODE_ALT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070064 mask = AMETA_ALT_LEFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070065 break;
Jeff Brownfd035822010-06-30 16:10:35 -070066 case AKEYCODE_ALT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070067 mask = AMETA_ALT_RIGHT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070068 break;
Jeff Brownfd035822010-06-30 16:10:35 -070069 case AKEYCODE_SHIFT_LEFT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070070 mask = AMETA_SHIFT_LEFT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070071 break;
Jeff Brownfd035822010-06-30 16:10:35 -070072 case AKEYCODE_SHIFT_RIGHT:
Jeff Brownc5ed5912010-07-14 18:48:53 -070073 mask = AMETA_SHIFT_RIGHT_ON;
Jeff Brown46b9ac02010-04-22 18:58:52 -070074 break;
Jeff Brownfd035822010-06-30 16:10:35 -070075 case AKEYCODE_SYM:
Jeff Brownc5ed5912010-07-14 18:48:53 -070076 mask = AMETA_SYM_ON;
Jeff Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brownfd035822010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-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 Brown46b9ac02010-04-22 18:58:52 -0700126 resetGlobalMetaState();
127 resetDisplayProperties();
Jeff Brown9c3cda02010-06-15 01:31:58 -0700128 updateExportedVirtualKeyState();
Jeff Brown46b9ac02010-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 Brownfd035822010-06-30 16:10:35 -0700257 if (device->isSingleTouchScreen()) {
Jeff Brown46b9ac02010-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 Brownfd035822010-06-30 16:10:35 -0700263 return;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700264 }
Jeff Brownfd035822010-06-30 16:10:35 -0700265 }
266
267 if (device->isTrackball()) {
Jeff Brown46b9ac02010-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 Brownfd035822010-06-30 16:10:35 -0700273 return;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700274 }
275 }
Jeff Brownfd035822010-06-30 16:10:35 -0700276
277 if (device->isKeyboard()) {
278 int32_t keyCode = rawEvent->keyCode;
279 onKey(rawEvent->when, device, down, keyCode, scanCode, rawEvent->flags);
280 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700281}
282
283void InputReader::handleRelativeMotion(const RawEvent* rawEvent) {
284 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
285 if (! device) return;
286
287 if (device->isTrackball()) {
288 switch (rawEvent->scanCode) {
289 case REL_X:
290 device->trackball.accumulator.fields |=
291 InputDevice::TrackballState::Accumulator::FIELD_REL_X;
292 device->trackball.accumulator.relX = rawEvent->value;
293 break;
294 case REL_Y:
295 device->trackball.accumulator.fields |=
296 InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
297 device->trackball.accumulator.relY = rawEvent->value;
298 break;
299 }
300 }
301}
302
303void InputReader::handleAbsoluteMotion(const RawEvent* rawEvent) {
304 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
305 if (! device) return;
306
307 if (device->isMultiTouchScreen()) {
308 uint32_t pointerIndex = device->multiTouchScreen.accumulator.pointerCount;
309 InputDevice::MultiTouchScreenState::Accumulator::Pointer* pointer =
310 & device->multiTouchScreen.accumulator.pointers[pointerIndex];
311
312 switch (rawEvent->scanCode) {
313 case ABS_MT_POSITION_X:
314 pointer->fields |=
315 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X;
316 pointer->absMTPositionX = rawEvent->value;
317 break;
318 case ABS_MT_POSITION_Y:
319 pointer->fields |=
320 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y;
321 pointer->absMTPositionY = rawEvent->value;
322 break;
323 case ABS_MT_TOUCH_MAJOR:
324 pointer->fields |=
325 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR;
326 pointer->absMTTouchMajor = rawEvent->value;
327 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700328 case ABS_MT_TOUCH_MINOR:
329 pointer->fields |=
330 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MINOR;
331 pointer->absMTTouchMinor = rawEvent->value;
332 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700333 case ABS_MT_WIDTH_MAJOR:
334 pointer->fields |=
335 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
336 pointer->absMTWidthMajor = rawEvent->value;
337 break;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700338 case ABS_MT_WIDTH_MINOR:
339 pointer->fields |=
340 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MINOR;
341 pointer->absMTWidthMinor = rawEvent->value;
342 break;
343 case ABS_MT_ORIENTATION:
344 pointer->fields |=
345 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_ORIENTATION;
346 pointer->absMTOrientation = rawEvent->value;
347 break;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700348 case ABS_MT_TRACKING_ID:
349 pointer->fields |=
350 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TRACKING_ID;
351 pointer->absMTTrackingId = rawEvent->value;
352 break;
353 }
354 } else if (device->isSingleTouchScreen()) {
355 switch (rawEvent->scanCode) {
356 case ABS_X:
357 device->singleTouchScreen.accumulator.fields |=
358 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X;
359 device->singleTouchScreen.accumulator.absX = rawEvent->value;
360 break;
361 case ABS_Y:
362 device->singleTouchScreen.accumulator.fields |=
363 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y;
364 device->singleTouchScreen.accumulator.absY = rawEvent->value;
365 break;
366 case ABS_PRESSURE:
367 device->singleTouchScreen.accumulator.fields |=
368 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE;
369 device->singleTouchScreen.accumulator.absPressure = rawEvent->value;
370 break;
371 case ABS_TOOL_WIDTH:
372 device->singleTouchScreen.accumulator.fields |=
373 InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH;
374 device->singleTouchScreen.accumulator.absToolWidth = rawEvent->value;
375 break;
376 }
377 }
378}
379
380void InputReader::handleSwitch(const RawEvent* rawEvent) {
381 InputDevice* device = getNonIgnoredDevice(rawEvent->deviceId);
382 if (! device) return;
383
Jeff Brown9c3cda02010-06-15 01:31:58 -0700384 onSwitch(rawEvent->when, device, rawEvent->scanCode, rawEvent->value);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700385}
386
387void InputReader::onKey(nsecs_t when, InputDevice* device,
388 bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) {
389 /* Refresh display properties so we can rotate key codes according to display orientation */
390
391 if (! refreshDisplayProperties()) {
392 return;
393 }
394
395 /* Update device state */
396
397 int32_t oldMetaState = device->keyboard.current.metaState;
398 int32_t newMetaState = updateMetaState(keyCode, down, oldMetaState);
399 if (oldMetaState != newMetaState) {
400 device->keyboard.current.metaState = newMetaState;
401 resetGlobalMetaState();
402 }
403
404 // FIXME if we send a down event about a rotated key press we should ensure that we send
405 // a corresponding up event about the rotated key press even if the orientation
406 // has changed in the meantime
407 keyCode = rotateKeyCode(keyCode, mDisplayOrientation);
408
409 if (down) {
410 device->keyboard.current.downTime = when;
411 }
412
413 /* Apply policy */
414
415 int32_t policyActions = mPolicy->interceptKey(when, device->id,
416 down, keyCode, scanCode, policyFlags);
417
418 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
419 return; // event dropped
420 }
421
422 /* Enqueue key event for dispatch */
423
424 int32_t keyEventAction;
425 if (down) {
426 device->keyboard.current.downTime = when;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700427 keyEventAction = AKEY_EVENT_ACTION_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700428 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700429 keyEventAction = AKEY_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700430 }
431
Jeff Brownc5ed5912010-07-14 18:48:53 -0700432 int32_t keyEventFlags = AKEY_EVENT_FLAG_FROM_SYSTEM;
Jeff Brown9c3cda02010-06-15 01:31:58 -0700433 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700434 keyEventFlags = keyEventFlags | AKEY_EVENT_FLAG_WOKE_HERE;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700435 }
436
Jeff Brownc5ed5912010-07-14 18:48:53 -0700437 mDispatcher->notifyKey(when, device->id, AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700438 keyEventAction, keyEventFlags, keyCode, scanCode,
439 device->keyboard.current.metaState,
440 device->keyboard.current.downTime);
441}
442
Jeff Brown9c3cda02010-06-15 01:31:58 -0700443void InputReader::onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode,
444 int32_t switchValue) {
445 int32_t policyActions = mPolicy->interceptSwitch(when, switchCode, switchValue);
446
447 uint32_t policyFlags = 0;
448 applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700449}
450
451void InputReader::onMultiTouchScreenStateChanged(nsecs_t when,
452 InputDevice* device) {
453 static const uint32_t REQUIRED_FIELDS =
454 InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_X
455 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_POSITION_Y
456 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MAJOR
457 | InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MAJOR;
458
459 /* Refresh display properties so we can map touch screen coords into display coords */
460
461 if (! refreshDisplayProperties()) {
462 return;
463 }
464
465 /* Update device state */
466
467 InputDevice::MultiTouchScreenState* in = & device->multiTouchScreen;
468 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
469
470 uint32_t inCount = in->accumulator.pointerCount;
471 uint32_t outCount = 0;
472 bool havePointerIds = true;
473
474 out->clear();
475
476 for (uint32_t inIndex = 0; inIndex < inCount; inIndex++) {
477 uint32_t fields = in->accumulator.pointers[inIndex].fields;
478
479 if ((fields & REQUIRED_FIELDS) != REQUIRED_FIELDS) {
480#if DEBUG_POINTERS
481 LOGD("Pointers: Missing required multitouch pointer fields: index=%d, fields=%d",
482 inIndex, fields);
483 continue;
484#endif
485 }
486
487 if (in->accumulator.pointers[inIndex].absMTTouchMajor <= 0) {
488 // Pointer is not down. Drop it.
489 continue;
490 }
491
Jeff Brownc5ed5912010-07-14 18:48:53 -0700492 out->pointers[outCount].x = in->accumulator.pointers[inIndex].absMTPositionX;
493 out->pointers[outCount].y = in->accumulator.pointers[inIndex].absMTPositionY;
494
495 out->pointers[outCount].touchMajor = in->accumulator.pointers[inIndex].absMTTouchMajor;
496 out->pointers[outCount].touchMinor = (fields
497 & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_TOUCH_MINOR) != 0
498 ? in->accumulator.pointers[inIndex].absMTTouchMinor
499 : in->accumulator.pointers[inIndex].absMTTouchMajor;
500
501 out->pointers[outCount].toolMajor = in->accumulator.pointers[inIndex].absMTWidthMajor;
502 out->pointers[outCount].toolMinor = (fields
503 & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_WIDTH_MINOR) != 0
504 ? in->accumulator.pointers[inIndex].absMTWidthMinor
505 : in->accumulator.pointers[inIndex].absMTWidthMajor;
506
507 out->pointers[outCount].orientation = (fields
508 & InputDevice::MultiTouchScreenState::Accumulator::FIELD_ABS_MT_ORIENTATION) != 0
509 ? in->accumulator.pointers[inIndex].absMTOrientation : 0;
510
511 // Derive an approximation of pressure and size.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700512 // FIXME assignment of pressure may be incorrect, probably better to let
513 // pressure = touch / width. Later on we pass width to MotionEvent as a size, which
514 // isn't quite right either. Should be using touch for that.
Jeff Brown46b9ac02010-04-22 18:58:52 -0700515 out->pointers[outCount].pressure = in->accumulator.pointers[inIndex].absMTTouchMajor;
516 out->pointers[outCount].size = in->accumulator.pointers[inIndex].absMTWidthMajor;
517
518 if (havePointerIds) {
519 if (fields & InputDevice::MultiTouchScreenState::Accumulator::
520 FIELD_ABS_MT_TRACKING_ID) {
521 uint32_t id = uint32_t(in->accumulator.pointers[inIndex].absMTTrackingId);
522
523 if (id > MAX_POINTER_ID) {
524#if DEBUG_POINTERS
525 LOGD("Pointers: Ignoring driver provided pointer id %d because "
526 "it is larger than max supported id %d for optimizations",
527 id, MAX_POINTER_ID);
528#endif
529 havePointerIds = false;
530 }
531 else {
532 out->pointers[outCount].id = id;
533 out->idToIndex[id] = outCount;
534 out->idBits.markBit(id);
535 }
536 } else {
537 havePointerIds = false;
538 }
539 }
540
541 outCount += 1;
542 }
543
544 out->pointerCount = outCount;
545
546 onTouchScreenChanged(when, device, havePointerIds);
547}
548
549void InputReader::onSingleTouchScreenStateChanged(nsecs_t when,
550 InputDevice* device) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700551 /* Refresh display properties so we can map touch screen coords into display coords */
552
553 if (! refreshDisplayProperties()) {
554 return;
555 }
556
557 /* Update device state */
558
559 InputDevice::SingleTouchScreenState* in = & device->singleTouchScreen;
560 InputDevice::TouchData* out = & device->touchScreen.currentTouch;
561
562 uint32_t fields = in->accumulator.fields;
563
564 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_BTN_TOUCH) {
565 in->current.down = in->accumulator.btnTouch;
566 }
567
Jeff Brown349703e2010-06-22 01:27:15 -0700568 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_X) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700569 in->current.x = in->accumulator.absX;
Jeff Brown349703e2010-06-22 01:27:15 -0700570 }
571
572 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_Y) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700573 in->current.y = in->accumulator.absY;
Jeff Brown349703e2010-06-22 01:27:15 -0700574 }
575
576 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_PRESSURE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700577 in->current.pressure = in->accumulator.absPressure;
Jeff Brown349703e2010-06-22 01:27:15 -0700578 }
579
580 if (fields & InputDevice::SingleTouchScreenState::Accumulator::FIELD_ABS_TOOL_WIDTH) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700581 in->current.size = in->accumulator.absToolWidth;
582 }
583
584 out->clear();
585
586 if (in->current.down) {
587 out->pointerCount = 1;
588 out->pointers[0].id = 0;
589 out->pointers[0].x = in->current.x;
590 out->pointers[0].y = in->current.y;
591 out->pointers[0].pressure = in->current.pressure;
592 out->pointers[0].size = in->current.size;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700593 out->pointers[0].touchMajor = in->current.pressure;
594 out->pointers[0].touchMinor = in->current.pressure;
595 out->pointers[0].toolMajor = in->current.size;
596 out->pointers[0].toolMinor = in->current.size;
597 out->pointers[0].orientation = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700598 out->idToIndex[0] = 0;
599 out->idBits.markBit(0);
600 }
601
602 onTouchScreenChanged(when, device, true);
603}
604
605void InputReader::onTouchScreenChanged(nsecs_t when,
606 InputDevice* device, bool havePointerIds) {
607 /* Apply policy */
608
609 int32_t policyActions = mPolicy->interceptTouch(when);
610
611 uint32_t policyFlags = 0;
612 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
613 device->touchScreen.lastTouch.clear();
614 return; // event dropped
615 }
616
617 /* Preprocess pointer data */
618
619 if (device->touchScreen.parameters.useBadTouchFilter) {
620 if (device->touchScreen.applyBadTouchFilter()) {
621 havePointerIds = false;
622 }
623 }
624
625 if (device->touchScreen.parameters.useJumpyTouchFilter) {
626 if (device->touchScreen.applyJumpyTouchFilter()) {
627 havePointerIds = false;
628 }
629 }
630
631 if (! havePointerIds) {
632 device->touchScreen.calculatePointerIds();
633 }
634
635 InputDevice::TouchData temp;
636 InputDevice::TouchData* savedTouch;
637 if (device->touchScreen.parameters.useAveragingTouchFilter) {
638 temp.copyFrom(device->touchScreen.currentTouch);
639 savedTouch = & temp;
640
641 device->touchScreen.applyAveragingTouchFilter();
642 } else {
643 savedTouch = & device->touchScreen.currentTouch;
644 }
645
646 /* Process virtual keys or touches */
647
648 if (! consumeVirtualKeyTouches(when, device, policyFlags)) {
649 dispatchTouches(when, device, policyFlags);
650 }
651
652 // Copy current touch to last touch in preparation for the next cycle.
653 device->touchScreen.lastTouch.copyFrom(*savedTouch);
654}
655
656bool InputReader::consumeVirtualKeyTouches(nsecs_t when,
657 InputDevice* device, uint32_t policyFlags) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700658 switch (device->touchScreen.currentVirtualKey.status) {
659 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED:
Jeff Brown46b9ac02010-04-22 18:58:52 -0700660 if (device->touchScreen.currentTouch.pointerCount == 0) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700661 // Pointer went up after virtual key canceled.
662 device->touchScreen.currentVirtualKey.status =
663 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
664 }
665 return true; // consumed
Jeff Brown46b9ac02010-04-22 18:58:52 -0700666
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700667 case InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN:
668 if (device->touchScreen.currentTouch.pointerCount == 0) {
669 // Pointer went up while virtual key was down.
670 device->touchScreen.currentVirtualKey.status =
671 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700672#if DEBUG_VIRTUAL_KEYS
673 LOGD("VirtualKeys: Generating key up: keyCode=%d, scanCode=%d",
674 device->touchScreen.currentVirtualKey.keyCode,
675 device->touchScreen.currentVirtualKey.scanCode);
676#endif
Jeff Brownc5ed5912010-07-14 18:48:53 -0700677 dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_UP,
678 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700679 return true; // consumed
680 }
681
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700682 if (device->touchScreen.currentTouch.pointerCount == 1) {
683 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
684 if (virtualKey
685 && virtualKey->keyCode == device->touchScreen.currentVirtualKey.keyCode) {
686 // Pointer is still within the space of the virtual key.
687 return true; // consumed
688 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700689 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700690
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700691 // Pointer left virtual key area or another pointer also went down.
692 // Send key cancellation.
693 device->touchScreen.currentVirtualKey.status =
694 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_CANCELED;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700695#if DEBUG_VIRTUAL_KEYS
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700696 LOGD("VirtualKeys: Canceling key: keyCode=%d, scanCode=%d",
697 device->touchScreen.currentVirtualKey.keyCode,
698 device->touchScreen.currentVirtualKey.scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700699#endif
Jeff Brownc5ed5912010-07-14 18:48:53 -0700700 dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_UP,
701 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY
702 | AKEY_EVENT_FLAG_CANCELED);
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700703 return true; // consumed
Jeff Brown46b9ac02010-04-22 18:58:52 -0700704
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700705 default:
706 if (device->touchScreen.currentTouch.pointerCount == 1
707 && device->touchScreen.lastTouch.pointerCount == 0) {
708 // Pointer just went down. Check for virtual key hit.
709 const InputDevice::VirtualKey* virtualKey = device->touchScreen.findVirtualKeyHit();
710 if (virtualKey) {
711 device->touchScreen.currentVirtualKey.status =
712 InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700713 device->touchScreen.currentVirtualKey.downTime = when;
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700714 device->touchScreen.currentVirtualKey.keyCode = virtualKey->keyCode;
715 device->touchScreen.currentVirtualKey.scanCode = virtualKey->scanCode;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700716#if DEBUG_VIRTUAL_KEYS
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700717 LOGD("VirtualKeys: Generating key down: keyCode=%d, scanCode=%d",
718 device->touchScreen.currentVirtualKey.keyCode,
719 device->touchScreen.currentVirtualKey.scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700720#endif
Jeff Brownc5ed5912010-07-14 18:48:53 -0700721 dispatchVirtualKey(when, device, policyFlags, AKEY_EVENT_ACTION_DOWN,
722 AKEY_EVENT_FLAG_FROM_SYSTEM | AKEY_EVENT_FLAG_VIRTUAL_HARD_KEY);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700723 return true; // consumed
724 }
725 }
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700726 return false; // not consumed
Jeff Brown46b9ac02010-04-22 18:58:52 -0700727 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700728}
729
730void InputReader::dispatchVirtualKey(nsecs_t when,
731 InputDevice* device, uint32_t policyFlags,
732 int32_t keyEventAction, int32_t keyEventFlags) {
Jeff Brown349703e2010-06-22 01:27:15 -0700733 updateExportedVirtualKeyState();
734
Jeff Brown46b9ac02010-04-22 18:58:52 -0700735 int32_t keyCode = device->touchScreen.currentVirtualKey.keyCode;
736 int32_t scanCode = device->touchScreen.currentVirtualKey.scanCode;
737 nsecs_t downTime = device->touchScreen.currentVirtualKey.downTime;
738 int32_t metaState = globalMetaState();
739
Jeff Brownc5ed5912010-07-14 18:48:53 -0700740 if (keyEventAction == AKEY_EVENT_ACTION_DOWN) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -0700741 mPolicy->virtualKeyDownFeedback();
742 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700743
Jeff Brown349703e2010-06-22 01:27:15 -0700744 int32_t policyActions = mPolicy->interceptKey(when, device->id,
Jeff Brownc5ed5912010-07-14 18:48:53 -0700745 keyEventAction == AKEY_EVENT_ACTION_DOWN, keyCode, scanCode, policyFlags);
Jeff Brown349703e2010-06-22 01:27:15 -0700746
747 if (applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700748 mDispatcher->notifyKey(when, device->id, AINPUT_SOURCE_KEYBOARD, policyFlags,
Jeff Brown349703e2010-06-22 01:27:15 -0700749 keyEventAction, keyEventFlags, keyCode, scanCode, metaState, downTime);
750 }
Jeff Brown46b9ac02010-04-22 18:58:52 -0700751}
752
753void InputReader::dispatchTouches(nsecs_t when,
754 InputDevice* device, uint32_t policyFlags) {
755 uint32_t currentPointerCount = device->touchScreen.currentTouch.pointerCount;
756 uint32_t lastPointerCount = device->touchScreen.lastTouch.pointerCount;
757 if (currentPointerCount == 0 && lastPointerCount == 0) {
758 return; // nothing to do!
759 }
760
761 BitSet32 currentIdBits = device->touchScreen.currentTouch.idBits;
762 BitSet32 lastIdBits = device->touchScreen.lastTouch.idBits;
763
764 if (currentIdBits == lastIdBits) {
765 // No pointer id changes so this is a move event.
766 // The dispatcher takes care of batching moves so we don't have to deal with that here.
Jeff Brownc5ed5912010-07-14 18:48:53 -0700767 int32_t motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700768 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
769 currentIdBits, motionEventAction);
770 } else {
771 // There may be pointers going up and pointers going down at the same time when pointer
772 // ids are reported by the device driver.
773 BitSet32 upIdBits(lastIdBits.value & ~ currentIdBits.value);
774 BitSet32 downIdBits(currentIdBits.value & ~ lastIdBits.value);
775 BitSet32 activeIdBits(lastIdBits.value);
776
777 while (! upIdBits.isEmpty()) {
778 uint32_t upId = upIdBits.firstMarkedBit();
779 upIdBits.clearBit(upId);
780 BitSet32 oldActiveIdBits = activeIdBits;
781 activeIdBits.clearBit(upId);
782
783 int32_t motionEventAction;
784 if (activeIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700785 motionEventAction = AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700786 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700787 motionEventAction = AMOTION_EVENT_ACTION_POINTER_UP
788 | (upId << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700789 }
790
791 dispatchTouch(when, device, policyFlags, & device->touchScreen.lastTouch,
792 oldActiveIdBits, motionEventAction);
793 }
794
795 while (! downIdBits.isEmpty()) {
796 uint32_t downId = downIdBits.firstMarkedBit();
797 downIdBits.clearBit(downId);
798 BitSet32 oldActiveIdBits = activeIdBits;
799 activeIdBits.markBit(downId);
800
801 int32_t motionEventAction;
802 if (oldActiveIdBits.isEmpty()) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700803 motionEventAction = AMOTION_EVENT_ACTION_DOWN;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700804 device->touchScreen.downTime = when;
805 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700806 motionEventAction = AMOTION_EVENT_ACTION_POINTER_DOWN
807 | (downId << AMOTION_EVENT_ACTION_POINTER_INDEX_SHIFT);
Jeff Brown46b9ac02010-04-22 18:58:52 -0700808 }
809
810 dispatchTouch(when, device, policyFlags, & device->touchScreen.currentTouch,
811 activeIdBits, motionEventAction);
812 }
813 }
814}
815
816void InputReader::dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
817 InputDevice::TouchData* touch, BitSet32 idBits,
818 int32_t motionEventAction) {
819 int32_t orientedWidth, orientedHeight;
820 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700821 case InputReaderPolicyInterface::ROTATION_90:
822 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac02010-04-22 18:58:52 -0700823 orientedWidth = mDisplayHeight;
824 orientedHeight = mDisplayWidth;
825 break;
826 default:
827 orientedWidth = mDisplayWidth;
828 orientedHeight = mDisplayHeight;
829 break;
830 }
831
832 uint32_t pointerCount = 0;
833 int32_t pointerIds[MAX_POINTERS];
834 PointerCoords pointerCoords[MAX_POINTERS];
835
Jeff Brown0b72e822010-06-29 16:52:21 -0700836 const InputDevice::TouchScreenState::Precalculated& precalculated =
837 device->touchScreen.precalculated;
838
Jeff Brown46b9ac02010-04-22 18:58:52 -0700839 // Walk through the the active pointers and map touch screen coordinates (TouchData) into
840 // display coordinates (PointerCoords) and adjust for display orientation.
841 while (! idBits.isEmpty()) {
842 uint32_t id = idBits.firstMarkedBit();
843 idBits.clearBit(id);
844 uint32_t index = touch->idToIndex[id];
845
Jeff Brown0b72e822010-06-29 16:52:21 -0700846 float x = float(touch->pointers[index].x
847 - precalculated.xOrigin) * precalculated.xScale;
848 float y = float(touch->pointers[index].y
849 - precalculated.yOrigin) * precalculated.yScale;
850 float pressure = float(touch->pointers[index].pressure
851 - precalculated.pressureOrigin) * precalculated.pressureScale;
852 float size = float(touch->pointers[index].size
853 - precalculated.sizeOrigin) * precalculated.sizeScale;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700854
Jeff Brownc5ed5912010-07-14 18:48:53 -0700855 float orientation = float(touch->pointers[index].orientation)
856 * precalculated.orientationScale;
857
858 bool vertical = abs(orientation) <= M_PI / 8;
859
Jeff Brown46b9ac02010-04-22 18:58:52 -0700860 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -0700861 case InputReaderPolicyInterface::ROTATION_90: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700862 float xTemp = x;
863 x = y;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700864 y = mDisplayWidth - xTemp;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700865 vertical = ! vertical;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700866 break;
867 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700868 case InputReaderPolicyInterface::ROTATION_180: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700869 x = mDisplayWidth - x;
870 y = mDisplayHeight - y;
871 break;
872 }
Jeff Brown9c3cda02010-06-15 01:31:58 -0700873 case InputReaderPolicyInterface::ROTATION_270: {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700874 float xTemp = x;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700875 x = mDisplayHeight - y;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700876 y = xTemp;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700877 vertical = ! vertical;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700878 break;
879 }
880 }
881
Jeff Brownc5ed5912010-07-14 18:48:53 -0700882 float touchMajor, touchMinor, toolMajor, toolMinor;
883 if (vertical) {
884 touchMajor = float(touch->pointers[index].touchMajor) * precalculated.yScale;
885 touchMinor = float(touch->pointers[index].touchMinor) * precalculated.xScale;
886 toolMajor = float(touch->pointers[index].toolMajor) * precalculated.yScale;
887 toolMinor = float(touch->pointers[index].toolMinor) * precalculated.xScale;
888 } else {
889 touchMajor = float(touch->pointers[index].touchMajor) * precalculated.xScale;
890 touchMinor = float(touch->pointers[index].touchMinor) * precalculated.yScale;
891 toolMajor = float(touch->pointers[index].toolMajor) * precalculated.xScale;
892 toolMinor = float(touch->pointers[index].toolMinor) * precalculated.yScale;
893 }
894
Jeff Brown46b9ac02010-04-22 18:58:52 -0700895 pointerIds[pointerCount] = int32_t(id);
896
897 pointerCoords[pointerCount].x = x;
898 pointerCoords[pointerCount].y = y;
899 pointerCoords[pointerCount].pressure = pressure;
900 pointerCoords[pointerCount].size = size;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700901 pointerCoords[pointerCount].touchMajor = touchMajor;
902 pointerCoords[pointerCount].touchMinor = touchMinor;
903 pointerCoords[pointerCount].toolMajor = toolMajor;
904 pointerCoords[pointerCount].toolMinor = toolMinor;
905 pointerCoords[pointerCount].orientation = orientation;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700906
907 pointerCount += 1;
908 }
909
910 // Check edge flags by looking only at the first pointer since the flags are
911 // global to the event.
912 // XXX Maybe we should revise the edge flags API to work on a per-pointer basis.
913 int32_t motionEventEdgeFlags = 0;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700914 if (motionEventAction == AMOTION_EVENT_ACTION_DOWN) {
Jeff Brown46b9ac02010-04-22 18:58:52 -0700915 if (pointerCoords[0].x <= 0) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700916 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_LEFT;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700917 } else if (pointerCoords[0].x >= orientedWidth) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700918 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_RIGHT;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700919 }
920 if (pointerCoords[0].y <= 0) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700921 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_TOP;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700922 } else if (pointerCoords[0].y >= orientedHeight) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700923 motionEventEdgeFlags |= AMOTION_EVENT_EDGE_FLAG_BOTTOM;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700924 }
925 }
926
927 nsecs_t downTime = device->touchScreen.downTime;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700928 mDispatcher->notifyMotion(when, device->id, AINPUT_SOURCE_TOUCHSCREEN, policyFlags,
Jeff Brown46b9ac02010-04-22 18:58:52 -0700929 motionEventAction, globalMetaState(), motionEventEdgeFlags,
930 pointerCount, pointerIds, pointerCoords,
931 0, 0, downTime);
932}
933
934void InputReader::onTrackballStateChanged(nsecs_t when,
935 InputDevice* device) {
936 static const uint32_t DELTA_FIELDS =
937 InputDevice::TrackballState::Accumulator::FIELD_REL_X
938 | InputDevice::TrackballState::Accumulator::FIELD_REL_Y;
939
940 /* Refresh display properties so we can trackball moves according to display orientation */
941
942 if (! refreshDisplayProperties()) {
943 return;
944 }
945
946 /* Update device state */
947
948 uint32_t fields = device->trackball.accumulator.fields;
949 bool downChanged = fields & InputDevice::TrackballState::Accumulator::FIELD_BTN_MOUSE;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700950 bool deltaChanged = fields & DELTA_FIELDS;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700951
952 bool down;
953 if (downChanged) {
954 if (device->trackball.accumulator.btnMouse) {
955 device->trackball.current.down = true;
956 device->trackball.current.downTime = when;
957 down = true;
958 } else {
959 device->trackball.current.down = false;
960 down = false;
961 }
962 } else {
963 down = device->trackball.current.down;
964 }
965
966 /* Apply policy */
967
968 int32_t policyActions = mPolicy->interceptTrackball(when, downChanged, down, deltaChanged);
969
970 uint32_t policyFlags = 0;
971 if (! applyStandardInputDispatchPolicyActions(when, policyActions, & policyFlags)) {
972 return; // event dropped
973 }
974
975 /* Enqueue motion event for dispatch */
976
977 int32_t motionEventAction;
978 if (downChanged) {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700979 motionEventAction = down ? AMOTION_EVENT_ACTION_DOWN : AMOTION_EVENT_ACTION_UP;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700980 } else {
Jeff Brownc5ed5912010-07-14 18:48:53 -0700981 motionEventAction = AMOTION_EVENT_ACTION_MOVE;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700982 }
983
984 int32_t pointerId = 0;
985 PointerCoords pointerCoords;
Jeff Brown7fbdc842010-06-17 20:52:56 -0700986 pointerCoords.x = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_X
987 ? device->trackball.accumulator.relX * device->trackball.precalculated.xScale : 0;
988 pointerCoords.y = fields & InputDevice::TrackballState::Accumulator::FIELD_REL_Y
989 ? device->trackball.accumulator.relY * device->trackball.precalculated.yScale : 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700990 pointerCoords.pressure = 1.0f; // XXX Consider making this 1.0f if down, 0 otherwise.
991 pointerCoords.size = 0;
Jeff Brownc5ed5912010-07-14 18:48:53 -0700992 pointerCoords.touchMajor = 0;
993 pointerCoords.touchMinor = 0;
994 pointerCoords.toolMajor = 0;
995 pointerCoords.toolMinor = 0;
996 pointerCoords.orientation = 0;
Jeff Brown46b9ac02010-04-22 18:58:52 -0700997
998 float temp;
999 switch (mDisplayOrientation) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001000 case InputReaderPolicyInterface::ROTATION_90:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001001 temp = pointerCoords.x;
1002 pointerCoords.x = pointerCoords.y;
1003 pointerCoords.y = - temp;
1004 break;
1005
Jeff Brown9c3cda02010-06-15 01:31:58 -07001006 case InputReaderPolicyInterface::ROTATION_180:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001007 pointerCoords.x = - pointerCoords.x;
1008 pointerCoords.y = - pointerCoords.y;
1009 break;
1010
Jeff Brown9c3cda02010-06-15 01:31:58 -07001011 case InputReaderPolicyInterface::ROTATION_270:
Jeff Brown46b9ac02010-04-22 18:58:52 -07001012 temp = pointerCoords.x;
1013 pointerCoords.x = - pointerCoords.y;
1014 pointerCoords.y = temp;
1015 break;
1016 }
1017
Jeff Brownc5ed5912010-07-14 18:48:53 -07001018 mDispatcher->notifyMotion(when, device->id, AINPUT_SOURCE_TRACKBALL, policyFlags,
1019 motionEventAction, globalMetaState(), AMOTION_EVENT_EDGE_FLAG_NONE,
Jeff Brown46b9ac02010-04-22 18:58:52 -07001020 1, & pointerId, & pointerCoords,
1021 device->trackball.precalculated.xPrecision,
1022 device->trackball.precalculated.yPrecision,
1023 device->trackball.current.downTime);
1024}
1025
1026void InputReader::onConfigurationChanged(nsecs_t when) {
1027 // Reset global meta state because it depends on the list of all configured devices.
1028 resetGlobalMetaState();
1029
1030 // Reset virtual keys, just in case.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001031 updateExportedVirtualKeyState();
1032
1033 // Update input configuration.
1034 updateExportedInputConfiguration();
Jeff Brown46b9ac02010-04-22 18:58:52 -07001035
1036 // Enqueue configuration changed.
Jeff Brown9c3cda02010-06-15 01:31:58 -07001037 mDispatcher->notifyConfigurationChanged(when);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001038}
1039
1040bool InputReader::applyStandardInputDispatchPolicyActions(nsecs_t when,
1041 int32_t policyActions, uint32_t* policyFlags) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001042 if (policyActions & InputReaderPolicyInterface::ACTION_APP_SWITCH_COMING) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001043 mDispatcher->notifyAppSwitchComing(when);
1044 }
1045
Jeff Brown9c3cda02010-06-15 01:31:58 -07001046 if (policyActions & InputReaderPolicyInterface::ACTION_WOKE_HERE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001047 *policyFlags |= POLICY_FLAG_WOKE_HERE;
1048 }
1049
Jeff Brown9c3cda02010-06-15 01:31:58 -07001050 if (policyActions & InputReaderPolicyInterface::ACTION_BRIGHT_HERE) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001051 *policyFlags |= POLICY_FLAG_BRIGHT_HERE;
1052 }
1053
Jeff Brown9c3cda02010-06-15 01:31:58 -07001054 return policyActions & InputReaderPolicyInterface::ACTION_DISPATCH;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001055}
1056
1057void InputReader::resetDisplayProperties() {
1058 mDisplayWidth = mDisplayHeight = -1;
1059 mDisplayOrientation = -1;
1060}
1061
1062bool InputReader::refreshDisplayProperties() {
1063 int32_t newWidth, newHeight, newOrientation;
1064 if (mPolicy->getDisplayInfo(0, & newWidth, & newHeight, & newOrientation)) {
1065 if (newWidth != mDisplayWidth || newHeight != mDisplayHeight) {
1066 LOGD("Display size changed from %dx%d to %dx%d, updating device configuration",
1067 mDisplayWidth, mDisplayHeight, newWidth, newHeight);
1068
1069 mDisplayWidth = newWidth;
1070 mDisplayHeight = newHeight;
1071
1072 for (size_t i = 0; i < mDevices.size(); i++) {
1073 configureDeviceForCurrentDisplaySize(mDevices.valueAt(i));
1074 }
1075 }
1076
Jeff Brown0b72e822010-06-29 16:52:21 -07001077 if (newOrientation != mDisplayOrientation) {
1078 LOGD("Display orientation changed to %d", mDisplayOrientation);
1079
1080 mDisplayOrientation = newOrientation;
1081 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001082 return true;
1083 } else {
1084 resetDisplayProperties();
1085 return false;
1086 }
1087}
1088
1089InputDevice* InputReader::getDevice(int32_t deviceId) {
1090 ssize_t index = mDevices.indexOfKey(deviceId);
1091 return index >= 0 ? mDevices.valueAt((size_t) index) : NULL;
1092}
1093
1094InputDevice* InputReader::getNonIgnoredDevice(int32_t deviceId) {
1095 InputDevice* device = getDevice(deviceId);
1096 return device && ! device->ignored ? device : NULL;
1097}
1098
1099void InputReader::addDevice(nsecs_t when, int32_t deviceId) {
1100 uint32_t classes = mEventHub->getDeviceClasses(deviceId);
1101 String8 name = mEventHub->getDeviceName(deviceId);
1102 InputDevice* device = new InputDevice(deviceId, classes, name);
1103
1104 if (classes != 0) {
1105 LOGI("Device added: id=0x%x, name=%s, classes=%02x", device->id,
1106 device->name.string(), device->classes);
1107
1108 configureDevice(device);
1109 } else {
1110 LOGI("Device added: id=0x%x, name=%s (ignored non-input device)", device->id,
1111 device->name.string());
1112
1113 device->ignored = true;
1114 }
1115
1116 device->reset();
1117
1118 mDevices.add(deviceId, device);
1119
1120 if (! device->ignored) {
1121 onConfigurationChanged(when);
1122 }
1123}
1124
1125void InputReader::removeDevice(nsecs_t when, InputDevice* device) {
1126 mDevices.removeItem(device->id);
1127
1128 if (! device->ignored) {
1129 LOGI("Device removed: id=0x%x, name=%s, classes=%02x", device->id,
1130 device->name.string(), device->classes);
1131
1132 onConfigurationChanged(when);
1133 } else {
1134 LOGI("Device removed: id=0x%x, name=%s (ignored non-input device)", device->id,
1135 device->name.string());
1136 }
1137
1138 delete device;
1139}
1140
1141void InputReader::configureDevice(InputDevice* device) {
1142 if (device->isMultiTouchScreen()) {
1143 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_X, "X",
1144 & device->touchScreen.parameters.xAxis);
1145 configureAbsoluteAxisInfo(device, ABS_MT_POSITION_Y, "Y",
1146 & device->touchScreen.parameters.yAxis);
1147 configureAbsoluteAxisInfo(device, ABS_MT_TOUCH_MAJOR, "Pressure",
1148 & device->touchScreen.parameters.pressureAxis);
1149 configureAbsoluteAxisInfo(device, ABS_MT_WIDTH_MAJOR, "Size",
1150 & device->touchScreen.parameters.sizeAxis);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001151 configureAbsoluteAxisInfo(device, ABS_MT_ORIENTATION, "Orientation",
1152 & device->touchScreen.parameters.orientationAxis);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001153 } else if (device->isSingleTouchScreen()) {
1154 configureAbsoluteAxisInfo(device, ABS_X, "X",
1155 & device->touchScreen.parameters.xAxis);
1156 configureAbsoluteAxisInfo(device, ABS_Y, "Y",
1157 & device->touchScreen.parameters.yAxis);
1158 configureAbsoluteAxisInfo(device, ABS_PRESSURE, "Pressure",
1159 & device->touchScreen.parameters.pressureAxis);
1160 configureAbsoluteAxisInfo(device, ABS_TOOL_WIDTH, "Size",
1161 & device->touchScreen.parameters.sizeAxis);
Jeff Brownc5ed5912010-07-14 18:48:53 -07001162 device->touchScreen.parameters.orientationAxis.valid = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001163 }
1164
1165 if (device->isTouchScreen()) {
1166 device->touchScreen.parameters.useBadTouchFilter =
1167 mPolicy->filterTouchEvents();
1168 device->touchScreen.parameters.useAveragingTouchFilter =
1169 mPolicy->filterTouchEvents();
1170 device->touchScreen.parameters.useJumpyTouchFilter =
1171 mPolicy->filterJumpyTouchEvents();
1172
Jeff Brown0b72e822010-06-29 16:52:21 -07001173 if (device->touchScreen.parameters.pressureAxis.valid) {
1174 device->touchScreen.precalculated.pressureOrigin =
1175 device->touchScreen.parameters.pressureAxis.minValue;
1176 device->touchScreen.precalculated.pressureScale =
1177 1.0f / device->touchScreen.parameters.pressureAxis.range;
1178 } else {
1179 device->touchScreen.precalculated.pressureOrigin = 0;
1180 device->touchScreen.precalculated.pressureScale = 1.0f;
1181 }
1182
1183 if (device->touchScreen.parameters.sizeAxis.valid) {
1184 device->touchScreen.precalculated.sizeOrigin =
1185 device->touchScreen.parameters.sizeAxis.minValue;
1186 device->touchScreen.precalculated.sizeScale =
1187 1.0f / device->touchScreen.parameters.sizeAxis.range;
1188 } else {
1189 device->touchScreen.precalculated.sizeOrigin = 0;
1190 device->touchScreen.precalculated.sizeScale = 1.0f;
1191 }
Jeff Brownc5ed5912010-07-14 18:48:53 -07001192
1193 if (device->touchScreen.parameters.orientationAxis.valid
1194 && device->touchScreen.parameters.orientationAxis.maxValue > 0) {
1195 device->touchScreen.precalculated.orientationScale =
1196 M_PI_4 / device->touchScreen.parameters.orientationAxis.maxValue;
1197 } else {
1198 device->touchScreen.precalculated.orientationScale = 0.0f;
1199 }
Jeff Brown46b9ac02010-04-22 18:58:52 -07001200 }
1201
1202 if (device->isTrackball()) {
1203 device->trackball.precalculated.xPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1204 device->trackball.precalculated.yPrecision = TRACKBALL_MOVEMENT_THRESHOLD;
1205 device->trackball.precalculated.xScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1206 device->trackball.precalculated.yScale = 1.0f / TRACKBALL_MOVEMENT_THRESHOLD;
1207 }
1208
1209 configureDeviceForCurrentDisplaySize(device);
1210}
1211
1212void InputReader::configureDeviceForCurrentDisplaySize(InputDevice* device) {
1213 if (device->isTouchScreen()) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001214 if (device->touchScreen.parameters.xAxis.valid
1215 && device->touchScreen.parameters.yAxis.valid) {
1216 device->touchScreen.precalculated.xOrigin =
1217 device->touchScreen.parameters.xAxis.minValue;
1218 device->touchScreen.precalculated.yOrigin =
1219 device->touchScreen.parameters.yAxis.minValue;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001220
Jeff Brown0b72e822010-06-29 16:52:21 -07001221 if (mDisplayWidth < 0) {
1222 LOGD("Skipping part of touch screen configuration since display size is unknown.");
1223
1224 device->touchScreen.precalculated.xScale = 1.0f;
1225 device->touchScreen.precalculated.yScale = 1.0f;
1226 } else {
1227 LOGI("Device configured: id=0x%x, name=%s (display size was changed)", device->id,
1228 device->name.string());
1229
1230 device->touchScreen.precalculated.xScale =
1231 float(mDisplayWidth) / device->touchScreen.parameters.xAxis.range;
1232 device->touchScreen.precalculated.yScale =
1233 float(mDisplayHeight) / device->touchScreen.parameters.yAxis.range;
1234
1235 configureVirtualKeys(device);
1236 }
1237 } else {
1238 device->touchScreen.precalculated.xOrigin = 0;
1239 device->touchScreen.precalculated.xScale = 1.0f;
1240 device->touchScreen.precalculated.yOrigin = 0;
1241 device->touchScreen.precalculated.yScale = 1.0f;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001242 }
1243 }
1244}
1245
1246void InputReader::configureVirtualKeys(InputDevice* device) {
Jeff Brown0b72e822010-06-29 16:52:21 -07001247 assert(device->touchScreen.parameters.xAxis.valid
1248 && device->touchScreen.parameters.yAxis.valid);
1249
Jeff Brown46b9ac02010-04-22 18:58:52 -07001250 device->touchScreen.virtualKeys.clear();
1251
Jeff Brown9c3cda02010-06-15 01:31:58 -07001252 Vector<InputReaderPolicyInterface::VirtualKeyDefinition> virtualKeyDefinitions;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001253 mPolicy->getVirtualKeyDefinitions(device->name, virtualKeyDefinitions);
1254 if (virtualKeyDefinitions.size() == 0) {
1255 return;
1256 }
1257
1258 device->touchScreen.virtualKeys.setCapacity(virtualKeyDefinitions.size());
1259
1260 int32_t touchScreenLeft = device->touchScreen.parameters.xAxis.minValue;
1261 int32_t touchScreenTop = device->touchScreen.parameters.yAxis.minValue;
1262 int32_t touchScreenWidth = device->touchScreen.parameters.xAxis.range;
1263 int32_t touchScreenHeight = device->touchScreen.parameters.yAxis.range;
1264
1265 for (size_t i = 0; i < virtualKeyDefinitions.size(); i++) {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001266 const InputReaderPolicyInterface::VirtualKeyDefinition& virtualKeyDefinition =
Jeff Brown46b9ac02010-04-22 18:58:52 -07001267 virtualKeyDefinitions[i];
1268
1269 device->touchScreen.virtualKeys.add();
1270 InputDevice::VirtualKey& virtualKey =
1271 device->touchScreen.virtualKeys.editTop();
1272
1273 virtualKey.scanCode = virtualKeyDefinition.scanCode;
1274 int32_t keyCode;
1275 uint32_t flags;
1276 if (mEventHub->scancodeToKeycode(device->id, virtualKey.scanCode,
1277 & keyCode, & flags)) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001278 LOGW(" VirtualKey %d: could not obtain key code, ignoring", virtualKey.scanCode);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001279 device->touchScreen.virtualKeys.pop(); // drop the key
1280 continue;
1281 }
1282
1283 virtualKey.keyCode = keyCode;
1284 virtualKey.flags = flags;
1285
1286 // convert the key definition's display coordinates into touch coordinates for a hit box
1287 int32_t halfWidth = virtualKeyDefinition.width / 2;
1288 int32_t halfHeight = virtualKeyDefinition.height / 2;
1289
1290 virtualKey.hitLeft = (virtualKeyDefinition.centerX - halfWidth)
1291 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1292 virtualKey.hitRight= (virtualKeyDefinition.centerX + halfWidth)
1293 * touchScreenWidth / mDisplayWidth + touchScreenLeft;
1294 virtualKey.hitTop = (virtualKeyDefinition.centerY - halfHeight)
1295 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1296 virtualKey.hitBottom = (virtualKeyDefinition.centerY + halfHeight)
1297 * touchScreenHeight / mDisplayHeight + touchScreenTop;
1298
1299 LOGI(" VirtualKey %d: keyCode=%d hitLeft=%d hitRight=%d hitTop=%d hitBottom=%d",
1300 virtualKey.scanCode, virtualKey.keyCode,
1301 virtualKey.hitLeft, virtualKey.hitRight, virtualKey.hitTop, virtualKey.hitBottom);
1302 }
1303}
1304
1305void InputReader::configureAbsoluteAxisInfo(InputDevice* device,
1306 int axis, const char* name, InputDevice::AbsoluteAxisInfo* out) {
1307 if (! mEventHub->getAbsoluteInfo(device->id, axis,
1308 & out->minValue, & out->maxValue, & out->flat, &out->fuzz)) {
1309 out->range = out->maxValue - out->minValue;
1310 if (out->range != 0) {
1311 LOGI(" %s: min=%d max=%d flat=%d fuzz=%d",
1312 name, out->minValue, out->maxValue, out->flat, out->fuzz);
Jeff Brown0b72e822010-06-29 16:52:21 -07001313 out->valid = true;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001314 return;
1315 }
1316 }
1317
Jeff Brown0b72e822010-06-29 16:52:21 -07001318 out->valid = false;
Jeff Brown46b9ac02010-04-22 18:58:52 -07001319 out->minValue = 0;
1320 out->maxValue = 0;
1321 out->flat = 0;
1322 out->fuzz = 0;
1323 out->range = 0;
Jeff Brown0b72e822010-06-29 16:52:21 -07001324 LOGI(" %s: unknown axis values, marking as invalid", name);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001325}
1326
Jeff Brown9c3cda02010-06-15 01:31:58 -07001327void InputReader::configureExcludedDevices() {
1328 Vector<String8> excludedDeviceNames;
1329 mPolicy->getExcludedDeviceNames(excludedDeviceNames);
1330
1331 for (size_t i = 0; i < excludedDeviceNames.size(); i++) {
1332 mEventHub->addExcludedDevice(excludedDeviceNames[i]);
1333 }
1334}
1335
Jeff Brown46b9ac02010-04-22 18:58:52 -07001336void InputReader::resetGlobalMetaState() {
1337 mGlobalMetaState = -1;
1338}
1339
1340int32_t InputReader::globalMetaState() {
1341 if (mGlobalMetaState == -1) {
1342 mGlobalMetaState = 0;
1343 for (size_t i = 0; i < mDevices.size(); i++) {
1344 InputDevice* device = mDevices.valueAt(i);
1345 if (device->isKeyboard()) {
1346 mGlobalMetaState |= device->keyboard.current.metaState;
1347 }
1348 }
1349 }
1350 return mGlobalMetaState;
1351}
1352
Jeff Brown9c3cda02010-06-15 01:31:58 -07001353void InputReader::updateExportedVirtualKeyState() {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001354 int32_t keyCode = -1, scanCode = -1;
1355
1356 for (size_t i = 0; i < mDevices.size(); i++) {
1357 InputDevice* device = mDevices.valueAt(i);
1358 if (device->isTouchScreen()) {
Jeff Brown00fa7bd2010-07-02 15:37:36 -07001359 if (device->touchScreen.currentVirtualKey.status
1360 == InputDevice::TouchScreenState::CurrentVirtualKeyState::STATUS_DOWN) {
Jeff Brown46b9ac02010-04-22 18:58:52 -07001361 keyCode = device->touchScreen.currentVirtualKey.keyCode;
1362 scanCode = device->touchScreen.currentVirtualKey.scanCode;
1363 }
1364 }
1365 }
1366
Jeff Brown9c3cda02010-06-15 01:31:58 -07001367 { // acquire exported state lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07001368 AutoMutex _l(mExportedStateLock);
1369
Jeff Brown9c3cda02010-06-15 01:31:58 -07001370 mExportedVirtualKeyCode = keyCode;
1371 mExportedVirtualScanCode = scanCode;
1372 } // release exported state lock
Jeff Brown46b9ac02010-04-22 18:58:52 -07001373}
1374
1375bool InputReader::getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const {
Jeff Brown9c3cda02010-06-15 01:31:58 -07001376 { // acquire exported state lock
1377 AutoMutex _l(mExportedStateLock);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001378
Jeff Brown9c3cda02010-06-15 01:31:58 -07001379 *outKeyCode = mExportedVirtualKeyCode;
1380 *outScanCode = mExportedVirtualScanCode;
1381 return mExportedVirtualKeyCode != -1;
1382 } // release exported state lock
1383}
1384
1385void InputReader::updateExportedInputConfiguration() {
1386 int32_t touchScreenConfig = InputConfiguration::TOUCHSCREEN_NOTOUCH;
1387 int32_t keyboardConfig = InputConfiguration::KEYBOARD_NOKEYS;
1388 int32_t navigationConfig = InputConfiguration::NAVIGATION_NONAV;
1389
1390 for (size_t i = 0; i < mDevices.size(); i++) {
1391 InputDevice* device = mDevices.valueAt(i);
1392 int32_t deviceClasses = device->classes;
1393
1394 if (deviceClasses & INPUT_DEVICE_CLASS_TOUCHSCREEN) {
1395 touchScreenConfig = InputConfiguration::TOUCHSCREEN_FINGER;
1396 }
1397 if (deviceClasses & INPUT_DEVICE_CLASS_ALPHAKEY) {
1398 keyboardConfig = InputConfiguration::KEYBOARD_QWERTY;
1399 }
1400 if (deviceClasses & INPUT_DEVICE_CLASS_TRACKBALL) {
1401 navigationConfig = InputConfiguration::NAVIGATION_TRACKBALL;
1402 } else if (deviceClasses & INPUT_DEVICE_CLASS_DPAD) {
1403 navigationConfig = InputConfiguration::NAVIGATION_DPAD;
1404 }
1405 }
1406
1407 { // acquire exported state lock
1408 AutoMutex _l(mExportedStateLock);
1409
1410 mExportedInputConfiguration.touchScreen = touchScreenConfig;
1411 mExportedInputConfiguration.keyboard = keyboardConfig;
1412 mExportedInputConfiguration.navigation = navigationConfig;
1413 } // release exported state lock
1414}
1415
1416void InputReader::getCurrentInputConfiguration(InputConfiguration* outConfiguration) const {
1417 { // acquire exported state lock
1418 AutoMutex _l(mExportedStateLock);
1419
1420 *outConfiguration = mExportedInputConfiguration;
1421 } // release exported state lock
1422}
1423
1424int32_t InputReader::getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
1425 int32_t scanCode) const {
1426 { // acquire exported state lock
1427 AutoMutex _l(mExportedStateLock);
1428
1429 if (mExportedVirtualScanCode == scanCode) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001430 return AKEY_STATE_VIRTUAL;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001431 }
1432 } // release exported state lock
1433
1434 return mEventHub->getScanCodeState(deviceId, deviceClasses, scanCode);
1435}
1436
1437int32_t InputReader::getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
1438 int32_t keyCode) const {
1439 { // acquire exported state lock
1440 AutoMutex _l(mExportedStateLock);
1441
1442 if (mExportedVirtualKeyCode == keyCode) {
Jeff Brownc5ed5912010-07-14 18:48:53 -07001443 return AKEY_STATE_VIRTUAL;
Jeff Brown9c3cda02010-06-15 01:31:58 -07001444 }
1445 } // release exported state lock
1446
1447 return mEventHub->getKeyCodeState(deviceId, deviceClasses, keyCode);
1448}
1449
1450int32_t InputReader::getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
1451 int32_t sw) const {
1452 return mEventHub->getSwitchState(deviceId, deviceClasses, sw);
1453}
1454
1455bool InputReader::hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const {
1456 return mEventHub->hasKeys(numCodes, keyCodes, outFlags);
Jeff Brown46b9ac02010-04-22 18:58:52 -07001457}
1458
1459
1460// --- InputReaderThread ---
1461
1462InputReaderThread::InputReaderThread(const sp<InputReaderInterface>& reader) :
1463 Thread(/*canCallJava*/ true), mReader(reader) {
1464}
1465
1466InputReaderThread::~InputReaderThread() {
1467}
1468
1469bool InputReaderThread::threadLoop() {
1470 mReader->loopOnce();
1471 return true;
1472}
1473
1474} // namespace android