Refactor input reader to support new device types more easily.

Refactored the input reader so that each raw input protocol is handled
by a separate subclass of the new InputMapper type.  This way, behaviors
pertaining to keyboard, trackballs, touchscreens, switches and other
devices are clearly distinguished for improved maintainability.

Added partial support for describing capabilities of input devices
(incomplete and untested for now, will be fleshed out in later commits).

Simplified EventHub interface somewhat since InputReader is taking over
more of the work.

Cleaned up some of the interactions between InputManager and
WindowManagerService related to reading input state.

Fixed swiping finger from screen edge into display area.

Added logging of device information to 'dumpsys window'.

Change-Id: I17faffc33e3aec3a0f33f0b37e81a70609378612
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index 5be17d3..dab35b3 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -60,6 +60,31 @@
 class KeyLayoutMap;
 
 /*
+ * A raw event as retrieved from the EventHub.
+ */
+struct RawEvent {
+    nsecs_t when;
+    int32_t deviceId;
+    int32_t type;
+    int32_t scanCode;
+    int32_t keyCode;
+    int32_t value;
+    uint32_t flags;
+};
+
+/* Describes an absolute axis. */
+struct RawAbsoluteAxisInfo {
+    bool valid; // true if the information is valid, false otherwise
+
+    int32_t minValue;  // minimum value
+    int32_t maxValue;  // maximum value
+    int32_t flat;      // center flat position, eg. flat == 8 means center is between -8 and 8
+    int32_t fuzz;      // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
+
+    inline int32_t getRange() { return maxValue - minValue; }
+};
+
+/*
  * Input device classes.
  */
 enum {
@@ -82,7 +107,10 @@
     INPUT_DEVICE_CLASS_DPAD          = 0x00000020,
 
     /* The input device is a gamepad (implies keyboard). */
-    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040
+    INPUT_DEVICE_CLASS_GAMEPAD       = 0x00000040,
+
+    /* The input device has switches. */
+    INPUT_DEVICE_CLASS_SWITCH        = 0x00000080,
 };
 
 /*
@@ -114,8 +142,8 @@
 
     virtual String8 getDeviceName(int32_t deviceId) const = 0;
 
-    virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
-            int* outMaxValue, int* outFlat, int* outFuzz) const = 0;
+    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+            RawAbsoluteAxisInfo* outAxisInfo) const = 0;
 
     virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
             int32_t* outKeycode, uint32_t* outFlags) const = 0;
@@ -131,26 +159,19 @@
      * If the device needs to remain awake longer than that, then the caller is responsible
      * for taking care of it (say, by poking the power manager user activity timer).
      */
-    virtual bool getEvent(int32_t* outDeviceId, int32_t* outType,
-            int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
-            int32_t* outValue, nsecs_t* outWhen) = 0;
+    virtual bool getEvent(RawEvent* outEvent) = 0;
 
     /*
      * Query current input state.
-     *   deviceId may be -1 to search for the device automatically, filtered by class.
-     *   deviceClasses may be -1 to ignore device class while searching.
      */
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t scanCode) const = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t keyCode) const = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
-            int32_t sw) const = 0;
+    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const = 0;
+    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const = 0;
+    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const = 0;
 
     /*
      * Examine key input devices for specific framework keycode support
      */
-    virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes,
+    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
             uint8_t* outFlags) const = 0;
 };
 
@@ -165,33 +186,28 @@
     
     virtual String8 getDeviceName(int32_t deviceId) const;
     
-    virtual int getAbsoluteInfo(int32_t deviceId, int axis, int *outMinValue,
-            int* outMaxValue, int* outFlat, int* outFuzz) const;
-        
+    virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
+            RawAbsoluteAxisInfo* outAxisInfo) const;
+
     virtual status_t scancodeToKeycode(int32_t deviceId, int scancode,
             int32_t* outKeycode, uint32_t* outFlags) const;
 
     virtual void addExcludedDevice(const char* deviceName);
 
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t scanCode) const;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t keyCode) const;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
-            int32_t sw) const;
+    virtual int32_t getScanCodeState(int32_t deviceId, int32_t scanCode) const;
+    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t keyCode) const;
+    virtual int32_t getSwitchState(int32_t deviceId, int32_t sw) const;
 
-    virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
+    virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags) const;
 
-    virtual bool getEvent(int32_t* outDeviceId, int32_t* outType,
-            int32_t* outScancode, int32_t* outKeycode, uint32_t *outFlags,
-            int32_t* outValue, nsecs_t* outWhen);
+    virtual bool getEvent(RawEvent* outEvent);
 
 protected:
     virtual ~EventHub();
     
 private:
     bool openPlatformInput(void);
-    int32_t convertDeviceKey_TI_P2(int code);
 
     int open_device(const char *device);
     int close_device(const char *device);
@@ -220,6 +236,8 @@
     int32_t getScanCodeStateLocked(device_t* device, int32_t scanCode) const;
     int32_t getKeyCodeStateLocked(device_t* device, int32_t keyCode) const;
     int32_t getSwitchStateLocked(device_t* device, int32_t sw) const;
+    bool markSupportedKeyCodesLocked(device_t* device, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags) const;
 
     // Protect all internal state.
     mutable Mutex   mLock;
diff --git a/include/ui/Input.h b/include/ui/Input.h
index d9b1091..2385973 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -23,7 +23,10 @@
 
 #include <android/input.h>
 #include <utils/Vector.h>
+#include <utils/KeyedVector.h>
 #include <utils/Timers.h>
+#include <utils/RefBase.h>
+#include <utils/String8.h>
 
 /*
  * Additional private constants not defined in ndk/ui/input.h.
@@ -47,21 +50,16 @@
     virtual ~AInputEvent() { }
 };
 
-namespace android {
-
 /*
- * A raw event as retrieved from the EventHub.
+ * Declare a concrete type for the NDK's input device forward declaration.
  */
-struct RawEvent {
-    nsecs_t when;
-    int32_t deviceId;
-    int32_t type;
-    int32_t scanCode;
-    int32_t keyCode;
-    int32_t value;
-    uint32_t flags;
+struct AInputDevice {
+    virtual ~AInputDevice() { }
 };
 
+
+namespace android {
+
 /*
  * Flags that flow alongside events in the input dispatch system to help with certain
  * policy decisions such as waking from device sleep.
@@ -424,6 +422,69 @@
     MotionEvent mMotionEvent;
 };
 
+/*
+ * Describes the characteristics and capabilities of an input device.
+ */
+class InputDeviceInfo {
+public:
+    InputDeviceInfo();
+    InputDeviceInfo(const InputDeviceInfo& other);
+    ~InputDeviceInfo();
+
+    struct MotionRange {
+        float min;
+        float max;
+        float flat;
+        float fuzz;
+    };
+
+    void initialize(int32_t id, const String8& name);
+
+    inline int32_t getId() const { return mId; }
+    inline const String8 getName() const { return mName; }
+    inline uint32_t getSources() const { return mSources; }
+
+    const MotionRange* getMotionRange(int32_t rangeType) const;
+
+    void addSource(uint32_t source);
+    void addMotionRange(int32_t rangeType, float min, float max, float flat, float fuzz);
+    void addMotionRange(int32_t rangeType, const MotionRange& range);
+
+    inline void setKeyboardType(int32_t keyboardType) { mKeyboardType = keyboardType; }
+    inline int32_t getKeyboardType() const { return mKeyboardType; }
+
+private:
+    int32_t mId;
+    String8 mName;
+    uint32_t mSources;
+    int32_t mKeyboardType;
+
+    KeyedVector<int32_t, MotionRange> mMotionRanges;
+};
+
+/*
+ * Provides remote access to information about an input device.
+ *
+ * Note: This is essentially a wrapper for Binder calls into the Window Manager Service.
+ */
+class InputDeviceProxy : public RefBase, public AInputDevice {
+protected:
+    InputDeviceProxy();
+    virtual ~InputDeviceProxy();
+
+public:
+    static void getDeviceIds(Vector<int32_t>& outIds);
+
+    static sp<InputDeviceProxy> getDevice(int32_t id);
+
+    inline const InputDeviceInfo* getInfo() { return & mInfo; }
+
+    // TODO add hasKeys, keymap, etc...
+
+private:
+    InputDeviceInfo mInfo;
+};
+
 
 } // namespace android
 
diff --git a/include/ui/InputDevice.h b/include/ui/InputDevice.h
deleted file mode 100644
index 3b9c70e..0000000
--- a/include/ui/InputDevice.h
+++ /dev/null
@@ -1,353 +0,0 @@
-/*
- * Copyright (C) 2010 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef _UI_INPUT_DEVICE_H
-#define _UI_INPUT_DEVICE_H
-
-#include <ui/EventHub.h>
-#include <ui/Input.h>
-#include <utils/KeyedVector.h>
-#include <utils/threads.h>
-#include <utils/Timers.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/BitSet.h>
-
-#include <stddef.h>
-#include <unistd.h>
-
-/* Maximum pointer id value supported.
- * (This is limited by our use of BitSet32 to track pointer assignments.) */
-#define MAX_POINTER_ID 31
-
-/* Maximum number of historical samples to average. */
-#define AVERAGING_HISTORY_SIZE 5
-
-
-namespace android {
-
-extern int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState);
-extern int32_t rotateKeyCode(int32_t keyCode, int32_t orientation);
-
-
-/*
- * An input device structure tracks the state of a single input device.
- *
- * This structure is only used by ReaderThread and is not intended to be shared with
- * DispatcherThread (because that would require locking).  This works out fine because
- * DispatcherThread is only interested in cooked event data anyways and does not need
- * any of the low-level data from InputDevice.
- */
-struct InputDevice {
-    struct AbsoluteAxisInfo {
-        bool valid;        // set to true if axis parameters are known, false otherwise
-
-        int32_t minValue;  // minimum value
-        int32_t maxValue;  // maximum value
-        int32_t range;     // range of values, equal to maxValue - minValue
-        int32_t flat;      // center flat position, eg. flat == 8 means center is between -8 and 8
-        int32_t fuzz;      // error tolerance, eg. fuzz == 4 means value is +/- 4 due to noise
-    };
-
-    struct VirtualKey {
-        int32_t keyCode;
-        int32_t scanCode;
-        uint32_t flags;
-
-        // computed hit box, specified in touch screen coords based on known display size
-        int32_t hitLeft;
-        int32_t hitTop;
-        int32_t hitRight;
-        int32_t hitBottom;
-
-        inline bool isHit(int32_t x, int32_t y) const {
-            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
-        }
-    };
-
-    struct KeyboardState {
-        struct Current {
-            int32_t metaState;
-            nsecs_t downTime; // time of most recent key down
-        } current;
-
-        void reset();
-    };
-
-    struct TrackballState {
-        struct Accumulator {
-            enum {
-                FIELD_BTN_MOUSE = 1,
-                FIELD_REL_X = 2,
-                FIELD_REL_Y = 4
-            };
-
-            uint32_t fields;
-
-            bool btnMouse;
-            int32_t relX;
-            int32_t relY;
-
-            inline void clear() {
-                fields = 0;
-            }
-
-            inline bool isDirty() {
-                return fields != 0;
-            }
-        } accumulator;
-
-        struct Current {
-            bool down;
-            nsecs_t downTime;
-        } current;
-
-        struct Precalculated {
-            float xScale;
-            float yScale;
-            float xPrecision;
-            float yPrecision;
-        } precalculated;
-
-        void reset();
-    };
-
-    struct SingleTouchScreenState {
-        struct Accumulator {
-            enum {
-                FIELD_BTN_TOUCH = 1,
-                FIELD_ABS_X = 2,
-                FIELD_ABS_Y = 4,
-                FIELD_ABS_PRESSURE = 8,
-                FIELD_ABS_TOOL_WIDTH = 16
-            };
-
-            uint32_t fields;
-
-            bool btnTouch;
-            int32_t absX;
-            int32_t absY;
-            int32_t absPressure;
-            int32_t absToolWidth;
-
-            inline void clear() {
-                fields = 0;
-            }
-
-            inline bool isDirty() {
-                return fields != 0;
-            }
-        } accumulator;
-
-        struct Current {
-            bool down;
-            int32_t x;
-            int32_t y;
-            int32_t pressure;
-            int32_t size;
-        } current;
-
-        void reset();
-    };
-
-    struct MultiTouchScreenState {
-        struct Accumulator {
-            enum {
-                FIELD_ABS_MT_POSITION_X = 1,
-                FIELD_ABS_MT_POSITION_Y = 2,
-                FIELD_ABS_MT_TOUCH_MAJOR = 4,
-                FIELD_ABS_MT_TOUCH_MINOR = 8,
-                FIELD_ABS_MT_WIDTH_MAJOR = 16,
-                FIELD_ABS_MT_WIDTH_MINOR = 32,
-                FIELD_ABS_MT_ORIENTATION = 64,
-                FIELD_ABS_MT_TRACKING_ID = 128
-            };
-
-            uint32_t pointerCount;
-            struct Pointer {
-                uint32_t fields;
-
-                int32_t absMTPositionX;
-                int32_t absMTPositionY;
-                int32_t absMTTouchMajor;
-                int32_t absMTTouchMinor;
-                int32_t absMTWidthMajor;
-                int32_t absMTWidthMinor;
-                int32_t absMTOrientation;
-                int32_t absMTTrackingId;
-
-                inline void clear() {
-                    fields = 0;
-                }
-            } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
-
-            inline void clear() {
-                pointerCount = 0;
-                pointers[0].clear();
-            }
-
-            inline bool isDirty() {
-                return pointerCount != 0;
-            }
-        } accumulator;
-
-        void reset();
-    };
-
-    struct PointerData {
-        uint32_t id;
-        int32_t x;
-        int32_t y;
-        int32_t pressure;
-        int32_t size;
-        int32_t touchMajor;
-        int32_t touchMinor;
-        int32_t toolMajor;
-        int32_t toolMinor;
-        int32_t orientation;
-    };
-
-    struct TouchData {
-        uint32_t pointerCount;
-        PointerData pointers[MAX_POINTERS];
-        BitSet32 idBits;
-        uint32_t idToIndex[MAX_POINTER_ID + 1];
-
-        void copyFrom(const TouchData& other);
-
-        inline void clear() {
-            pointerCount = 0;
-            idBits.clear();
-        }
-    };
-
-    // common state used for both single-touch and multi-touch screens after the initial
-    // touch decoding has been performed
-    struct TouchScreenState {
-        Vector<VirtualKey> virtualKeys;
-
-        struct Parameters {
-            bool useBadTouchFilter;
-            bool useJumpyTouchFilter;
-            bool useAveragingTouchFilter;
-
-            AbsoluteAxisInfo xAxis;
-            AbsoluteAxisInfo yAxis;
-            AbsoluteAxisInfo pressureAxis;
-            AbsoluteAxisInfo sizeAxis;
-            AbsoluteAxisInfo orientationAxis;
-        } parameters;
-
-        // The touch data of the current sample being processed.
-        TouchData currentTouch;
-
-        // The touch data of the previous sample that was processed.  This is updated
-        // incrementally while the current sample is being processed.
-        TouchData lastTouch;
-
-        // The time the primary pointer last went down.
-        nsecs_t downTime;
-
-        struct CurrentVirtualKeyState {
-            enum Status {
-                STATUS_UP,
-                STATUS_DOWN,
-                STATUS_CANCELED
-            };
-
-            Status status;
-            nsecs_t downTime;
-            int32_t keyCode;
-            int32_t scanCode;
-        } currentVirtualKey;
-
-        struct AveragingTouchFilterState {
-            // Individual history tracks are stored by pointer id
-            uint32_t historyStart[MAX_POINTERS];
-            uint32_t historyEnd[MAX_POINTERS];
-            struct {
-                struct {
-                    int32_t x;
-                    int32_t y;
-                    int32_t pressure;
-                } pointers[MAX_POINTERS];
-            } historyData[AVERAGING_HISTORY_SIZE];
-        } averagingTouchFilter;
-
-        struct JumpTouchFilterState {
-            int32_t jumpyPointsDropped;
-        } jumpyTouchFilter;
-
-        struct Precalculated {
-            int32_t xOrigin;
-            float xScale;
-
-            int32_t yOrigin;
-            float yScale;
-
-            int32_t pressureOrigin;
-            float pressureScale;
-
-            int32_t sizeOrigin;
-            float sizeScale;
-
-            float orientationScale;
-        } precalculated;
-
-        void reset();
-
-        bool applyBadTouchFilter();
-        bool applyJumpyTouchFilter();
-        void applyAveragingTouchFilter();
-        void calculatePointerIds();
-
-        bool isPointInsideDisplay(int32_t x, int32_t y) const;
-        const InputDevice::VirtualKey* findVirtualKeyHit() const;
-    };
-
-    InputDevice(int32_t id, uint32_t classes, String8 name);
-
-    int32_t id;
-    uint32_t classes;
-    String8 name;
-    bool ignored;
-
-    KeyboardState keyboard;
-    TrackballState trackball;
-    TouchScreenState touchScreen;
-    union {
-        SingleTouchScreenState singleTouchScreen;
-        MultiTouchScreenState multiTouchScreen;
-    };
-
-    void reset();
-
-    inline bool isKeyboard() const { return classes & INPUT_DEVICE_CLASS_KEYBOARD; }
-    inline bool isAlphaKey() const { return classes & INPUT_DEVICE_CLASS_ALPHAKEY; }
-    inline bool isTrackball() const { return classes & INPUT_DEVICE_CLASS_TRACKBALL; }
-    inline bool isDPad() const { return classes & INPUT_DEVICE_CLASS_DPAD; }
-    inline bool isSingleTouchScreen() const { return (classes
-            & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT))
-            == INPUT_DEVICE_CLASS_TOUCHSCREEN; }
-    inline bool isMultiTouchScreen() const { return classes
-            & INPUT_DEVICE_CLASS_TOUCHSCREEN_MT; }
-    inline bool isTouchScreen() const { return classes
-            & (INPUT_DEVICE_CLASS_TOUCHSCREEN | INPUT_DEVICE_CLASS_TOUCHSCREEN_MT); }
-};
-
-} // namespace android
-
-#endif // _UI_INPUT_DEVICE_H
diff --git a/include/ui/InputManager.h b/include/ui/InputManager.h
index e755238..7ebec10 100644
--- a/include/ui/InputManager.h
+++ b/include/ui/InputManager.h
@@ -96,22 +96,28 @@
     virtual void preemptInputDispatch() = 0;
 
     /* Gets input device configuration. */
-    virtual void getInputConfiguration(InputConfiguration* outConfiguration) const = 0;
+    virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
 
-    /*
-     * Queries current input state.
-     *   deviceId may be -1 to search for the device automatically, filtered by class.
-     *   deviceClasses may be -1 to ignore device class while searching.
+    /* Gets information about the specified input device.
+     * Returns OK if the device information was obtained or NAME_NOT_FOUND if there
+     * was no such device.
      */
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t scanCode) const = 0;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t keyCode) const = 0;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
-            int32_t sw) const = 0;
+    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
+
+    /* Gets the list of all registered device ids. */
+    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
+
+    /* Queries current input state. */
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode) = 0;
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode) = 0;
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw) = 0;
 
     /* Determines whether physical keys exist for the given framework-domain key codes. */
-    virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
 };
 
 class InputManager : public InputManagerInterface {
@@ -140,14 +146,17 @@
 
     virtual void preemptInputDispatch();
 
-    virtual void getInputConfiguration(InputConfiguration* outConfiguration) const;
-    virtual int32_t getScanCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t scanCode) const;
-    virtual int32_t getKeyCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t keyCode) const;
-    virtual int32_t getSwitchState(int32_t deviceId, int32_t deviceClasses,
-            int32_t sw) const;
-    virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
+    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
+    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
+    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode);
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode);
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw);
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
 
 private:
     sp<InputReaderInterface> mReader;
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index 14bea65..d7ec8ea 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -19,7 +19,6 @@
 
 #include <ui/EventHub.h>
 #include <ui/Input.h>
-#include <ui/InputDevice.h>
 #include <ui/InputDispatcher.h>
 #include <utils/KeyedVector.h>
 #include <utils/threads.h>
@@ -33,6 +32,10 @@
 
 namespace android {
 
+class InputDevice;
+class InputMapper;
+
+
 /*
  * Input reader policy interface.
  *
@@ -68,14 +71,6 @@
         // The input dispatcher should perform special filtering in preparation for
         // a pending app switch.
         ACTION_APP_SWITCH_COMING = 0x00000002,
-
-        // The input dispatcher should add POLICY_FLAG_WOKE_HERE to the policy flags it
-        // passes through the dispatch pipeline.
-        ACTION_WOKE_HERE = 0x00000004,
-
-        // The input dispatcher should add POLICY_FLAG_BRIGHT_HERE to the policy flags it
-        // passes through the dispatch pipeline.
-        ACTION_BRIGHT_HERE = 0x00000008,
     };
 
     /* Describes a virtual key. */
@@ -101,38 +96,30 @@
 
     /* Intercepts a key event.
      * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing.
+     * and early event preprocessing such as updating policy flags.
      *
      * Returns a policy action constant such as ACTION_DISPATCH.
      */
     virtual int32_t interceptKey(nsecs_t when, int32_t deviceId,
-            bool down, int32_t keyCode, int32_t scanCode, uint32_t policyFlags) = 0;
-
-    /* Intercepts a trackball event.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing.
-     *
-     * Returns a policy action constant such as ACTION_DISPATCH.
-     */
-    virtual int32_t interceptTrackball(nsecs_t when, bool buttonChanged, bool buttonDown,
-            bool rolled) = 0;
-
-    /* Intercepts a touch event.
-     * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing.
-     *
-     * Returns a policy action constant such as ACTION_DISPATCH.
-     */
-    virtual int32_t interceptTouch(nsecs_t when) = 0;
+            bool down, int32_t keyCode, int32_t scanCode, uint32_t& policyFlags) = 0;
 
     /* Intercepts a switch event.
      * The policy can use this method as an opportunity to perform power management functions
-     * and early event preprocessing.
+     * and early event preprocessing such as updating policy flags.
      *
      * Switches are not dispatched to applications so this method should
      * usually return ACTION_NONE.
      */
-    virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue) = 0;
+    virtual int32_t interceptSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue,
+            uint32_t& policyFlags) = 0;
+
+    /* Intercepts a generic touch, trackball or other event.
+     * The policy can use this method as an opportunity to perform power management functions
+     * and early event preprocessing such as updating policy flags.
+     *
+     * Returns a policy action constant such as ACTION_DISPATCH.
+     */
+    virtual int32_t interceptGeneric(nsecs_t when, uint32_t& policyFlags) = 0;
 
     /* Determines whether to turn on some hacks we have to improve the touch interaction with a
      * certain device whose screen currently is not all that good.
@@ -167,32 +154,52 @@
      */
     virtual void loopOnce() = 0;
 
-    /* Gets the current virtual key.  Returns false if not down.
-     *
-     * This method may be called on any thread (usually by the input manager).
-     */
-    virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const = 0;
-
     /* Gets the current input device configuration.
      *
      * This method may be called on any thread (usually by the input manager).
      */
-    virtual void getCurrentInputConfiguration(InputConfiguration* outConfiguration) const = 0;
+    virtual void getInputConfiguration(InputConfiguration* outConfiguration) = 0;
 
-    /*
-     * Query current input state.
-     *   deviceId may be -1 to search for the device automatically, filtered by class.
-     *   deviceClasses may be -1 to ignore device class while searching.
+    /* Gets information about the specified input device.
+     * Returns OK if the device information was obtained or NAME_NOT_FOUND if there
+     * was no such device.
+     *
+     * This method may be called on any thread (usually by the input manager).
      */
-    virtual int32_t getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t scanCode) const = 0;
-    virtual int32_t getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t keyCode) const = 0;
-    virtual int32_t getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
-            int32_t sw) const = 0;
+    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo) = 0;
+
+    /* Gets the list of all registered device ids. */
+    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds) = 0;
+
+    /* Query current input state. */
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode) = 0;
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode) = 0;
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw) = 0;
 
     /* Determine whether physical keys exist for the given framework-domain key codes. */
-    virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const = 0;
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) = 0;
+};
+
+
+/* Internal interface used by individual input devices to access global input device state
+ * and parameters maintained by the input reader.
+ */
+class InputReaderContext {
+protected:
+    InputReaderContext() { }
+    virtual ~InputReaderContext() { }
+
+public:
+    virtual void updateGlobalMetaState() = 0;
+    virtual int32_t getGlobalMetaState() = 0;
+
+    virtual InputReaderPolicyInterface* getPolicy() = 0;
+    virtual InputDispatcherInterface* getDispatcher() = 0;
+    virtual EventHubInterface* getEventHub() = 0;
 };
 
 
@@ -201,10 +208,11 @@
  * event filtering in low power states, are controlled by a separate policy object.
  *
  * IMPORTANT INVARIANT:
- *     Because the policy can potentially block or cause re-entrance into the input reader,
- *     the input reader never calls into the policy while holding its internal locks.
+ *     Because the policy and dispatcher can potentially block or cause re-entrance into
+ *     the input reader, the input reader never calls into other components while holding
+ *     an exclusive internal lock.
  */
-class InputReader : public InputReaderInterface {
+class InputReader : public InputReaderInterface, private InputReaderContext {
 public:
     InputReader(const sp<EventHubInterface>& eventHub,
             const sp<InputReaderPolicyInterface>& policy,
@@ -213,107 +221,69 @@
 
     virtual void loopOnce();
 
-    virtual bool getCurrentVirtualKey(int32_t* outKeyCode, int32_t* outScanCode) const;
+    virtual void getInputConfiguration(InputConfiguration* outConfiguration);
 
-    virtual void getCurrentInputConfiguration(InputConfiguration* outConfiguration) const;
+    virtual status_t getInputDeviceInfo(int32_t deviceId, InputDeviceInfo* outDeviceInfo);
+    virtual void getInputDeviceIds(Vector<int32_t>& outDeviceIds);
 
-    virtual int32_t getCurrentScanCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t scanCode) const;
-    virtual int32_t getCurrentKeyCodeState(int32_t deviceId, int32_t deviceClasses,
-            int32_t keyCode) const;
-    virtual int32_t getCurrentSwitchState(int32_t deviceId, int32_t deviceClasses,
-            int32_t sw) const;
+    virtual int32_t getScanCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t scanCode);
+    virtual int32_t getKeyCodeState(int32_t deviceId, uint32_t sourceMask,
+            int32_t keyCode);
+    virtual int32_t getSwitchState(int32_t deviceId, uint32_t sourceMask,
+            int32_t sw);
 
-    virtual bool hasKeys(size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags) const;
+    virtual bool hasKeys(int32_t deviceId, uint32_t sourceMask,
+            size_t numCodes, const int32_t* keyCodes, uint8_t* outFlags);
 
 private:
-    // Lock that must be acquired while manipulating state that may be concurrently accessed
-    // from other threads by input state query methods.  It should be held for as short a
-    // time as possible.
-    //
-    // Exported state:
-    //   - global virtual key code and scan code
-    //   - device list and immutable properties of devices such as id, name, and class
-    //     (but not other internal device state)
-    mutable Mutex mExportedStateLock;
-
-    // current virtual key information (lock mExportedStateLock)
-    int32_t mExportedVirtualKeyCode;
-    int32_t mExportedVirtualScanCode;
-
-    // current input configuration (lock mExportedStateLock)
-    InputConfiguration mExportedInputConfiguration;
-
-    // combined key meta state
-    int32_t mGlobalMetaState;
-
     sp<EventHubInterface> mEventHub;
     sp<InputReaderPolicyInterface> mPolicy;
     sp<InputDispatcherInterface> mDispatcher;
 
+    virtual InputReaderPolicyInterface* getPolicy() { return mPolicy.get(); }
+    virtual InputDispatcherInterface* getDispatcher() { return mDispatcher.get(); }
+    virtual EventHubInterface* getEventHub() { return mEventHub.get(); }
+
+    // This reader/writer lock guards the list of input devices.
+    // The writer lock must be held whenever the list of input devices is modified
+    //   and then promptly released.
+    // The reader lock must be held whenever the list of input devices is traversed or an
+    //   input device in the list is accessed.
+    // This lock only protects the registry and prevents inadvertent deletion of device objects
+    // that are in use.  Individual devices are responsible for guarding their own internal state
+    // as needed for concurrent operation.
+    RWLock mDeviceRegistryLock;
     KeyedVector<int32_t, InputDevice*> mDevices;
 
-    // display properties needed to translate touch screen coordinates into display coordinates
-    int32_t mDisplayOrientation;
-    int32_t mDisplayWidth;
-    int32_t mDisplayHeight;
-
-    // low-level input event decoding
+    // low-level input event decoding and device management
     void process(const RawEvent* rawEvent);
-    void handleDeviceAdded(const RawEvent* rawEvent);
-    void handleDeviceRemoved(const RawEvent* rawEvent);
-    void handleSync(const RawEvent* rawEvent);
-    void handleKey(const RawEvent* rawEvent);
-    void handleRelativeMotion(const RawEvent* rawEvent);
-    void handleAbsoluteMotion(const RawEvent* rawEvent);
-    void handleSwitch(const RawEvent* rawEvent);
 
-    // input policy processing and dispatch
-    void onKey(nsecs_t when, InputDevice* device, bool down,
-            int32_t keyCode, int32_t scanCode, uint32_t policyFlags);
-    void onSwitch(nsecs_t when, InputDevice* device, int32_t switchCode, int32_t switchValue);
-    void onSingleTouchScreenStateChanged(nsecs_t when, InputDevice* device);
-    void onMultiTouchScreenStateChanged(nsecs_t when, InputDevice* device);
-    void onTouchScreenChanged(nsecs_t when, InputDevice* device, bool havePointerIds);
-    void onTrackballStateChanged(nsecs_t when, InputDevice* device);
-    void onConfigurationChanged(nsecs_t when);
-
-    bool applyStandardInputDispatchPolicyActions(nsecs_t when,
-            int32_t policyActions, uint32_t* policyFlags);
-
-    bool consumeVirtualKeyTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
-    void dispatchVirtualKey(nsecs_t when, InputDevice* device, uint32_t policyFlags,
-            int32_t keyEventAction, int32_t keyEventFlags);
-    void dispatchTouches(nsecs_t when, InputDevice* device, uint32_t policyFlags);
-    void dispatchTouch(nsecs_t when, InputDevice* device, uint32_t policyFlags,
-            InputDevice::TouchData* touch, BitSet32 idBits, uint32_t changedId,
-            int32_t motionEventAction);
-
-    // display
-    void resetDisplayProperties();
-    bool refreshDisplayProperties();
-
-    // device management
-    InputDevice* getDevice(int32_t deviceId);
-    InputDevice* getNonIgnoredDevice(int32_t deviceId);
     void addDevice(nsecs_t when, int32_t deviceId);
-    void removeDevice(nsecs_t when, InputDevice* device);
-    void configureDevice(InputDevice* device);
-    void configureDeviceForCurrentDisplaySize(InputDevice* device);
-    void configureVirtualKeys(InputDevice* device);
-    void configureAbsoluteAxisInfo(InputDevice* device, int axis, const char* name,
-            InputDevice::AbsoluteAxisInfo* out);
+    void removeDevice(nsecs_t when, int32_t deviceId);
+    InputDevice* createDevice(int32_t deviceId, const String8& name, uint32_t classes);
     void configureExcludedDevices();
 
-    // global meta state management for all devices
-    void resetGlobalMetaState();
-    int32_t globalMetaState();
+    void consumeEvent(const RawEvent* rawEvent);
 
-    // virtual key management
-    void updateExportedVirtualKeyState();
+    void handleConfigurationChanged(nsecs_t when);
 
-    // input configuration management
-    void updateExportedInputConfiguration();
+    // state management for all devices
+    Mutex mStateLock;
+
+    int32_t mGlobalMetaState;
+    virtual void updateGlobalMetaState();
+    virtual int32_t getGlobalMetaState();
+
+    InputConfiguration mInputConfiguration;
+    void updateInputConfiguration();
+
+    // state queries
+    typedef int32_t (InputDevice::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+    int32_t getState(int32_t deviceId, uint32_t sourceMask, int32_t code,
+            GetStateFunc getStateFunc);
+    bool markSupportedKeyCodes(int32_t deviceId, uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
 };
 
 
@@ -329,6 +299,527 @@
     virtual bool threadLoop();
 };
 
+
+/* Represents the state of a single input device. */
+class InputDevice {
+public:
+    InputDevice(InputReaderContext* context, int32_t id, const String8& name);
+    ~InputDevice();
+
+    inline InputReaderContext* getContext() { return mContext; }
+    inline int32_t getId() { return mId; }
+    inline const String8& getName() { return mName; }
+    inline uint32_t getSources() { return mSources; }
+
+    inline bool isIgnored() { return mMappers.isEmpty(); }
+
+    void addMapper(InputMapper* mapper);
+    void configure();
+    void reset();
+    void process(const RawEvent* rawEvent);
+
+    void getDeviceInfo(InputDeviceInfo* outDeviceInfo);
+    int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    int32_t getMetaState();
+
+private:
+    InputReaderContext* mContext;
+    int32_t mId;
+
+    Vector<InputMapper*> mMappers;
+
+    String8 mName;
+    uint32_t mSources;
+
+    typedef int32_t (InputMapper::*GetStateFunc)(uint32_t sourceMask, int32_t code);
+    int32_t getState(uint32_t sourceMask, int32_t code, GetStateFunc getStateFunc);
+};
+
+
+/* An input mapper transforms raw input events into cooked event data.
+ * A single input device can have multiple associated input mappers in order to interpret
+ * different classes of events.
+ */
+class InputMapper {
+public:
+    InputMapper(InputDevice* device);
+    virtual ~InputMapper();
+
+    inline InputDevice* getDevice() { return mDevice; }
+    inline int32_t getDeviceId() { return mDevice->getId(); }
+    inline const String8 getDeviceName() { return mDevice->getName(); }
+    inline InputReaderContext* getContext() { return mContext; }
+    inline InputReaderPolicyInterface* getPolicy() { return mContext->getPolicy(); }
+    inline InputDispatcherInterface* getDispatcher() { return mContext->getDispatcher(); }
+    inline EventHubInterface* getEventHub() { return mContext->getEventHub(); }
+
+    virtual uint32_t getSources() = 0;
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void configure();
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent) = 0;
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual int32_t getMetaState();
+
+protected:
+    InputDevice* mDevice;
+    InputReaderContext* mContext;
+
+    bool applyStandardPolicyActions(nsecs_t when, int32_t policyActions);
+};
+
+
+class SwitchInputMapper : public InputMapper {
+public:
+    SwitchInputMapper(InputDevice* device);
+    virtual ~SwitchInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getSwitchState(uint32_t sourceMask, int32_t switchCode);
+
+private:
+    void processSwitch(nsecs_t when, int32_t switchCode, int32_t switchValue);
+};
+
+
+class KeyboardInputMapper : public InputMapper {
+public:
+    KeyboardInputMapper(InputDevice* device, int32_t associatedDisplayId, uint32_t sources,
+            int32_t keyboardType);
+    virtual ~KeyboardInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+    virtual int32_t getMetaState();
+
+private:
+    struct KeyDown {
+        int32_t keyCode;
+        int32_t scanCode;
+    };
+
+    int32_t mAssociatedDisplayId;
+    uint32_t mSources;
+    int32_t mKeyboardType;
+
+    Vector<KeyDown> mKeyDowns; // keys that are down
+    int32_t mMetaState;
+    nsecs_t mDownTime; // time of most recent key down
+
+    void initialize();
+
+    bool isKeyboardOrGamepadKey(int32_t scanCode);
+    void processKey(nsecs_t when, bool down, int32_t keyCode, int32_t scanCode,
+            uint32_t policyFlags);
+
+    ssize_t findKeyDown(int32_t scanCode);
+};
+
+
+class TrackballInputMapper : public InputMapper {
+public:
+    TrackballInputMapper(InputDevice* device, int32_t associatedDisplayId);
+    virtual ~TrackballInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+private:
+    // Amount that trackball needs to move in order to generate a key event.
+    static const int32_t TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+    int32_t mAssociatedDisplayId;
+
+    struct Accumulator {
+        enum {
+            FIELD_BTN_MOUSE = 1,
+            FIELD_REL_X = 2,
+            FIELD_REL_Y = 4
+        };
+
+        uint32_t fields;
+
+        bool btnMouse;
+        int32_t relX;
+        int32_t relY;
+
+        inline void clear() {
+            fields = 0;
+        }
+
+        inline bool isDirty() {
+            return fields != 0;
+        }
+    } mAccumulator;
+
+    bool mDown;
+    nsecs_t mDownTime;
+
+    float mXScale;
+    float mYScale;
+    float mXPrecision;
+    float mYPrecision;
+
+    void initialize();
+
+    void sync(nsecs_t when);
+};
+
+
+class TouchInputMapper : public InputMapper {
+public:
+    TouchInputMapper(InputDevice* device, int32_t associatedDisplayId);
+    virtual ~TouchInputMapper();
+
+    virtual uint32_t getSources();
+    virtual void populateDeviceInfo(InputDeviceInfo* deviceInfo);
+    virtual void configure();
+    virtual void reset();
+
+    virtual int32_t getKeyCodeState(uint32_t sourceMask, int32_t keyCode);
+    virtual int32_t getScanCodeState(uint32_t sourceMask, int32_t scanCode);
+    virtual bool markSupportedKeyCodes(uint32_t sourceMask, size_t numCodes,
+            const int32_t* keyCodes, uint8_t* outFlags);
+
+protected:
+    /* Maximum pointer id value supported.
+     * (This is limited by our use of BitSet32 to track pointer assignments.) */
+    static const uint32_t MAX_POINTER_ID = 31;
+
+    struct VirtualKey {
+        int32_t keyCode;
+        int32_t scanCode;
+        uint32_t flags;
+
+        // computed hit box, specified in touch screen coords based on known display size
+        int32_t hitLeft;
+        int32_t hitTop;
+        int32_t hitRight;
+        int32_t hitBottom;
+
+        inline bool isHit(int32_t x, int32_t y) const {
+            return x >= hitLeft && x <= hitRight && y >= hitTop && y <= hitBottom;
+        }
+    };
+
+    struct PointerData {
+        uint32_t id;
+        int32_t x;
+        int32_t y;
+        int32_t pressure;
+        int32_t size;
+        int32_t touchMajor;
+        int32_t touchMinor;
+        int32_t toolMajor;
+        int32_t toolMinor;
+        int32_t orientation;
+    };
+
+    struct TouchData {
+        uint32_t pointerCount;
+        PointerData pointers[MAX_POINTERS];
+        BitSet32 idBits;
+        uint32_t idToIndex[MAX_POINTER_ID + 1];
+
+        void copyFrom(const TouchData& other) {
+            pointerCount = other.pointerCount;
+            idBits = other.idBits;
+
+            for (uint32_t i = 0; i < pointerCount; i++) {
+                pointers[i] = other.pointers[i];
+                idToIndex[i] = other.idToIndex[i];
+            }
+        }
+
+        inline void clear() {
+            pointerCount = 0;
+            idBits.clear();
+        }
+    };
+
+    int32_t mAssociatedDisplayId;
+    Vector<VirtualKey> mVirtualKeys;
+
+    // Immutable configuration parameters.
+    struct Parameters {
+        bool useBadTouchFilter;
+        bool useJumpyTouchFilter;
+        bool useAveragingTouchFilter;
+    } mParameters;
+
+    // Raw axis information.
+    struct Axes {
+        RawAbsoluteAxisInfo x;
+        RawAbsoluteAxisInfo y;
+        RawAbsoluteAxisInfo pressure;
+        RawAbsoluteAxisInfo size;
+        RawAbsoluteAxisInfo touchMajor;
+        RawAbsoluteAxisInfo touchMinor;
+        RawAbsoluteAxisInfo toolMajor;
+        RawAbsoluteAxisInfo toolMinor;
+        RawAbsoluteAxisInfo orientation;
+    } mAxes;
+
+    // The surface orientation and width and height set by configureSurface().
+    int32_t mSurfaceOrientation;
+    int32_t mSurfaceWidth, mSurfaceHeight;
+
+    // Translation and scaling factors, orientation-independent.
+    int32_t mXOrigin;
+    float mXScale;
+    float mXPrecision;
+
+    int32_t mYOrigin;
+    float mYScale;
+    float mYPrecision;
+
+    int32_t mPressureOrigin;
+    float mPressureScale;
+
+    int32_t mSizeOrigin;
+    float mSizeScale;
+
+    float mOrientationScale;
+
+    // Oriented motion ranges for input device info.
+    struct OrientedRanges {
+        InputDeviceInfo::MotionRange x;
+        InputDeviceInfo::MotionRange y;
+        InputDeviceInfo::MotionRange pressure;
+        InputDeviceInfo::MotionRange size;
+        InputDeviceInfo::MotionRange touchMajor;
+        InputDeviceInfo::MotionRange touchMinor;
+        InputDeviceInfo::MotionRange toolMajor;
+        InputDeviceInfo::MotionRange toolMinor;
+        InputDeviceInfo::MotionRange orientation;
+    } mOrientedRanges;
+
+    // Oriented dimensions and precision.
+    float mOrientedSurfaceWidth, mOrientedSurfaceHeight;
+    float mOrientedXPrecision, mOrientedYPrecision;
+
+    // The touch data of the current sample being processed.
+    TouchData mCurrentTouch;
+
+    // The touch data of the previous sample that was processed.  This is updated
+    // incrementally while the current sample is being processed.
+    TouchData mLastTouch;
+
+    // The time the primary pointer last went down.
+    nsecs_t mDownTime;
+
+    struct CurrentVirtualKeyState {
+        bool down;
+        nsecs_t downTime;
+        int32_t keyCode;
+        int32_t scanCode;
+    } mCurrentVirtualKey;
+
+    // Lock for virtual key state.
+    Mutex mVirtualKeyLock; // methods use "Lvk" suffix
+
+    virtual void configureAxes();
+    virtual bool configureSurface();
+    virtual void configureVirtualKeys();
+
+    enum TouchResult {
+        // Dispatch the touch normally.
+        DISPATCH_TOUCH,
+        // Do not dispatch the touch, but keep tracking the current stroke.
+        SKIP_TOUCH,
+        // Do not dispatch the touch, and drop all information associated with the current stoke
+        // so the next movement will appear as a new down.
+        DROP_STROKE
+    };
+
+    void syncTouch(nsecs_t when, bool havePointerIds);
+
+private:
+    /* Maximum number of historical samples to average. */
+    static const uint32_t AVERAGING_HISTORY_SIZE = 5;
+
+    /* Slop distance for jumpy pointer detection.
+     * The vertical range of the screen divided by this is our epsilon value. */
+    static const uint32_t JUMPY_EPSILON_DIVISOR = 212;
+
+    /* Number of jumpy points to drop for touchscreens that need it. */
+    static const uint32_t JUMPY_TRANSITION_DROPS = 3;
+    static const uint32_t JUMPY_DROP_LIMIT = 3;
+
+    /* Maximum squared distance for averaging.
+     * If moving farther than this, turn of averaging to avoid lag in response. */
+    static const uint64_t AVERAGING_DISTANCE_LIMIT = 75 * 75;
+
+    struct AveragingTouchFilterState {
+        // Individual history tracks are stored by pointer id
+        uint32_t historyStart[MAX_POINTERS];
+        uint32_t historyEnd[MAX_POINTERS];
+        struct {
+            struct {
+                int32_t x;
+                int32_t y;
+                int32_t pressure;
+            } pointers[MAX_POINTERS];
+        } historyData[AVERAGING_HISTORY_SIZE];
+    } mAveragingTouchFilter;
+
+    struct JumpTouchFilterState {
+        uint32_t jumpyPointsDropped;
+    } mJumpyTouchFilter;
+
+    struct PointerDistanceHeapElement {
+        uint32_t currentPointerIndex : 8;
+        uint32_t lastPointerIndex : 8;
+        uint64_t distance : 48; // squared distance
+    };
+
+    void initialize();
+
+    TouchResult consumeOffScreenTouches(nsecs_t when, uint32_t policyFlags);
+    void dispatchTouches(nsecs_t when, uint32_t policyFlags);
+    void dispatchTouch(nsecs_t when, uint32_t policyFlags, TouchData* touch,
+            BitSet32 idBits, uint32_t changedId, int32_t motionEventAction);
+
+    bool isPointInsideSurface(int32_t x, int32_t y);
+    const VirtualKey* findVirtualKeyHitLvk(int32_t x, int32_t y);
+
+    bool applyBadTouchFilter();
+    bool applyJumpyTouchFilter();
+    void applyAveragingTouchFilter();
+    void calculatePointerIds();
+};
+
+
+class SingleTouchInputMapper : public TouchInputMapper {
+public:
+    SingleTouchInputMapper(InputDevice* device, int32_t associatedDisplayId);
+    virtual ~SingleTouchInputMapper();
+
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+protected:
+    virtual void configureAxes();
+
+private:
+    struct Accumulator {
+        enum {
+            FIELD_BTN_TOUCH = 1,
+            FIELD_ABS_X = 2,
+            FIELD_ABS_Y = 4,
+            FIELD_ABS_PRESSURE = 8,
+            FIELD_ABS_TOOL_WIDTH = 16
+        };
+
+        uint32_t fields;
+
+        bool btnTouch;
+        int32_t absX;
+        int32_t absY;
+        int32_t absPressure;
+        int32_t absToolWidth;
+
+        inline void clear() {
+            fields = 0;
+        }
+
+        inline bool isDirty() {
+            return fields != 0;
+        }
+    } mAccumulator;
+
+    bool mDown;
+    int32_t mX;
+    int32_t mY;
+    int32_t mPressure;
+    int32_t mSize;
+
+    void initialize();
+
+    void sync(nsecs_t when);
+};
+
+
+class MultiTouchInputMapper : public TouchInputMapper {
+public:
+    MultiTouchInputMapper(InputDevice* device, int32_t associatedDisplayId);
+    virtual ~MultiTouchInputMapper();
+
+    virtual void reset();
+    virtual void process(const RawEvent* rawEvent);
+
+protected:
+    virtual void configureAxes();
+
+private:
+    struct Accumulator {
+        enum {
+            FIELD_ABS_MT_POSITION_X = 1,
+            FIELD_ABS_MT_POSITION_Y = 2,
+            FIELD_ABS_MT_TOUCH_MAJOR = 4,
+            FIELD_ABS_MT_TOUCH_MINOR = 8,
+            FIELD_ABS_MT_WIDTH_MAJOR = 16,
+            FIELD_ABS_MT_WIDTH_MINOR = 32,
+            FIELD_ABS_MT_ORIENTATION = 64,
+            FIELD_ABS_MT_TRACKING_ID = 128
+        };
+
+        uint32_t pointerCount;
+        struct Pointer {
+            uint32_t fields;
+
+            int32_t absMTPositionX;
+            int32_t absMTPositionY;
+            int32_t absMTTouchMajor;
+            int32_t absMTTouchMinor;
+            int32_t absMTWidthMajor;
+            int32_t absMTWidthMinor;
+            int32_t absMTOrientation;
+            int32_t absMTTrackingId;
+
+            inline void clear() {
+                fields = 0;
+            }
+        } pointers[MAX_POINTERS + 1]; // + 1 to remove the need for extra range checks
+
+        inline void clear() {
+            pointerCount = 0;
+            pointers[0].clear();
+        }
+
+        inline bool isDirty() {
+            return pointerCount != 0;
+        }
+    } mAccumulator;
+
+    void initialize();
+
+    void sync(nsecs_t when);
+};
+
 } // namespace android
 
 #endif // _UI_INPUT_READER_H