auto import from //depot/cupcake/@135843
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
new file mode 100644
index 0000000..7b8a2a4
--- /dev/null
+++ b/services/java/com/android/server/InputDevice.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright (C) 2007 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.
+ */
+
+package com.android.server;
+
+import android.util.Log;
+import android.view.Display;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.WindowManagerPolicy;
+
+public class InputDevice {
+    /** Amount that trackball needs to move in order to generate a key event. */
+    static final int TRACKBALL_MOVEMENT_THRESHOLD = 6;
+
+    final int id;
+    final int classes;
+    final String name;
+    final AbsoluteInfo absX;
+    final AbsoluteInfo absY;
+    final AbsoluteInfo absPressure;
+    final AbsoluteInfo absSize;
+    
+    long mDownTime = 0;
+    int mMetaKeysState = 0;
+    
+    final MotionState mAbs = new MotionState(0, 0);
+    final MotionState mRel = new MotionState(TRACKBALL_MOVEMENT_THRESHOLD,
+            TRACKBALL_MOVEMENT_THRESHOLD);
+    
+    static class MotionState {
+        int xPrecision;
+        int yPrecision;
+        float xMoveScale;
+        float yMoveScale;
+        MotionEvent currentMove = null;
+        boolean changed = false;
+        boolean down = false;
+        boolean lastDown = false;
+        long downTime = 0;
+        int x = 0;
+        int y = 0;
+        int pressure = 1;
+        int size = 0;
+        
+        MotionState(int mx, int my) {
+            xPrecision = mx;
+            yPrecision = my;
+            xMoveScale = mx != 0 ? (1.0f/mx) : 1.0f;
+            yMoveScale = my != 0 ? (1.0f/my) : 1.0f;
+        }
+        
+        MotionEvent generateMotion(InputDevice device, long curTime,
+                boolean isAbs, Display display, int orientation,
+                int metaState) {
+            if (!changed) {
+                return null;
+            }
+            
+            float scaledX = x;
+            float scaledY = y;
+            float temp;
+            float scaledPressure = 1.0f;
+            float scaledSize = 0;
+            int edgeFlags = 0;
+            if (isAbs) {
+                int w = display.getWidth()-1;
+                int h = display.getHeight()-1;
+                if (orientation == Surface.ROTATION_90
+                        || orientation == Surface.ROTATION_270) {
+                    int tmp = w;
+                    w = h;
+                    h = tmp;
+                }
+                if (device.absX != null) {
+                    scaledX = ((scaledX-device.absX.minValue)
+                                / device.absX.range) * w;
+                }
+                if (device.absY != null) {
+                    scaledY = ((scaledY-device.absY.minValue)
+                                / device.absY.range) * h;
+                }
+                if (device.absPressure != null) {
+                    scaledPressure = 
+                        ((pressure-device.absPressure.minValue)
+                                / (float)device.absPressure.range);
+                }
+                if (device.absSize != null) {
+                    scaledSize = 
+                        ((size-device.absSize.minValue)
+                                / (float)device.absSize.range);
+                }
+                switch (orientation) {
+                    case Surface.ROTATION_90:
+                        temp = scaledX;
+                        scaledX = scaledY;
+                        scaledY = w-temp;
+                        break;
+                    case Surface.ROTATION_180:
+                        scaledX = w-scaledX;
+                        scaledY = h-scaledY;
+                        break;
+                    case Surface.ROTATION_270:
+                        temp = scaledX;
+                        scaledX = h-scaledY;
+                        scaledY = temp;
+                        break;
+                }
+
+                if (scaledX == 0) {
+                    edgeFlags += MotionEvent.EDGE_LEFT;
+                } else if (scaledX == display.getWidth() - 1.0f) {
+                    edgeFlags += MotionEvent.EDGE_RIGHT;
+                }
+                
+                if (scaledY == 0) {
+                    edgeFlags += MotionEvent.EDGE_TOP;
+                } else if (scaledY == display.getHeight() - 1.0f) {
+                    edgeFlags += MotionEvent.EDGE_BOTTOM;
+                }
+                
+            } else {
+                scaledX *= xMoveScale;
+                scaledY *= yMoveScale;
+                switch (orientation) {
+                    case Surface.ROTATION_90:
+                        temp = scaledX;
+                        scaledX = scaledY;
+                        scaledY = -temp;
+                        break;
+                    case Surface.ROTATION_180:
+                        scaledX = -scaledX;
+                        scaledY = -scaledY;
+                        break;
+                    case Surface.ROTATION_270:
+                        temp = scaledX;
+                        scaledX = -scaledY;
+                        scaledY = temp;
+                        break;
+                }
+            }
+            
+            changed = false;
+            if (down != lastDown) {
+                int action;
+                lastDown = down;
+                if (down) {
+                    action = MotionEvent.ACTION_DOWN;
+                    downTime = curTime;
+                } else {
+                    action = MotionEvent.ACTION_UP;
+                }
+                currentMove = null;
+                if (!isAbs) {
+                    x = y = 0;
+                }
+                return MotionEvent.obtain(downTime, curTime, action,
+                        scaledX, scaledY, scaledPressure, scaledSize, metaState,
+                        xPrecision, yPrecision, device.id, edgeFlags);
+            } else {
+                if (currentMove != null) {
+                    if (false) Log.i("InputDevice", "Adding batch x=" + scaledX
+                            + " y=" + scaledY + " to " + currentMove);
+                    currentMove.addBatch(curTime, scaledX, scaledY,
+                            scaledPressure, scaledSize, metaState);
+                    if (WindowManagerPolicy.WATCH_POINTER) {
+                        Log.i("KeyInputQueue", "Updating: " + currentMove);
+                    }
+                    return null;
+                }
+                MotionEvent me = MotionEvent.obtain(downTime, curTime,
+                        MotionEvent.ACTION_MOVE, scaledX, scaledY,
+                        scaledPressure, scaledSize, metaState,
+                        xPrecision, yPrecision, device.id, edgeFlags);
+                currentMove = me;
+                return me;
+            }
+        }
+    }
+    
+    static class AbsoluteInfo {
+        int minValue;
+        int maxValue;
+        int range;
+        int flat;
+        int fuzz;
+    };
+    
+    InputDevice(int _id, int _classes, String _name,
+            AbsoluteInfo _absX, AbsoluteInfo _absY,
+            AbsoluteInfo _absPressure, AbsoluteInfo _absSize) {
+        id = _id;
+        classes = _classes;
+        name = _name;
+        absX = _absX;
+        absY = _absY;
+        absPressure = _absPressure;
+        absSize = _absSize;
+    }
+};