Merge "DockObserver: Watch for exceptions in LocationManger.isProviderEnabled()."
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 1b5b3e4..02961f0 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -87,7 +87,7 @@
     </string-array>
 
     <!-- Regex array of allowable upstream ifaces for tethering - for example if you want
-         tethering on your a new interface called "foo2" add "foo\\d" here -->
+         tethering on a new interface called "foo2" add <item>"foo\\d"</item> to the array -->
     <string-array translatable="false" name="config_tether_upstream_regexs">
     </string-array>
 
diff --git a/core/tests/coretests/src/android/text/StaticLayoutTest.java b/core/tests/coretests/src/android/text/StaticLayoutTest.java
index 7511ec1..1f58a2c 100644
--- a/core/tests/coretests/src/android/text/StaticLayoutTest.java
+++ b/core/tests/coretests/src/android/text/StaticLayoutTest.java
@@ -26,6 +26,11 @@
 
 /**
  * Tests StaticLayout vertical metrics behavior.
+ * 
+ * Requires disabling access checks in the vm since this calls package-private
+ * APIs.
+ * 
+ * @Suppress
  */
 public class StaticLayoutTest extends TestCase {
 
@@ -33,7 +38,7 @@
      * Basic test showing expected behavior and relationship between font
      * metrics and line metrics.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters1() {
         LayoutBuilder b = builder();
         FontMetricsInt fmi = b.paint.getFontMetricsInt();
@@ -59,7 +64,7 @@
      * Basic test showing effect of includePad = true with 1 line.
      * Top and bottom padding are affected, as is the line descent and height.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters2() {
         LayoutBuilder b = builder()
             .setIncludePad(true);
@@ -74,7 +79,7 @@
      * Basic test showing effect of includePad = true wrapping to 2 lines.
      * Ascent of top line and descent of bottom line are affected.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters3() {
         LayoutBuilder b = builder()
             .setIncludePad(true)
@@ -91,7 +96,7 @@
      * Basic test showing effect of includePad = true wrapping to 3 lines.
      * First line ascent is top, bottom line descent is bottom.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters4() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
@@ -111,7 +116,7 @@
      * large text. See effect of leading. Currently, we don't expect there to
      * even be non-zero leading.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters5() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
@@ -138,7 +143,7 @@
      * Basic test showing effect of includePad = true, spacingAdd = 2, wrapping
      * to 3 lines.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters6() {
         int spacingAdd = 2; // int so expressions return int
         LayoutBuilder b = builder()
@@ -159,7 +164,7 @@
      * Basic test showing effect of includePad = true, spacingAdd = 2,
      * spacingMult = 1.5, wrapping to 3 lines.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters7() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
@@ -181,7 +186,7 @@
      * Basic test showing effect of includePad = true, spacingAdd = 0,
      * spacingMult = 0.8 when wrapping to 3 lines.
      */
-    @SmallTest
+    //@SmallTest
     public void testGetters8() {
         LayoutBuilder b = builder()
             .setText("This is a longer test")
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index c4d4f99..57192a5 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -604,8 +604,11 @@
 
     // figure out the kinds of events the device reports
     
-    // See if this is a keyboard, and classify it.
-    uint8_t key_bitmask[(KEY_MAX+1)/8];
+    // See if this is a keyboard, and classify it.  Note that we only
+    // consider up through the function keys; we don't want to include
+    // ones after that (play cd etc) so we don't mistakenly consider a
+    // controller to be a keyboard.
+    uint8_t key_bitmask[(KEY_PLAYCD+1)/8];
     memset(key_bitmask, 0, sizeof(key_bitmask));
     LOGV("Getting keys...");
     if (ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(key_bitmask)), key_bitmask) >= 0) {
@@ -702,22 +705,20 @@
         device->layoutMap->load(keylayoutFilename);
 
         // tell the world about the devname (the descriptive name)
-        int32_t publicID;
-        if (!mHaveFirstKeyboard && !defaultKeymap) {
-            publicID = 0;
+        if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
             // the built-in keyboard has a well-known device ID of 0,
             // this device better not go away.
             mHaveFirstKeyboard = true;
             mFirstKeyboardId = device->id;
+            property_set("hw.keyboards.0.devname", name);
         } else {
-            publicID = device->id;
             // ensure mFirstKeyboardId is set to -something-.
             if (mFirstKeyboardId == 0) {
                 mFirstKeyboardId = device->id;
             }
         }
         char propName[100];
-        sprintf(propName, "hw.keyboards.%u.devname", publicID);
+        sprintf(propName, "hw.keyboards.%u.devname", device->id);
         property_set(propName, name);
 
         // 'Q' key support = cheap test of whether this is an alpha-capable kbd
@@ -734,8 +735,8 @@
             device->classes |= CLASS_DPAD;
         }
         
-        LOGI("New keyboard: publicID=%d device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
-                publicID, device->id, name, propName, keylayoutFilename);
+        LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
+                device->id, name, propName, keylayoutFilename);
     }
 
     LOGI("New device: path=%s name=%s id=0x%x (of 0x%x) index=%d fd=%d classes=0x%x\n",
@@ -808,18 +809,15 @@
             device->next = mClosingDevices;
             mClosingDevices = device;
 
-            uint32_t publicID;
             if (device->id == mFirstKeyboardId) {
                 LOGW("built-in keyboard device %s (id=%d) is closing! the apps will not like this",
                         device->path.string(), mFirstKeyboardId);
                 mFirstKeyboardId = 0;
-                publicID = 0;
-            } else {
-                publicID = device->id;
+                property_set("hw.keyboards.0.devname", NULL);
             }
             // clear the property
             char propName[100];
-            sprintf(propName, "hw.keyboards.%u.devname", publicID);
+            sprintf(propName, "hw.keyboards.%u.devname", device->id);
             property_set(propName, NULL);
             return 0;
         }
diff --git a/services/java/com/android/server/InputDevice.java b/services/java/com/android/server/InputDevice.java
index 1c18d6f..d5e94ec 100644
--- a/services/java/com/android/server/InputDevice.java
+++ b/services/java/com/android/server/InputDevice.java
@@ -22,6 +22,8 @@
 import android.view.Surface;
 import android.view.WindowManagerPolicy;
 
+import java.io.PrintWriter;
+
 public class InputDevice {
     static final boolean DEBUG_POINTERS = false;
     static final boolean DEBUG_HACKS = false;
@@ -58,6 +60,7 @@
         float yMoveScale;
         MotionEvent currentMove = null;
         boolean changed = false;
+        boolean everChanged = false;
         long mDownTime = 0;
         
         // The currently assigned pointer IDs, corresponding to the last data.
@@ -103,6 +106,56 @@
         int mAddingPointerOffset = 0;
         final boolean[] mDown = new boolean[MAX_POINTERS];
         
+        void dumpIntArray(PrintWriter pw, int[] array) {
+            pw.print("[");
+            for (int i=0; i<array.length; i++) {
+                if (i > 0) pw.print(", ");
+                pw.print(array[i]);
+            }
+            pw.print("]");
+        }
+        
+        void dumpBooleanArray(PrintWriter pw, boolean[] array) {
+            pw.print("[");
+            for (int i=0; i<array.length; i++) {
+                if (i > 0) pw.print(", ");
+                pw.print(array[i] ? "true" : "false");
+            }
+            pw.print("]");
+        }
+        
+        void dump(PrintWriter pw, String prefix) {
+            pw.print(prefix); pw.print("xPrecision="); pw.print(xPrecision);
+                    pw.print(" yPrecision="); pw.println(yPrecision);
+            pw.print(prefix); pw.print("xMoveScale="); pw.print(xMoveScale);
+                    pw.print(" yMoveScale="); pw.println(yMoveScale);
+            if (currentMove != null) {
+                pw.print(prefix); pw.print("currentMove="); pw.println(currentMove);
+            }
+            if (changed || mDownTime != 0) {
+                pw.print(prefix); pw.print("changed="); pw.print(changed);
+                        pw.print(" mDownTime="); pw.println(mDownTime);
+            }
+            pw.print(prefix); pw.print("mPointerIds="); dumpIntArray(pw, mPointerIds);
+                    pw.println("");
+            if (mSkipLastPointers || mLastNumPointers != 0) {
+                pw.print(prefix); pw.print("mSkipLastPointers="); pw.print(mSkipLastPointers);
+                        pw.print(" mLastNumPointers="); pw.println(mLastNumPointers);
+                pw.print(prefix); pw.print("mLastData="); dumpIntArray(pw, mLastData);
+                        pw.println("");
+            }
+            if (mNextNumPointers != 0) {
+                pw.print(prefix); pw.print("mNextNumPointers="); pw.println(mNextNumPointers);
+                pw.print(prefix); pw.print("mNextData="); dumpIntArray(pw, mNextData);
+                        pw.println("");
+            }
+            pw.print(prefix); pw.print("mDroppedBadPoint=");
+                    dumpBooleanArray(pw, mDroppedBadPoint); pw.println("");
+            pw.print(prefix); pw.print("mAddingPointerOffset="); pw.println(mAddingPointerOffset);
+            pw.print(prefix); pw.print("mDown=");
+                    dumpBooleanArray(pw, mDown); pw.println("");
+        }
+        
         MotionState(int mx, int my) {
             xPrecision = mx;
             yPrecision = my;
@@ -775,6 +828,14 @@
         int range;
         int flat;
         int fuzz;
+        
+        final void dump(PrintWriter pw) {
+            pw.print("minValue="); pw.print(minValue);
+            pw.print(" maxValue="); pw.print(maxValue);
+            pw.print(" range="); pw.print(range);
+            pw.print(" flat="); pw.print(flat);
+            pw.print(" fuzz="); pw.print(fuzz);
+        }
     };
     
     InputDevice(int _id, int _classes, String _name,
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 0535d4c..a08258a 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -22,6 +22,7 @@
 import android.os.LatencyTimer;
 import android.os.PowerManager;
 import android.os.SystemClock;
+import android.os.SystemProperties;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -43,6 +44,7 @@
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStreamReader;
+import java.io.PrintWriter;
 import java.util.ArrayList;
 
 public abstract class KeyInputQueue {
@@ -738,6 +740,7 @@
                                 
                                 InputDevice.MotionState ms = di.mAbs;
                                 if (ms.changed) {
+                                    ms.everChanged = true;
                                     ms.changed = false;
                                     
                                     if ((classes&(RawInputEvent.CLASS_TOUCHSCREEN
@@ -809,6 +812,7 @@
                                 
                                 ms = di.mRel;
                                 if (ms.changed) {
+                                    ms.everChanged = true;
                                     ms.changed = false;
                                     
                                     me = ms.generateRelMotion(di, curTime,
@@ -1280,4 +1284,91 @@
         return null;
     }
     private static native boolean readEvent(RawInputEvent outEvent);
+    
+    void dump(PrintWriter pw, String prefix) {
+        synchronized (mFirst) {
+            for (int i=0; i<mDevices.size(); i++) {
+                InputDevice dev = mDevices.valueAt(i);
+                pw.print(prefix); pw.print("Device #");
+                        pw.print(mDevices.keyAt(i)); pw.print(" ");
+                        pw.print(dev.name); pw.print(" (classes=0x");
+                        pw.print(Integer.toHexString(dev.classes));
+                        pw.println("):");
+                pw.print(prefix); pw.print("  mKeyDownTime=");
+                        pw.print(dev.mKeyDownTime); pw.print(" mMetaKeysState=");
+                        pw.println(dev.mMetaKeysState);
+                if (dev.absX != null) {
+                    pw.print(prefix); pw.print("  absX: "); dev.absX.dump(pw);
+                            pw.println("");
+                }
+                if (dev.absY != null) {
+                    pw.print(prefix); pw.print("  absY: "); dev.absY.dump(pw);
+                            pw.println("");
+                }
+                if (dev.absPressure != null) {
+                    pw.print(prefix); pw.print("  absPressure: ");
+                            dev.absPressure.dump(pw); pw.println("");
+                }
+                if (dev.absSize != null) {
+                    pw.print(prefix); pw.print("  absSize: ");
+                            dev.absSize.dump(pw); pw.println("");
+                }
+                if (dev.mAbs.everChanged) {
+                    pw.print(prefix); pw.println("  mAbs:");
+                    dev.mAbs.dump(pw, prefix + "    ");
+                }
+                if (dev.mRel.everChanged) {
+                    pw.print(prefix); pw.println("  mRel:");
+                    dev.mRel.dump(pw, prefix + "    ");
+                }
+            }
+            pw.println(" ");
+            for (int i=0; i<mIgnoredDevices.size(); i++) {
+                InputDevice dev = mIgnoredDevices.valueAt(i);
+                pw.print(prefix); pw.print("Ignored Device #");
+                        pw.print(mIgnoredDevices.keyAt(i)); pw.print(" ");
+                        pw.print(dev.name); pw.print(" (classes=0x");
+                        pw.print(Integer.toHexString(dev.classes));
+                        pw.println(")");
+            }
+            pw.println(" ");
+            for (int i=0; i<mVirtualKeys.size(); i++) {
+                VirtualKey vk = mVirtualKeys.get(i);
+                pw.print(prefix); pw.print("Virtual Key #");
+                        pw.print(i); pw.println(":");
+                pw.print(prefix); pw.print("  scancode="); pw.println(vk.scancode);
+                pw.print(prefix); pw.print("  centerx="); pw.print(vk.centerx);
+                        pw.print(" centery="); pw.print(vk.centery);
+                        pw.print(" width="); pw.print(vk.width);
+                        pw.print(" height="); pw.println(vk.height);
+                pw.print(prefix); pw.print("  hitLeft="); pw.print(vk.hitLeft);
+                        pw.print(" hitTop="); pw.print(vk.hitTop);
+                        pw.print(" hitRight="); pw.print(vk.hitRight);
+                        pw.print(" hitBottom="); pw.println(vk.hitBottom);
+                if (vk.lastDevice != null) {
+                    pw.print(prefix); pw.print("  lastDevice=#");
+                            pw.println(vk.lastDevice.id);
+                }
+                if (vk.lastKeycode != 0) {
+                    pw.print(prefix); pw.print("  lastKeycode=");
+                            pw.println(vk.lastKeycode);
+                }
+            }
+            pw.println(" ");
+            pw.print(prefix); pw.print("  Default keyboard: ");
+                    pw.println(SystemProperties.get("hw.keyboards.0.devname"));
+            pw.print(prefix); pw.print("  mGlobalMetaState=");
+                    pw.print(mGlobalMetaState); pw.print(" mHaveGlobalMetaState=");
+                    pw.println(mHaveGlobalMetaState);
+            pw.print(prefix); pw.print("  mDisplayWidth=");
+                    pw.print(mDisplayWidth); pw.print(" mDisplayHeight=");
+                    pw.println(mDisplayHeight);
+            pw.print(prefix); pw.print("  mOrientation=");
+                    pw.println(mOrientation);
+            if (mPressedVirtualKey != null) {
+                pw.print(prefix); pw.print("  mPressedVirtualKey.scancode=");
+                        pw.println(mPressedVirtualKey.scancode);
+            }
+        }
+    }
 }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 67eba3d..8781263 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -10851,6 +10851,10 @@
             return;
         }
 
+        pw.println("Input State:");
+        mQueue.dump(pw, "  ");
+        pw.println(" ");
+        
         synchronized(mWindowMap) {
             pw.println("Current Window Manager state:");
             for (int i=mWindows.size()-1; i>=0; i--) {
@@ -11014,7 +11018,7 @@
             if (mDimAnimator != null) {
                 mDimAnimator.printTo(pw);
             } else {
-                pw.print( "  no DimAnimator ");
+                pw.println( "  no DimAnimator ");
             }
             pw.print("  mInputMethodAnimLayerAdjustment=");
                     pw.print(mInputMethodAnimLayerAdjustment);