blob: 7e7a64c70e58147eae8b1e4645c926841327b57a [file] [log] [blame]
Jeff Browne839a582010-04-22 18:58:52 -07001/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#ifndef _UI_INPUT_READER_H
18#define _UI_INPUT_READER_H
19
20#include <ui/EventHub.h>
21#include <ui/Input.h>
22#include <ui/InputDispatchPolicy.h>
23#include <ui/InputDispatcher.h>
24#include <utils/KeyedVector.h>
25#include <utils/threads.h>
26#include <utils/Timers.h>
27#include <utils/RefBase.h>
28#include <utils/String8.h>
29#include <utils/BitSet.h>
30
31#include <stddef.h>
32#include <unistd.h>
33
34/* Maximum pointer id value supported.
35 * (This is limited by our use of BitSet32 to track pointer assignments.) */
36#define MAX_POINTER_ID 32
37
38/** Amount that trackball needs to move in order to generate a key event. */
39#define TRACKBALL_MOVEMENT_THRESHOLD 6
40
41/* Slop distance for jumpy pointer detection.
42 * The vertical range of the screen divided by this is our epsilon value. */
43#define JUMPY_EPSILON_DIVISOR 212
44
45/* Number of jumpy points to drop for touchscreens that need it. */
46#define JUMPY_TRANSITION_DROPS 3
47#define JUMPY_DROP_LIMIT 3
48
49/* Maximum squared distance for averaging.
50 * If moving farther than this, turn of averaging to avoid lag in response. */
51#define AVERAGING_DISTANCE_LIMIT (75 * 75)
52
53/* Maximum number of historical samples to average. */
54#define AVERAGING_HISTORY_SIZE 5
55
56
57namespace android {
58
59extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
60extern int32_t rotateKeyCode(int32_t keyCode, int32_t orientation);
61
62/*
63 * An input device structure tracks the state of a single input device.
64 *
65 * This structure is only used by ReaderThread and is not intended to be shared with
66 * DispatcherThread (because that would require locking). This works out fine because
67 * DispatcherThread is only interested in cooked event data anyways and does not need
68 * any of the low-level data from InputDevice.
69 */
70struct InputDevice {
71 struct AbsoluteAxisInfo {
72 int32_t minValue; // minimum value
73 int32_t maxValue; // maximum value
74 int32_t range; // range of values, equal to maxValue - minValue
75 int32_t flat; // center flat position, eg. flat == 8 means center is between -8 and 8
76 int32_t fuzz; // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
77 };
78
79 struct VirtualKey {
80 int32_t keyCode;
81 int32_t scanCode;
82 uint32_t flags;
83
84 // computed hit box, specified in touch screen coords based on known display size
85 int32_t hitLeft;
86 int32_t hitTop;
87 int32_t hitRight;
88 int32_t hitBottom;
89
90 inline bool isHit(int32_t x, int32_t y) const {
91 return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
92 }
93 };
94
95 struct KeyboardState {
96 struct Current {
97 int32_t metaState;
98 nsecs_t downTime; // time of most recent key down
99 } current;
100
101 void reset();
102 };
103
104 struct TrackballState {
105 struct Accumulator {
106 enum {
107 FIELD_BTN_MOUSE = 1,
108 FIELD_REL_X = 2,
109 FIELD_REL_Y = 4
110 };
111
112 uint32_t fields;
113
114 bool btnMouse;
115 int32_t relX;
116 int32_t relY;
117
118 inline void clear() {
119 fields = 0;
120 }
121
122 inline bool isDirty() {
123 return fields != 0;
124 }
125 } accumulator;
126
127 struct Current {
128 bool down;
129 nsecs_t downTime;
130 } current;
131
132 struct Precalculated {
133 float xScale;
134 float yScale;
135 float xPrecision;
136 float yPrecision;
137 } precalculated;
138
139 void reset();
140 };
141
142 struct SingleTouchScreenState {
143 struct Accumulator {
144 enum {
145 FIELD_BTN_TOUCH = 1,
146 FIELD_ABS_X = 2,
147 FIELD_ABS_Y = 4,
148 FIELD_ABS_PRESSURE = 8,
149 FIELD_ABS_TOOL_WIDTH = 16
150 };
151
152 uint32_t fields;
153
154 bool btnTouch;
155 int32_t absX;
156 int32_t absY;
157 int32_t absPressure;
158 int32_t absToolWidth;
159
160 inline void clear() {
161 fields = 0;
162 }
163
164 inline bool isDirty() {
165 return fields != 0;
166 }
167 } accumulator;
168
169 struct Current {
170 bool down;
171 int32_t x;
172 int32_t y;
173 int32_t pressure;
174 int32_t size;
175 } current;
176
177 void reset();
178 };
179
180 struct MultiTouchScreenState {
181 struct Accumulator {
182 enum {
183 FIELD_ABS_MT_POSITION_X = 1,
184 FIELD_ABS_MT_POSITION_Y = 2,
185 FIELD_ABS_MT_TOUCH_MAJOR = 4,
186 FIELD_ABS_MT_WIDTH_MAJOR = 8,
187 FIELD_ABS_MT_TRACKING_ID = 16
188 };
189
190 uint32_t pointerCount;
191 struct Pointer {
192 uint32_t fields;
193
194 int32_t absMTPositionX;
195 int32_t absMTPositionY;
196 int32_t absMTTouchMajor;
197 int32_t absMTWidthMajor;
198 int32_t absMTTrackingId;
199
200 inline void clear() {
201 fields = 0;
202 }
203 } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
204
205 inline void clear() {
206 pointerCount = 0;
207 pointers[0].clear();
208 }
209
210 inline bool isDirty() {
211 return pointerCount != 0;
212 }
213 } accumulator;
214
215 void reset();
216 };
217
218 struct PointerData {
219 uint32_t id;
220 int32_t x;
221 int32_t y;
222 int32_t pressure;
223 int32_t size;
224 };
225
226 struct TouchData {
227 uint32_t pointerCount;
228 PointerData pointers[MAX_POINTERS];
229 BitSet32 idBits;
230 uint32_t idToIndex[MAX_POINTER_ID];
231
232 void copyFrom(const TouchData& other);
233
234 inline void clear() {
235 pointerCount = 0;
236 idBits.clear();
237 }
238 };
239
240 // common state used for both single-touch and multi-touch screens after the initial
241 // touch decoding has been performed
242 struct TouchScreenState {
243 Vector<VirtualKey> virtualKeys;
244
245 struct Parameters {
246 bool useBadTouchFilter;
247 bool useJumpyTouchFilter;
248 bool useAveragingTouchFilter;
249
250 AbsoluteAxisInfo xAxis;
251 AbsoluteAxisInfo yAxis;
252 AbsoluteAxisInfo pressureAxis;
253 AbsoluteAxisInfo sizeAxis;
254 } parameters;
255
256 // The touch data of the current sample being processed.
257 TouchData currentTouch;
258
259 // The touch data of the previous sample that was processed. This is updated
260 // incrementally while the current sample is being processed.
261 TouchData lastTouch;
262
263 // The time the primary pointer last went down.
264 nsecs_t downTime;
265
266 struct CurrentVirtualKeyState {
267 bool down;
268 nsecs_t downTime;
269 int32_t keyCode;
270 int32_t scanCode;
271 } currentVirtualKey;
272
273 struct AveragingTouchFilterState {
274 // Individual history tracks are stored by pointer id
275 uint32_t historyStart[MAX_POINTERS];
276 uint32_t historyEnd[MAX_POINTERS];
277 struct {
278 struct {
279 int32_t x;
280 int32_t y;
281 int32_t pressure;
282 } pointers[MAX_POINTERS];
283 } historyData[AVERAGING_HISTORY_SIZE];
284 } averagingTouchFilter;
285
286 struct JumpTouchFilterState {
287 int32_t jumpyPointsDropped;
288 } jumpyTouchFilter;
289
290 struct Precalculated {
291 float xScale;
292 float yScale;
293 float pressureScale;
294 float sizeScale;
295 } precalculated;
296
297 void reset();
298
299 bool applyBadTouchFilter();
300 bool applyJumpyTouchFilter();
301 void applyAveragingTouchFilter();
302 void calculatePointerIds();
303
304 bool isPointInsideDisplay(int32_t x, int32_t y) const;
305 };
306
307 InputDevice(int32_t id, uint32_t classes, String8 name);
308
309 int32_t id;
310 uint32_t classes;
311 String8 name;
312 bool ignored;
313
314 KeyboardState keyboard;
315 TrackballState trackball;
316 TouchScreenState touchScreen;
317 union {
318 SingleTouchScreenState singleTouchScreen;
319 MultiTouchScreenState multiTouchScreen;
320 };
321
322 void reset();
323
324 inline bool isKeyboard() const { return classes & INPUT_DEVICE_CLASS_KEYBOARD; }
325 inline bool isAlphaKey() const { return classes & INPUT_DEVICE_CLASS_ALPHAKEY; }
326 inline bool isTrackball() const { return classes & INPUT_DEVICE_CLASS_TRACKBALL; }
327 inline bool isDPad() const { return classes & INPUT_DEVICE_CLASS_DPAD; }
328 inline bool isSingleTouchScreen() const { return (classes
329 & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT))
330 == INPUT_DEVICE_CLASS_TOUCHSCREEN; }
331 inline bool isMultiTouchScreen() const { return classes
332 & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT; }
333 inline bool isTouchScreen() const { return classes
334 & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT); }
335};
336
337
338/* Processes raw input events and sends cooked event data to an input dispatcher
339 * in accordance with the input dispatch policy. */
340class InputReaderInterface : public virtual RefBase {
341protected:
342 InputReaderInterface() { }
343 virtual ~InputReaderInterface() { }
344
345public:
346 /* Runs a single iteration of the processing loop.
347 * Nominally reads and processes one incoming message from the EventHub.
348 *
349 * This method should be called on the input reader thread.
350 */
351 virtual void loopOnce() = 0;
352
353 /* Gets the current virtual key. Returns false if not down.
354 *
355 * This method may be called on any thread (usually by the input manager).
356 */
357 virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const = 0;
358};
359
360/* The input reader reads raw event data from the event hub and processes it into input events
361 * that it sends to the input dispatcher. Some functions of the input reader are controlled
362 * by the input dispatch policy, such as early event filtering in low power states.
363 */
364class InputReader : public InputReaderInterface {
365public:
366 InputReader(const sp<EventHubInterface>& eventHub,
367 const sp<InputDispatchPolicyInterface>& policy,
368 const sp<InputDispatcherInterface>& dispatcher);
369 virtual ~InputReader();
370
371 virtual void loopOnce();
372
373 virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const;
374
375private:
376 // Lock that must be acquired while manipulating state that may be concurrently accessed
377 // from other threads by input state query methods. It should be held for as short a
378 // time as possible.
379 //
380 // Exported state:
381 // - global virtual key code and scan code
382 // - device list and immutable properties of devices such as id, name, and class
383 // (but not other internal device state)
384 mutable Mutex mExportedStateLock;
385
386 // current virtual key information
387 int32_t mGlobalVirtualKeyCode;
388 int32_t mGlobalVirtualScanCode;
389
390 // combined key meta state
391 int32_t mGlobalMetaState;
392
393 sp<EventHubInterface> mEventHub;
394 sp<InputDispatchPolicyInterface> mPolicy;
395 sp<InputDispatcherInterface> mDispatcher;
396
397 KeyedVector<int32_t, InputDevice*> mDevices;
398
399 // display properties needed to translate touch screen coordinates into display coordinates
400 int32_t mDisplayOrientation;
401 int32_t mDisplayWidth;
402 int32_t mDisplayHeight;
403
404 // low-level input event decoding
405 void process(const RawEvent* rawEvent);
406 void handleDeviceAdded(const RawEvent* rawEvent);
407 void handleDeviceRemoved(const RawEvent* rawEvent);
408 void handleSync(const RawEvent* rawEvent);
409 void handleKey(const RawEvent* rawEvent);
410 void handleRelativeMotion(const RawEvent* rawEvent);
411 void handleAbsoluteMotion(const RawEvent* rawEvent);
412 void handleSwitch(const RawEvent* rawEvent);
413
414 // input policy processing and dispatch
415 void onKey(nsecs_t when, InputDevice* device, bool down,
416 int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
417 void onSwitch(nsecs_t when, InputDevice* device, bool down, int32_t code);
418 void onSingleTouchScreenStateChanged(nsecs_t when, InputDevice* device);
419 void onMultiTouchScreenStateChanged(nsecs_t when, InputDevice* device);
420 void onTouchScreenChanged(nsecs_t when, InputDevice* device, bool havePointerIds);
421 void onTrackballStateChanged(nsecs_t when, InputDevice* device);
422 void onConfigurationChanged(nsecs_t when);
423
424 bool applyStandardInputDispatchPolicyActions(nsecs_t when,
425 int32_t policyActions, uint32_t* policyFlags);
426
427 bool consumeVirtualKeyTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
428 void dispatchVirtualKey(nsecs_t when, InputDevice* device, uint32_t policyFlags,
429 int32_t keyEventAction, int32_t keyEventFlags);
430 void dispatchTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
431 void dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
432 InputDevice::TouchData* touch, BitSet32 idBits, int32_t motionEventAction);
433
434 // display
435 void resetDisplayProperties();
436 bool refreshDisplayProperties();
437
438 // device management
439 InputDevice* getDevice(int32_t deviceId);
440 InputDevice* getNonIgnoredDevice(int32_t deviceId);
441 void addDevice(nsecs_t when, int32_t deviceId);
442 void removeDevice(nsecs_t when, InputDevice* device);
443 void configureDevice(InputDevice* device);
444 void configureDeviceForCurrentDisplaySize(InputDevice* device);
445 void configureVirtualKeys(InputDevice* device);
446 void configureAbsoluteAxisInfo(InputDevice* device, int axis, const char* name,
447 InputDevice::AbsoluteAxisInfo* out);
448
449 // global meta state management for all devices
450 void resetGlobalMetaState();
451 int32_t globalMetaState();
452
453 // virtual key management
454 void updateGlobalVirtualKeyState();
455};
456
457
458/* Reads raw events from the event hub and processes them, endlessly. */
459class InputReaderThread : public Thread {
460public:
461 InputReaderThread(const sp<InputReaderInterface>& reader);
462 virtual ~InputReaderThread();
463
464private:
465 sp<InputReaderInterface> mReader;
466
467 virtual bool threadLoop();
468};
469
470} // namespace android
471
472#endif // _UI_INPUT_READER_H