Merge "Fix typos in JSON documentation."
diff --git a/api/current.xml b/api/current.xml
index b51242b..914dc26 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -196530,6 +196530,39 @@
  visibility="public"
 >
 </method>
+<method name="isCapsLockLatched"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isCtrlPressed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="isFunctionPressed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isLongPress"
  return="boolean"
  abstract="false"
@@ -196541,6 +196574,17 @@
  visibility="public"
 >
 </method>
+<method name="isMetaPressed"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isModifierKey"
  return="boolean"
  abstract="false"
@@ -196554,6 +196598,17 @@
 <parameter name="keyCode" type="int">
 </parameter>
 </method>
+<method name="isNumLockLatched"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isPrintingKey"
  return="boolean"
  abstract="false"
@@ -196565,6 +196620,17 @@
  visibility="public"
 >
 </method>
+<method name="isScrollLockLatched"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isShiftPressed"
  return="boolean"
  abstract="false"
@@ -196986,6 +197052,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_BREAK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="121"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_BUTTON_A"
  type="int"
  transient="false"
@@ -197184,6 +197261,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_CAPS_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="115"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_CLEAR"
  type="int"
  transient="false"
@@ -197206,6 +197294,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_CTRL_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="113"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_CTRL_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="114"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_D"
  type="int"
  transient="false"
@@ -197338,6 +197448,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_ESCAPE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="111"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_EXPLORER"
  type="int"
  transient="false"
@@ -197360,6 +197481,138 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_F1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F10"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="140"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F11"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="141"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F12"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="142"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="132"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="133"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="134"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="135"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="136"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="137"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="138"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_F9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="139"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_FOCUS"
  type="int"
  transient="false"
@@ -197371,6 +197624,39 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_FORWARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="125"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_FORWARD_DEL"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="112"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_FUNCTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="119"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_G"
  type="int"
  transient="false"
@@ -197437,6 +197723,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_INSERT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="124"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_J"
  type="int"
  transient="false"
@@ -197492,6 +197789,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MEDIA_CLOSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="128"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_MEDIA_EJECT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="129"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MEDIA_FAST_FORWARD"
  type="int"
  transient="false"
@@ -197514,6 +197833,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MEDIA_PAUSE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="127"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_MEDIA_PLAY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="126"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MEDIA_PLAY_PAUSE"
  type="int"
  transient="false"
@@ -197536,6 +197877,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MEDIA_RECORD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="130"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MEDIA_REWIND"
  type="int"
  transient="false"
@@ -197569,6 +197921,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_META_LEFT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="117"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_META_RIGHT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="118"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MINUS"
  type="int"
  transient="false"
@@ -197580,6 +197954,28 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_MOVE_END"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="123"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_MOVE_HOME"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="122"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_MUTE"
  type="int"
  transient="false"
@@ -197624,6 +198020,237 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_NUMPAD_0"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_1"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="145"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_2"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="146"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_3"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="147"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_4"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="148"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_5"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="149"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_6"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="150"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_7"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="151"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_8"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_9"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="153"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_ADD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="157"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_COMMA"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="159"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_DIVIDE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="154"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_DOT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="158"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_ENTER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="160"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_EQUALS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="161"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_LEFT_PAREN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="162"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_MULTIPLY"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="155"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_RIGHT_PAREN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="163"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUMPAD_SUBTRACT"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="156"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="KEYCODE_NUM_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="143"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_O"
  type="int"
  transient="false"
@@ -197767,6 +198394,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_SCROLL_LOCK"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="116"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_SEARCH"
  type="int"
  transient="false"
@@ -197888,6 +198526,17 @@
  visibility="public"
 >
 </field>
+<field name="KEYCODE_SYSRQ"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="120"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="KEYCODE_T"
  type="int"
  transient="false"
@@ -198053,6 +198702,116 @@
  visibility="public"
 >
 </field>
+<field name="META_CAPS_LOCK_LATCHED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="1048576"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_LEFT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8192"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4096"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_CTRL_RIGHT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16384"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_FUNCTION_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_LEFT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="131072"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="65536"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_META_RIGHT_ON"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="262144"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_NUM_LOCK_LATCHED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="2097152"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="META_SCROLL_LOCK_LATCHED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="4194304"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="META_SHIFT_LEFT_ON"
  type="int"
  transient="false"
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 54ac906..dd25eaa 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -1145,12 +1145,9 @@
         float h2 = isLevelBoundary(point) ?
                     getSecondaryHorizontal(point) - 0.5f : h1;
 
-        int caps = TextKeyListener.getMetaState(editingBuffer,
-                                                KeyEvent.META_SHIFT_ON) |
-                   TextKeyListener.getMetaState(editingBuffer,
-                                                TextKeyListener.META_SELECTING);
-        int fn = TextKeyListener.getMetaState(editingBuffer,
-                                              KeyEvent.META_ALT_ON);
+        int caps = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SHIFT_ON) |
+                   TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_SELECTING);
+        int fn = TextKeyListener.getMetaState(editingBuffer, TextKeyListener.META_ALT_ON);
         int dist = 0;
 
         if (caps != 0 || fn != 0) {
diff --git a/core/java/android/text/method/ArrowKeyMovementMethod.java b/core/java/android/text/method/ArrowKeyMovementMethod.java
index 220e023..0d012d6 100644
--- a/core/java/android/text/method/ArrowKeyMovementMethod.java
+++ b/core/java/android/text/method/ArrowKeyMovementMethod.java
@@ -30,12 +30,12 @@
 
 public class ArrowKeyMovementMethod implements MovementMethod {
     private boolean isCap(Spannable buffer) {
-        return ((MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_SHIFT_ON) == 1) ||
+        return ((MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SHIFT_ON) == 1) ||
                 (MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_SELECTING) != 0));
     }
 
     private boolean isAlt(Spannable buffer) {
-        return MetaKeyKeyListener.getMetaState(buffer, KeyEvent.META_ALT_ON) == 1;
+        return MetaKeyKeyListener.getMetaState(buffer, MetaKeyKeyListener.META_ALT_ON) == 1;
     }
 
     private boolean up(TextView widget, Spannable buffer) {
diff --git a/core/java/android/text/method/DialerKeyListener.java b/core/java/android/text/method/DialerKeyListener.java
index 584e83f..1e1812a 100644
--- a/core/java/android/text/method/DialerKeyListener.java
+++ b/core/java/android/text/method/DialerKeyListener.java
@@ -56,7 +56,7 @@
          * Prefer number if no meta key is active, or if it produces something
          * valid and the meta lookup does not.
          */
-        if ((meta & (KeyEvent.META_ALT_ON | KeyEvent.META_SHIFT_ON)) == 0) {
+        if ((meta & (MetaKeyKeyListener.META_ALT_ON | MetaKeyKeyListener.META_SHIFT_ON)) == 0) {
             if (number != 0) {
                 return number;
             }
diff --git a/core/java/android/text/method/MetaKeyKeyListener.java b/core/java/android/text/method/MetaKeyKeyListener.java
index 61ec67f..e7b36d7 100644
--- a/core/java/android/text/method/MetaKeyKeyListener.java
+++ b/core/java/android/text/method/MetaKeyKeyListener.java
@@ -16,9 +16,12 @@
 
 package android.text.method;
 
+import android.text.Editable;
+import android.text.NoCopySpan;
+import android.text.Spannable;
+import android.text.Spanned;
 import android.view.KeyEvent;
 import android.view.View;
-import android.text.*;
 
 /**
  * This base class encapsulates the behavior for handling the meta keys
@@ -28,38 +31,58 @@
  */
 
 public abstract class MetaKeyKeyListener {
+    /**
+     * Flag that indicates that the SHIFT key is on.
+     * Value equals {@link KeyEvent#META_SHIFT_ON}.
+     */
     public static final int META_SHIFT_ON = KeyEvent.META_SHIFT_ON;
+    /**
+     * Flag that indicates that the ALT key is on.
+     * Value equals {@link KeyEvent#META_ALT_ON}.
+     */
     public static final int META_ALT_ON = KeyEvent.META_ALT_ON;
+    /**
+     * Flag that indicates that the SYM key is on.
+     * Value equals {@link KeyEvent#META_SYM_ON}.
+     */
     public static final int META_SYM_ON = KeyEvent.META_SYM_ON;
-
-    private static final int LOCKED_SHIFT = 8;
     
-    public static final int META_CAP_LOCKED = KeyEvent.META_SHIFT_ON << LOCKED_SHIFT;
-    public static final int META_ALT_LOCKED = KeyEvent.META_ALT_ON << LOCKED_SHIFT;
-    public static final int META_SYM_LOCKED = KeyEvent.META_SYM_ON << LOCKED_SHIFT;
+    /**
+     * Flag that indicates that the SHIFT key is locked in CAPS mode.
+     */
+    public static final int META_CAP_LOCKED = KeyEvent.META_CAP_LOCKED;
+    /**
+     * Flag that indicates that the ALT key is locked.
+     */
+    public static final int META_ALT_LOCKED = KeyEvent.META_ALT_LOCKED;
+    /**
+     * Flag that indicates that the SYM key is locked.
+     */
+    public static final int META_SYM_LOCKED = KeyEvent.META_SYM_LOCKED;
 
     /**
      * @hide pending API review
      */
-    public static final int META_SELECTING = 1 << 16;
+    public static final int META_SELECTING = KeyEvent.META_SELECTING;
 
-    private static final int USED_SHIFT = 24;
-    
-    private static final long META_CAP_USED = ((long)KeyEvent.META_SHIFT_ON) << USED_SHIFT;
-    private static final long META_ALT_USED = ((long)KeyEvent.META_ALT_ON) << USED_SHIFT;
-    private static final long META_SYM_USED = ((long)KeyEvent.META_SYM_ON) << USED_SHIFT;
+    private static final int META_SHIFT_ON_AND_LOCKED = META_SHIFT_ON | META_CAP_LOCKED;
+    private static final int META_ALT_ON_AND_LOCKED = META_ALT_ON | META_ALT_LOCKED;
+    private static final int META_SYM_ON_AND_LOCKED = META_SYM_ON | META_SYM_LOCKED;
 
-    private static final int PRESSED_SHIFT = 32;
+    // These bits are privately used by the meta key key listener.
+    // They are deliberately assigned values outside of the representable range of an 'int'
+    // so as not to conflict with any meta key states publicly defined by KeyEvent.
+    private static final long META_CAP_USED = 1L << 32;
+    private static final long META_ALT_USED = 1L << 33;
+    private static final long META_SYM_USED = 1L << 34;
     
-    private static final long META_CAP_PRESSED = ((long)KeyEvent.META_SHIFT_ON) << PRESSED_SHIFT;
-    private static final long META_ALT_PRESSED = ((long)KeyEvent.META_ALT_ON) << PRESSED_SHIFT;
-    private static final long META_SYM_PRESSED = ((long)KeyEvent.META_SYM_ON) << PRESSED_SHIFT;
-
-    private static final int RELEASED_SHIFT = 40;
+    private static final long META_CAP_PRESSED = 1L << 40;
+    private static final long META_ALT_PRESSED = 1L << 41;
+    private static final long META_SYM_PRESSED = 1L << 42;
     
-    private static final long META_CAP_RELEASED = ((long)KeyEvent.META_SHIFT_ON) << RELEASED_SHIFT;
-    private static final long META_ALT_RELEASED = ((long)KeyEvent.META_ALT_ON) << RELEASED_SHIFT;
-    private static final long META_SYM_RELEASED = ((long)KeyEvent.META_SYM_ON) << RELEASED_SHIFT;
+    private static final long META_CAP_RELEASED = 1L << 48;
+    private static final long META_ALT_RELEASED = 1L << 49;
+    private static final long META_SYM_RELEASED = 1L << 50;
 
     private static final long META_SHIFT_MASK = META_SHIFT_ON
             | META_CAP_LOCKED | META_CAP_USED
@@ -306,15 +329,14 @@
      * (arrow keys, for example) and you handle a key.
      */
     public static long resetLockedMeta(long state) {
-        state = resetLock(state, META_SHIFT_ON, META_SHIFT_MASK);
-        state = resetLock(state, META_ALT_ON, META_ALT_MASK);
-        state = resetLock(state, META_SYM_ON, META_SYM_MASK);
-        return state;
-    }
-
-    private static long resetLock(long state, int what, long mask) {
-        if ((state&(((long)what)<<LOCKED_SHIFT)) != 0) {
-            state &= ~mask;
+        if ((state & META_CAP_LOCKED) != 0) {
+            state &= ~META_SHIFT_MASK;
+        }
+        if ((state & META_ALT_LOCKED) != 0) {
+            state &= ~META_ALT_MASK;
+        }
+        if ((state & META_SYM_LOCKED) != 0) {
+            state &= ~META_SYM_MASK;
         }
         return state;
     }
@@ -332,9 +354,27 @@
      *         or locked meta key.
      */
     public static final int getMetaState(long state) {
-        return getActive(state, META_SHIFT_ON, META_SHIFT_ON, META_CAP_LOCKED) |
-               getActive(state, META_ALT_ON, META_ALT_ON, META_ALT_LOCKED) |
-               getActive(state, META_SYM_ON, META_SYM_ON, META_SYM_LOCKED);
+        int result = 0;
+
+        if ((state & META_CAP_LOCKED) != 0) {
+            result |= META_CAP_LOCKED;
+        } else if ((state & META_SHIFT_ON) != 0) {
+            result |= META_SHIFT_ON;
+        }
+
+        if ((state & META_ALT_LOCKED) != 0) {
+            result |= META_ALT_LOCKED;
+        } else if ((state & META_ALT_ON) != 0) {
+            result |= META_ALT_ON;
+        }
+
+        if ((state & META_SYM_LOCKED) != 0) {
+            result |= META_SYM_LOCKED;
+        } else if ((state & META_SYM_ON) != 0) {
+            result |= META_SYM_ON;
+        }
+
+        return result;
     }
 
     /**
@@ -348,29 +388,25 @@
     public static final int getMetaState(long state, int meta) {
         switch (meta) {
             case META_SHIFT_ON:
-                return getActive(state, meta, 1, 2);
+                if ((state & META_CAP_LOCKED) != 0) return 2;
+                if ((state & META_SHIFT_ON) != 0) return 1;
+                return 0;
 
             case META_ALT_ON:
-                return getActive(state, meta, 1, 2);
+                if ((state & META_ALT_LOCKED) != 0) return 2;
+                if ((state & META_ALT_ON) != 0) return 1;
+                return 0;
 
             case META_SYM_ON:
-                return getActive(state, meta, 1, 2);
+                if ((state & META_SYM_LOCKED) != 0) return 2;
+                if ((state & META_SYM_ON) != 0) return 1;
+                return 0;
 
             default:
                 return 0;
         }
     }
 
-    private static int getActive(long state, int meta, int on, int lock) {
-        if ((state&(meta<<LOCKED_SHIFT)) != 0) {
-            return lock;
-        } else if ((state&meta) != 0) {
-            return on;
-        } else {
-            return 0;
-        }
-    }
-
     /**
      * Call this method after you handle a keypress so that the meta
      * state will be reset to unshifted (if it is not still down)
@@ -378,17 +414,23 @@
      * the current state, returns the new state.
      */
     public static long adjustMetaAfterKeypress(long state) {
-        state = adjust(state, META_SHIFT_ON, META_SHIFT_MASK);
-        state = adjust(state, META_ALT_ON, META_ALT_MASK);
-        state = adjust(state, META_SYM_ON, META_SYM_MASK);
-        return state;
-    }
+        if ((state & META_CAP_PRESSED) != 0) {
+            state = (state & ~META_SHIFT_MASK) | META_SHIFT_ON | META_CAP_USED;
+        } else if ((state & META_CAP_RELEASED) != 0) {
+            state &= ~META_SHIFT_MASK;
+        }
 
-    private static long adjust(long state, int what, long mask) {
-        if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
-            return (state&~mask) | what | ((long)what)<<USED_SHIFT;
-        else if ((state&(((long)what)<<RELEASED_SHIFT)) != 0)
-            return state & ~mask;
+        if ((state & META_ALT_PRESSED) != 0) {
+            state = (state & ~META_ALT_MASK) | META_ALT_ON | META_ALT_USED;
+        } else if ((state & META_ALT_RELEASED) != 0) {
+            state &= ~META_ALT_MASK;
+        }
+
+        if ((state & META_SYM_PRESSED) != 0) {
+            state = (state & ~META_SYM_MASK) | META_SYM_ON | META_SYM_USED;
+        } else if ((state & META_SYM_RELEASED) != 0) {
+            state &= ~META_SYM_MASK;
+        }
         return state;
     }
 
@@ -397,32 +439,36 @@
      */
     public static long handleKeyDown(long state, int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            return press(state, META_SHIFT_ON, META_SHIFT_MASK);
+            return press(state, META_SHIFT_ON, META_SHIFT_MASK,
+                    META_CAP_LOCKED, META_CAP_PRESSED, META_CAP_RELEASED, META_CAP_USED);
         }
 
         if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
                 || keyCode == KeyEvent.KEYCODE_NUM) {
-            return press(state, META_ALT_ON, META_ALT_MASK);
+            return press(state, META_ALT_ON, META_ALT_MASK,
+                    META_ALT_LOCKED, META_ALT_PRESSED, META_ALT_RELEASED, META_ALT_USED);
         }
 
         if (keyCode == KeyEvent.KEYCODE_SYM) {
-            return press(state, META_SYM_ON, META_SYM_MASK);
+            return press(state, META_SYM_ON, META_SYM_MASK,
+                    META_SYM_LOCKED, META_SYM_PRESSED, META_SYM_RELEASED, META_SYM_USED);
         }
-
         return state;
     }
 
-    private static long press(long state, int what, long mask) {
-        if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
-            ; // repeat before use
-        else if ((state&(((long)what)<<RELEASED_SHIFT)) != 0)
-            state = (state&~mask) | what | (((long)what) << LOCKED_SHIFT);
-        else if ((state&(((long)what)<<USED_SHIFT)) != 0)
-            ; // repeat after use
-        else if ((state&(((long)what)<<LOCKED_SHIFT)) != 0)
-            state = state&~mask;
-        else
-            state = state | what | (((long)what)<<PRESSED_SHIFT);
+    private static long press(long state, int what, long mask,
+            long locked, long pressed, long released, long used) {
+        if ((state & pressed) != 0) {
+            // repeat before use
+        } else if ((state & released) != 0) {
+            state = (state &~ mask) | what | locked;
+        } else if ((state & used) != 0) {
+            // repeat after use
+        } else if ((state & locked) != 0) {
+            state &= ~mask;
+        } else {
+            state |= what | pressed;
+        }
         return state;
     }
 
@@ -431,39 +477,52 @@
      */
     public static long handleKeyUp(long state, int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_SHIFT_LEFT || keyCode == KeyEvent.KEYCODE_SHIFT_RIGHT) {
-            return release(state, META_SHIFT_ON, META_SHIFT_MASK);
+            return release(state, META_SHIFT_ON, META_SHIFT_MASK,
+                    META_CAP_PRESSED, META_CAP_RELEASED, META_CAP_USED);
         }
 
         if (keyCode == KeyEvent.KEYCODE_ALT_LEFT || keyCode == KeyEvent.KEYCODE_ALT_RIGHT
                 || keyCode == KeyEvent.KEYCODE_NUM) {
-            return release(state, META_ALT_ON, META_ALT_MASK);
+            return release(state, META_ALT_ON, META_ALT_MASK,
+                    META_ALT_PRESSED, META_ALT_RELEASED, META_ALT_USED);
         }
 
         if (keyCode == KeyEvent.KEYCODE_SYM) {
-            return release(state, META_SYM_ON, META_SYM_MASK);
+            return release(state, META_SYM_ON, META_SYM_MASK,
+                    META_SYM_PRESSED, META_SYM_RELEASED, META_SYM_USED);
         }
-
         return state;
     }
 
-    private static long release(long state, int what, long mask) {
-        if ((state&(((long)what)<<USED_SHIFT)) != 0)
-            state = state&~mask;
-        else if ((state&(((long)what)<<PRESSED_SHIFT)) != 0)
-            state = state | what | (((long)what)<<RELEASED_SHIFT);
+    private static long release(long state, int what, long mask,
+            long pressed, long released, long used) {
+        if ((state & used) != 0) {
+            state &= ~mask;
+        } else if ((state & pressed) != 0) {
+            state |= what | released;
+        }
         return state;
     }
 
+    /**
+     * Clears the state of the specified meta key if it is locked.
+     * @param state the meta key state
+     * @param which meta keys to clear, may be a combination of {@link #META_SHIFT_ON},
+     * {@link #META_ALT_ON} or {@link #META_SYM_ON}.
+     */
     public long clearMetaKeyState(long state, int which) {
-        if ((which&META_SHIFT_ON) != 0)
-            state = resetLock(state, META_SHIFT_ON, META_SHIFT_MASK);
-        if ((which&META_ALT_ON) != 0)
-            state = resetLock(state, META_ALT_ON, META_ALT_MASK);
-        if ((which&META_SYM_ON) != 0)
-            state = resetLock(state, META_SYM_ON, META_SYM_MASK);
+        if ((which & META_SHIFT_ON_AND_LOCKED) == META_SHIFT_ON_AND_LOCKED) {
+            state &= ~META_SHIFT_MASK;
+        }
+        if ((which & META_ALT_ON_AND_LOCKED) == META_ALT_ON_AND_LOCKED) {
+            state &= ~META_ALT_MASK;
+        }
+        if ((which & META_SYM_ON_AND_LOCKED) == META_SYM_ON_AND_LOCKED) {
+            state &= ~META_SYM_MASK;
+        }
         return state;
     }
-    
+
     /**
      * The meta key has been pressed but has not yet been used.
      */
diff --git a/core/java/android/text/method/Touch.java b/core/java/android/text/method/Touch.java
index 3b98fc3..9eaab17 100644
--- a/core/java/android/text/method/Touch.java
+++ b/core/java/android/text/method/Touch.java
@@ -144,7 +144,7 @@
                 if (ds[0].mFarEnough) {
                     ds[0].mUsed = true;
                     boolean cap = (MetaKeyKeyListener.getMetaState(buffer,
-                                   KeyEvent.META_SHIFT_ON) == 1) ||
+                                   MetaKeyKeyListener.META_SHIFT_ON) == 1) ||
                                    (MetaKeyKeyListener.getMetaState(buffer,
                                     MetaKeyKeyListener.META_SELECTING) != 0);
                     float dx;
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 0e5ece1..0e75682 100755
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -42,6 +42,13 @@
  * Meta states describe the pressed state of key modifiers
  * such as {@link #META_SHIFT_ON} or {@link #META_ALT_ON}.
  * </p><p>
+ * Key codes typically correspond one-to-one with individual keys on an input device.
+ * Many keys and key combinations serve quite different functions on different
+ * input devices so care must be taken when interpreting them.  Always use the
+ * {@link KeyCharacterMap} associated with the input device when mapping keys
+ * to characters.  Be aware that there may be multiple key input devices active
+ * at the same time and each will have its own key character map.
+ * </p><p>
  * When interacting with an IME, the framework may deliver key events
  * with the special action {@link #ACTION_MULTIPLE} that either specifies
  * that single repeated key code or a sequence of characters to insert.
@@ -209,7 +216,7 @@
     /** Key code constant: Enter key. */
     public static final int KEYCODE_ENTER           = 66;
     /** Key code constant: Backspace key.
-     * Deletes characters before the insertion point. */
+     * Deletes characters before the insertion point, unlike {@link #KEYCODE_FORWARD_DEL}. */
     public static final int KEYCODE_DEL             = 67;
     /** Key code constant: '`' (backtick) key. */
     public static final int KEYCODE_GRAVE           = 68;
@@ -331,6 +338,125 @@
     /** Key code constant: Mode Button key.
      * On a game controller, the button labeled Mode. */
     public static final int KEYCODE_BUTTON_MODE     = 110;
+    /** Key code constant: Escape key. */
+    public static final int KEYCODE_ESCAPE          = 111;
+    /** Key code constant: Forward Delete key.
+     * Deletes characters ahead of the insertion point, unlike {@link #KEYCODE_DEL}. */
+    public static final int KEYCODE_FORWARD_DEL     = 112;
+    /** Key code constant: Left Control modifier key. */
+    public static final int KEYCODE_CTRL_LEFT       = 113;
+    /** Key code constant: Right Control modifier key. */
+    public static final int KEYCODE_CTRL_RIGHT      = 114;
+    /** Key code constant: Caps Lock modifier key. */
+    public static final int KEYCODE_CAPS_LOCK       = 115;
+    /** Key code constant: Scroll Lock key. */
+    public static final int KEYCODE_SCROLL_LOCK     = 116;
+    /** Key code constant: Left Meta modifier key. */
+    public static final int KEYCODE_META_LEFT       = 117;
+    /** Key code constant: Right Meta modifier key. */
+    public static final int KEYCODE_META_RIGHT      = 118;
+    /** Key code constant: Function modifier key. */
+    public static final int KEYCODE_FUNCTION        = 119;
+    /** Key code constant: System Request / Print Screen key. */
+    public static final int KEYCODE_SYSRQ           = 120;
+    /** Key code constant: Break / Pause key. */
+    public static final int KEYCODE_BREAK           = 121;
+    /** Key code constant: Home Movement key.
+     * Used for scrolling or moving the cursor around to the start of a line
+     * or to the top of a list. */
+    public static final int KEYCODE_MOVE_HOME       = 122;
+    /** Key code constant: End Movement key.
+     * Used for scrolling or moving the cursor around to the end of a line
+     * or to the bottom of a list. */
+    public static final int KEYCODE_MOVE_END        = 123;
+    /** Key code constant: Insert key.
+     * Toggles insert / overwrite edit mode. */
+    public static final int KEYCODE_INSERT          = 124;
+    /** Key code constant: Forward key.
+     * Navigates forward in the history stack.  Complement of {@link #KEYCODE_BACK}. */
+    public static final int KEYCODE_FORWARD         = 125;
+    /** Key code constant: Play media key. */
+    public static final int KEYCODE_MEDIA_PLAY      = 126;
+    /** Key code constant: Pause media key. */
+    public static final int KEYCODE_MEDIA_PAUSE     = 127;
+    /** Key code constant: Close media key.
+     * May be used to close a CD tray, for example. */
+    public static final int KEYCODE_MEDIA_CLOSE     = 128;
+    /** Key code constant: Eject media key.
+     * May be used to eject a CD tray, for example. */
+    public static final int KEYCODE_MEDIA_EJECT     = 129;
+    /** Key code constant: Record media key. */
+    public static final int KEYCODE_MEDIA_RECORD    = 130;
+    /** Key code constant: F1 key. */
+    public static final int KEYCODE_F1              = 131;
+    /** Key code constant: F2 key. */
+    public static final int KEYCODE_F2              = 132;
+    /** Key code constant: F3 key. */
+    public static final int KEYCODE_F3              = 133;
+    /** Key code constant: F4 key. */
+    public static final int KEYCODE_F4              = 134;
+    /** Key code constant: F5 key. */
+    public static final int KEYCODE_F5              = 135;
+    /** Key code constant: F6 key. */
+    public static final int KEYCODE_F6              = 136;
+    /** Key code constant: F7 key. */
+    public static final int KEYCODE_F7              = 137;
+    /** Key code constant: F8 key. */
+    public static final int KEYCODE_F8              = 138;
+    /** Key code constant: F9 key. */
+    public static final int KEYCODE_F9              = 139;
+    /** Key code constant: F10 key. */
+    public static final int KEYCODE_F10             = 140;
+    /** Key code constant: F11 key. */
+    public static final int KEYCODE_F11             = 141;
+    /** Key code constant: F12 key. */
+    public static final int KEYCODE_F12             = 142;
+    /** Key code constant: Num Lock modifier key.
+     * This is the Num Lock key; it is different from {@link #KEYCODE_NUM}.
+     * This key generally modifies the behavior of other keys on the numeric keypad. */
+    public static final int KEYCODE_NUM_LOCK        = 143;
+    /** Key code constant: Numeric keypad '0' key. */
+    public static final int KEYCODE_NUMPAD_0        = 144;
+    /** Key code constant: Numeric keypad '1' key. */
+    public static final int KEYCODE_NUMPAD_1        = 145;
+    /** Key code constant: Numeric keypad '2' key. */
+    public static final int KEYCODE_NUMPAD_2        = 146;
+    /** Key code constant: Numeric keypad '3' key. */
+    public static final int KEYCODE_NUMPAD_3        = 147;
+    /** Key code constant: Numeric keypad '4' key. */
+    public static final int KEYCODE_NUMPAD_4        = 148;
+    /** Key code constant: Numeric keypad '5' key. */
+    public static final int KEYCODE_NUMPAD_5        = 149;
+    /** Key code constant: Numeric keypad '6' key. */
+    public static final int KEYCODE_NUMPAD_6        = 150;
+    /** Key code constant: Numeric keypad '7' key. */
+    public static final int KEYCODE_NUMPAD_7        = 151;
+    /** Key code constant: Numeric keypad '8' key. */
+    public static final int KEYCODE_NUMPAD_8        = 152;
+    /** Key code constant: Numeric keypad '9' key. */
+    public static final int KEYCODE_NUMPAD_9        = 153;
+    /** Key code constant: Numeric keypad '/' key (for division). */
+    public static final int KEYCODE_NUMPAD_DIVIDE   = 154;
+    /** Key code constant: Numeric keypad '*' key (for multiplication). */
+    public static final int KEYCODE_NUMPAD_MULTIPLY = 155;
+    /** Key code constant: Numeric keypad '-' key (for subtraction). */
+    public static final int KEYCODE_NUMPAD_SUBTRACT = 156;
+    /** Key code constant: Numeric keypad '+' key (for addition). */
+    public static final int KEYCODE_NUMPAD_ADD      = 157;
+    /** Key code constant: Numeric keypad '.' key (for decimals or digit grouping). */
+    public static final int KEYCODE_NUMPAD_DOT      = 158;
+    /** Key code constant: Numeric keypad ',' key (for decimals or digit grouping). */
+    public static final int KEYCODE_NUMPAD_COMMA    = 159;
+    /** Key code constant: Numeric keypad Enter key. */
+    public static final int KEYCODE_NUMPAD_ENTER    = 160;
+    /** Key code constant: Numeric keypad '=' key. */
+    public static final int KEYCODE_NUMPAD_EQUALS   = 161;
+    /** Key code constant: Numeric keypad '(' key. */
+    public static final int KEYCODE_NUMPAD_LEFT_PAREN = 162;
+    /** Key code constant: Numeric keypad ')' key. */
+    public static final int KEYCODE_NUMPAD_RIGHT_PAREN = 163;
+
+    private static final int LAST_KEYCODE           = KEYCODE_NUMPAD_RIGHT_PAREN;
 
     // NOTE: If you add a new keycode here you must also add it to:
     //  isSystem()
@@ -339,7 +465,6 @@
     //  external/webkit/WebKit/android/plugins/ANPKeyCodes.h
     //  tools/puppet_master/PuppetMaster/nav_keys.py
     //  frameworks/base/core/res/res/values/attrs.xml
-    //  commands/monkey/Monkey.java
     //  emulator?
     //
     //  Also Android currently does not reserve code ranges for vendor-
@@ -347,9 +472,213 @@
     //  MUST contribute a patch to the open source project to define
     //  those new codes.  This is intended to maintain a consistent
     //  set of key code definitions across all Android devices.
-   
-    private static final int LAST_KEYCODE           = KEYCODE_BUTTON_MODE;
-    
+
+    // Symbolic names of all keys indexed by keycode.
+    // There should be exactly LAST_KEYCODE + 1 entries in this table.
+    private static final String[] KEYCODE_SYMBOLIC_NAMES = new String[] {
+        "KEYCODE_UNKNOWN",
+        "KEYCODE_SOFT_LEFT",
+        "KEYCODE_SOFT_RIGHT",
+        "KEYCODE_HOME",
+        "KEYCODE_BACK",
+        "KEYCODE_CALL",
+        "KEYCODE_ENDCALL",
+        "KEYCODE_0",
+        "KEYCODE_1",
+        "KEYCODE_2",
+        "KEYCODE_3",
+        "KEYCODE_4",
+        "KEYCODE_5",
+        "KEYCODE_6",
+        "KEYCODE_7",
+        "KEYCODE_8",
+        "KEYCODE_9",
+        "KEYCODE_STAR",
+        "KEYCODE_POUND",
+        "KEYCODE_DPAD_UP",
+        "KEYCODE_DPAD_DOWN",
+        "KEYCODE_DPAD_LEFT",
+        "KEYCODE_DPAD_RIGHT",
+        "KEYCODE_DPAD_CENTER",
+        "KEYCODE_VOLUME_UP",
+        "KEYCODE_VOLUME_DOWN",
+        "KEYCODE_POWER",
+        "KEYCODE_CAMERA",
+        "KEYCODE_CLEAR",
+        "KEYCODE_A",
+        "KEYCODE_B",
+        "KEYCODE_C",
+        "KEYCODE_D",
+        "KEYCODE_E",
+        "KEYCODE_F",
+        "KEYCODE_G",
+        "KEYCODE_H",
+        "KEYCODE_I",
+        "KEYCODE_J",
+        "KEYCODE_K",
+        "KEYCODE_L",
+        "KEYCODE_M",
+        "KEYCODE_N",
+        "KEYCODE_O",
+        "KEYCODE_P",
+        "KEYCODE_Q",
+        "KEYCODE_R",
+        "KEYCODE_S",
+        "KEYCODE_T",
+        "KEYCODE_U",
+        "KEYCODE_V",
+        "KEYCODE_W",
+        "KEYCODE_X",
+        "KEYCODE_Y",
+        "KEYCODE_Z",
+        "KEYCODE_COMMA",
+        "KEYCODE_PERIOD",
+        "KEYCODE_ALT_LEFT",
+        "KEYCODE_ALT_RIGHT",
+        "KEYCODE_SHIFT_LEFT",
+        "KEYCODE_SHIFT_RIGHT",
+        "KEYCODE_TAB",
+        "KEYCODE_SPACE",
+        "KEYCODE_SYM",
+        "KEYCODE_EXPLORER",
+        "KEYCODE_ENVELOPE",
+        "KEYCODE_ENTER",
+        "KEYCODE_DEL",
+        "KEYCODE_GRAVE",
+        "KEYCODE_MINUS",
+        "KEYCODE_EQUALS",
+        "KEYCODE_LEFT_BRACKET",
+        "KEYCODE_RIGHT_BRACKET",
+        "KEYCODE_BACKSLASH",
+        "KEYCODE_SEMICOLON",
+        "KEYCODE_APOSTROPHE",
+        "KEYCODE_SLASH",
+        "KEYCODE_AT",
+        "KEYCODE_NUM",
+        "KEYCODE_HEADSETHOOK",
+        "KEYCODE_FOCUS",
+        "KEYCODE_PLUS",
+        "KEYCODE_MENU",
+        "KEYCODE_NOTIFICATION",
+        "KEYCODE_SEARCH",
+        "KEYCODE_MEDIA_PLAY_PAUSE",
+        "KEYCODE_MEDIA_STOP",
+        "KEYCODE_MEDIA_NEXT",
+        "KEYCODE_MEDIA_PREVIOUS",
+        "KEYCODE_MEDIA_REWIND",
+        "KEYCODE_MEDIA_FAST_FORWARD",
+        "KEYCODE_MUTE",
+        "KEYCODE_PAGE_UP",
+        "KEYCODE_PAGE_DOWN",
+        "KEYCODE_PICTSYMBOLS",
+        "KEYCODE_SWITCH_CHARSET",
+        "KEYCODE_BUTTON_A",
+        "KEYCODE_BUTTON_B",
+        "KEYCODE_BUTTON_C",
+        "KEYCODE_BUTTON_X",
+        "KEYCODE_BUTTON_Y",
+        "KEYCODE_BUTTON_Z",
+        "KEYCODE_BUTTON_L1",
+        "KEYCODE_BUTTON_R1",
+        "KEYCODE_BUTTON_L2",
+        "KEYCODE_BUTTON_R2",
+        "KEYCODE_BUTTON_THUMBL",
+        "KEYCODE_BUTTON_THUMBR",
+        "KEYCODE_BUTTON_START",
+        "KEYCODE_BUTTON_SELECT",
+        "KEYCODE_BUTTON_MODE",
+        "KEYCODE_ESCAPE",
+        "KEYCODE_FORWARD_DEL",
+        "KEYCODE_CTRL_LEFT",
+        "KEYCODE_CTRL_RIGHT",
+        "KEYCODE_CAPS_LOCK",
+        "KEYCODE_SCROLL_LOCK",
+        "KEYCODE_META_LEFT",
+        "KEYCODE_META_RIGHT",
+        "KEYCODE_FUNCTION",
+        "KEYCODE_SYSRQ",
+        "KEYCODE_BREAK",
+        "KEYCODE_MOVE_HOME",
+        "KEYCODE_MOVE_END",
+        "KEYCODE_INSERT",
+        "KEYCODE_FORWARD",
+        "KEYCODE_MEDIA_PLAY",
+        "KEYCODE_MEDIA_PAUSE",
+        "KEYCODE_MEDIA_CLOSE",
+        "KEYCODE_MEDIA_EJECT",
+        "KEYCODE_MEDIA_RECORD",
+        "KEYCODE_F1",
+        "KEYCODE_F2",
+        "KEYCODE_F3",
+        "KEYCODE_F4",
+        "KEYCODE_F5",
+        "KEYCODE_F6",
+        "KEYCODE_F7",
+        "KEYCODE_F8",
+        "KEYCODE_F9",
+        "KEYCODE_F10",
+        "KEYCODE_F11",
+        "KEYCODE_F12",
+        "KEYCODE_NUM_LOCK",
+        "KEYCODE_NUMPAD_0",
+        "KEYCODE_NUMPAD_1",
+        "KEYCODE_NUMPAD_2",
+        "KEYCODE_NUMPAD_3",
+        "KEYCODE_NUMPAD_4",
+        "KEYCODE_NUMPAD_5",
+        "KEYCODE_NUMPAD_6",
+        "KEYCODE_NUMPAD_7",
+        "KEYCODE_NUMPAD_8",
+        "KEYCODE_NUMPAD_9",
+        "KEYCODE_NUMPAD_DIVIDE",
+        "KEYCODE_NUMPAD_MULTIPLY",
+        "KEYCODE_MUMPAD_SUBTRACT",
+        "KEYCODE_NUMPAD_ADD",
+        "KEYCODE_NUMPAD_DOT",
+        "KEYCODE_NUMPAD_COMMA",
+        "KEYCODE_NUMPAD_ENTER",
+        "KEYCODE_NUMPAD_EQUALS",
+        "KEYCODE_NUMPAD_LEFT_PAREN",
+        "KEYCODE_NUMPAD_RIGHT_PAREN",
+    };
+
+    // Symbolic names of all metakeys in bit order from least significant to most significant.
+    // Accordingly there are exactly 32 values in this table.
+    private static final String[] META_SYMBOLIC_NAMES = new String[] {
+        "META_SHIFT_ON",
+        "META_ALT_ON",
+        "META_SYM_ON",
+        "META_FUNCTION_ON",
+        "META_ALT_LEFT_ON",
+        "META_ALT_RIGHT_ON",
+        "META_SHIFT_LEFT_ON",
+        "META_SHIFT_RIGHT_ON",
+        "META_CAP_LOCKED",
+        "META_ALT_LOCKED",
+        "META_SYM_LOCKED",
+        "0x00000800",
+        "META_CTRL_ON",
+        "META_CTRL_LEFT_ON",
+        "META_CTRL_RIGHT_ON",
+        "0x00008000",
+        "META_META_ON",
+        "META_META_LEFT_ON",
+        "META_META_RIGHT_ON",
+        "0x00080000",
+        "META_CAPS_LOCK_LATCHED",
+        "META_NUM_LOCK_LATCHED",
+        "META_SCROLL_LOCK_LATCHED",
+        "0x00800000",
+        "0x01000000",
+        "0x02000000",
+        "0x04000000",
+        "0x08000000",
+        "0x10000000",
+        "0x20000000",
+        "0x40000000",
+        "0x80000000",
+    };
+
     /**
      * @deprecated There are now more than MAX_KEYCODE keycodes.
      * Use {@link #getMaxKeyCode()} instead.
@@ -377,6 +706,35 @@
     public static final int ACTION_MULTIPLE         = 2;
 
     /**
+     * SHIFT key locked in CAPS mode.
+     * Reserved for use by {@link MetaKeyKeyListener} for a published constant in its API.
+     * @hide
+     */
+    public static final int META_CAP_LOCKED = 0x100;
+
+    /**
+     * ALT key locked.
+     * Reserved for use by {@link MetaKeyKeyListener} for a published constant in its API.
+     * @hide
+     */
+    public static final int META_ALT_LOCKED = 0x200;
+
+    /**
+     * SYM key locked.
+     * Reserved for use by {@link MetaKeyKeyListener} for a published constant in its API.
+     * @hide
+     */
+    public static final int META_SYM_LOCKED = 0x400;
+
+    /**
+     * Text is in selection mode.
+     * Reserved for use by {@link MetaKeyKeyListener} for a private unpublished constant
+     * in its API that is currently being retained for legacy reasons.
+     * @hide
+     */
+    public static final int META_SELECTING = 0x800;
+
+    /**
      * <p>This mask is used to check whether one of the ALT meta keys is pressed.</p>
      *
      * @see #isAltPressed()
@@ -441,6 +799,97 @@
     public static final int META_SYM_ON = 0x4;
 
     /**
+     * <p>This mask is used to check whether the FUNCTION meta key is pressed.</p>
+     *
+     * @see #isFunctionPressed()
+     * @see #getMetaState()
+     */
+    public static final int META_FUNCTION_ON = 0x8;
+
+    /**
+     * <p>This mask is used to check whether one of the CTRL meta keys is pressed.</p>
+     *
+     * @see #isCtrlPressed()
+     * @see #getMetaState()
+     * @see #KEYCODE_CTRL_LEFT
+     * @see #KEYCODE_CTRL_RIGHT
+     */
+    public static final int META_CTRL_ON = 0x1000;
+
+    /**
+     * <p>This mask is used to check whether the left CTRL meta key is pressed.</p>
+     *
+     * @see #isCtrlPressed()
+     * @see #getMetaState()
+     * @see #KEYCODE_CTRL_LEFT
+     */
+    public static final int META_CTRL_LEFT_ON = 0x2000;
+
+    /**
+     * <p>This mask is used to check whether the right CTRL meta key is pressed.</p>
+     *
+     * @see #isCtrlPressed()
+     * @see #getMetaState()
+     * @see #KEYCODE_CTRL_RIGHT
+     */
+    public static final int META_CTRL_RIGHT_ON = 0x4000;
+
+    /**
+     * <p>This mask is used to check whether one of the META meta keys is pressed.</p>
+     *
+     * @see #isMetaPressed()
+     * @see #getMetaState()
+     * @see #KEYCODE_META_LEFT
+     * @see #KEYCODE_META_RIGHT
+     */
+    public static final int META_META_ON = 0x10000;
+
+    /**
+     * <p>This mask is used to check whether the left META meta key is pressed.</p>
+     *
+     * @see #isMetaPressed()
+     * @see #getMetaState()
+     * @see #KEYCODE_META_LEFT
+     */
+    public static final int META_META_LEFT_ON = 0x20000;
+
+    /**
+     * <p>This mask is used to check whether the right META meta key is pressed.</p>
+     *
+     * @see #isMetaPressed()
+     * @see #getMetaState()
+     * @see #KEYCODE_META_RIGHT
+     */
+    public static final int META_META_RIGHT_ON = 0x40000;
+
+    /**
+     * <p>This mask is used to check whether the CAPS LOCK meta key is latched.</p>
+     *
+     * @see #isCapsLockLatched()
+     * @see #getMetaState()
+     * @see #KEYCODE_CAPS_LOCK
+     */
+    public static final int META_CAPS_LOCK_LATCHED = 0x100000;
+
+    /**
+     * <p>This mask is used to check whether the NUM LOCK meta key is latched.</p>
+     *
+     * @see #isNumLockLatched()
+     * @see #getMetaState()
+     * @see #KEYCODE_NUM_LOCK
+     */
+    public static final int META_NUM_LOCK_LATCHED = 0x200000;
+
+    /**
+     * <p>This mask is used to check whether the SCROLL LOCK meta key is latched.</p>
+     *
+     * @see #isScrollLockLatched()
+     * @see #getMetaState()
+     * @see #KEYCODE_SCROLL_LOCK
+     */
+    public static final int META_SCROLL_LOCK_LATCHED = 0x400000;
+
+    /**
      * This mask is set if the device woke because of this key event.
      */
     public static final int FLAG_WOKE_HERE = 0x1;
@@ -603,6 +1052,17 @@
         boolean onKeyMultiple(int keyCode, int count, KeyEvent event);
     }
 
+    static {
+        if (META_SYMBOLIC_NAMES.length != 32) {
+            throw new IllegalStateException(
+                    "META_SYMBOLIC_NAMES array should contain exactly 32 entries.");
+        }
+        if (KEYCODE_SYMBOLIC_NAMES.length != LAST_KEYCODE + 1) {
+            throw new IllegalStateException(
+                    "KEYCODE_SYMBOLIC_NAMES array is out of sync with the keycode constants.");
+        }
+    }
+
     /**
      * Create a new key event.
      * 
@@ -939,9 +1399,29 @@
      * @see #isAltPressed()
      * @see #isShiftPressed()
      * @see #isSymPressed()
+     * @see #isCtrlPressed()
+     * @see #isMetaPressed()
+     * @see #isFunctionPressed()
+     * @see #isCapsLockLatched()
+     * @see #isNumLockLatched()
+     * @see #isScrollLockLatched()
      * @see #META_ALT_ON
+     * @see #META_ALT_LEFT_ON
+     * @see #META_ALT_RIGHT_ON
      * @see #META_SHIFT_ON
+     * @see #META_SHIFT_LEFT_ON
+     * @see #META_SHIFT_RIGHT_ON
      * @see #META_SYM_ON
+     * @see #META_FUNCTION_ON
+     * @see #META_CTRL_ON
+     * @see #META_CTRL_LEFT_ON
+     * @see #META_CTRL_RIGHT_ON
+     * @see #META_META_ON
+     * @see #META_META_LEFT_ON
+     * @see #META_META_RIGHT_ON
+     * @see #META_CAPS_LOCK_LATCHED
+     * @see #META_NUM_LOCK_LATCHED
+     * @see #META_SCROLL_LOCK_LATCHED
      */
     public final int getMetaState() {
         return mMetaState;
@@ -961,13 +1441,28 @@
      *
      * @return whether the provided keyCode is one of
      * {@link #KEYCODE_SHIFT_LEFT} {@link #KEYCODE_SHIFT_RIGHT},
-     * {@link #KEYCODE_ALT_LEFT}, {@link #KEYCODE_ALT_RIGHT}
-     * or {@link #KEYCODE_SYM}.
+     * {@link #KEYCODE_ALT_LEFT}, {@link #KEYCODE_ALT_RIGHT},
+     * {@link #KEYCODE_SYM}, {@link #KEYCODE_NUM}, {@link #KEYCODE_FUNCTION},
+     * {@link #KEYCODE_CTRL_LEFT}, {@link #KEYCODE_CTRL_RIGHT},
+     * {@link #KEYCODE_META_LEFT}, or {@link #KEYCODE_META_RIGHT}.
      */
     public static boolean isModifierKey(int keyCode) {
-        return keyCode == KEYCODE_SHIFT_LEFT || keyCode == KEYCODE_SHIFT_RIGHT
-                || keyCode == KEYCODE_ALT_LEFT || keyCode == KEYCODE_ALT_RIGHT
-                || keyCode == KEYCODE_SYM;
+        switch (keyCode) {
+            case KEYCODE_SHIFT_LEFT:
+            case KEYCODE_SHIFT_RIGHT:
+            case KEYCODE_ALT_LEFT:
+            case KEYCODE_ALT_RIGHT:
+            case KEYCODE_SYM:
+            case KEYCODE_NUM:
+            case KEYCODE_FUNCTION:
+            case KEYCODE_CTRL_LEFT:
+            case KEYCODE_CTRL_RIGHT:
+            case KEYCODE_META_LEFT:
+            case KEYCODE_META_RIGHT:
+                return true;
+            default:
+                return false;
+        }
     }
 
     /**
@@ -1009,6 +1504,80 @@
     }
 
     /**
+     * <p>Returns the pressed state of the CTRL meta key.</p>
+     *
+     * @return true if the CTRL key is pressed, false otherwise
+     *
+     * @see #KEYCODE_CTRL_LEFT
+     * @see #KEYCODE_CTRL_RIGHT
+     * @see #META_CTRL_ON
+     */
+    public final boolean isCtrlPressed() {
+        return (mMetaState & META_CTRL_ON) != 0;
+    }
+
+    /**
+     * <p>Returns the pressed state of the META meta key.</p>
+     *
+     * @return true if the META key is pressed, false otherwise
+     *
+     * @see #KEYCODE_META_LEFT
+     * @see #KEYCODE_META_RIGHT
+     * @see #META_META_ON
+     */
+    public final boolean isMetaPressed() {
+        return (mMetaState & META_META_ON) != 0;
+    }
+
+    /**
+     * <p>Returns the pressed state of the FUNCTION meta key.</p>
+     *
+     * @return true if the FUNCTION key is pressed, false otherwise
+     *
+     * @see #KEYCODE_FUNCTION
+     * @see #META_FUNCTION_ON
+     */
+    public final boolean isFunctionPressed() {
+        return (mMetaState & META_FUNCTION_ON) != 0;
+    }
+
+    /**
+     * <p>Returns the latched state of the CAPS LOCK meta key.</p>
+     *
+     * @return true if the CAPS LOCK key is latched, false otherwise
+     *
+     * @see #KEYCODE_CAPS_LOCK
+     * @see #META_CAPS_LOCK_LATCHED
+     */
+    public final boolean isCapsLockLatched() {
+        return (mMetaState & META_CAPS_LOCK_LATCHED) != 0;
+    }
+
+    /**
+     * <p>Returns the latched state of the NUM LOCK meta key.</p>
+     *
+     * @return true if the NUM LOCK key is latched, false otherwise
+     *
+     * @see #KEYCODE_NUM_LOCK
+     * @see #META_NUM_LOCK_LATCHED
+     */
+    public final boolean isNumLockLatched() {
+        return (mMetaState & META_NUM_LOCK_LATCHED) != 0;
+    }
+
+    /**
+     * <p>Returns the latched state of the SCROLL LOCK meta key.</p>
+     *
+     * @return true if the SCROLL LOCK key is latched, false otherwise
+     *
+     * @see #KEYCODE_SCROLL_LOCK
+     * @see #META_SCROLL_LOCK_LATCHED
+     */
+    public final boolean isScrollLockLatched() {
+        return (mMetaState & META_SCROLL_LOCK_LATCHED) != 0;
+    }
+
+    /**
      * Retrieve the action of this key event.  May be either
      * {@link #ACTION_DOWN}, {@link #ACTION_UP}, or {@link #ACTION_MULTIPLE}.
      * 
@@ -1392,12 +1961,118 @@
             }
         }
     }
-    
+
+    @Override
     public String toString() {
-        return "KeyEvent{action=" + mAction + " code=" + mKeyCode
-            + " repeat=" + mRepeatCount
-            + " meta=" + mMetaState + " scancode=" + mScanCode
-            + " mFlags=" + mFlags + "}";
+        return "KeyEvent{action=" + actionToString(mAction)
+                + " keycode=" + keyCodeToString(mKeyCode)
+                + " scancode=" + mScanCode
+                + " meta=" + metaStateToString(mMetaState)
+                + " flags=0x" + Integer.toHexString(mFlags)
+                + " repeat=" + mRepeatCount
+                + " device=" + mDeviceId
+                + " source=0x" + Integer.toHexString(mSource)
+                + "}";
+    }
+
+    /**
+     * Returns a string that represents the symbolic name of the specified action
+     * such as "ACTION_DOWN", or "35" (if unknown).
+     *
+     * @param action The action.
+     * @return The symbolic name of the specified action.
+     * @hide
+     */
+    public static String actionToString(int action) {
+        switch (action) {
+            case ACTION_DOWN:
+                return "ACTION_DOWN";
+            case ACTION_UP:
+                return "ACTION_UP";
+            case ACTION_MULTIPLE:
+                return "ACTION_MULTIPLE";
+            default:
+                return Integer.toString(action);
+        }
+    }
+
+    /**
+     * Returns a string that represents the symbolic name of the specified keycode
+     * such as "KEYCODE_A", "KEYCODE_DPAD_UP", or "1001" (if unknown).
+     *
+     * @param keyCode The key code.
+     * @return The symbolic name of the specified keycode.
+     *
+     * @see KeyCharacterMap#getDisplayLabel
+     * @hide
+     */
+    public static String keyCodeToString(int keyCode) {
+        if (keyCode >= 0 && keyCode < KEYCODE_SYMBOLIC_NAMES.length) {
+            return KEYCODE_SYMBOLIC_NAMES[keyCode];
+        }
+        return Integer.toString(keyCode);
+    }
+
+    /**
+     * Gets a keycode by its symbolic name such as "KEYCODE_A" or "1001" (if unknown).
+     *
+     * @param symbolicName The symbolic name of the keycode.
+     * @return The keycode or -1 if not found.
+     * @see #keycodeToString
+     * @hide
+     */
+    public static int keyCodeFromString(String symbolicName) {
+        if (symbolicName == null) {
+            throw new IllegalArgumentException("symbolicName must not be null");
+        }
+
+        final int count = KEYCODE_SYMBOLIC_NAMES.length;
+        for (int i = 0; i < count; i++) {
+            if (symbolicName.equals(KEYCODE_SYMBOLIC_NAMES[i])) {
+                return i;
+            }
+        }
+
+        try {
+            return Integer.parseInt(symbolicName,10);
+        } catch (NumberFormatException ex) {
+            return -1;
+        }
+    }
+
+    /**
+     * Returns a string that represents the symbolic name of the specified combined meta
+     * key modifier state flags such as "0", "META_SHIFT_ON",
+     * "META_ALT_ON|META_SHIFT_ON" or "0x10000000" (if unknown).
+     *
+     * @param metaState The meta state.
+     * @return The symbolic name of the specified combined meta state flags.
+     * @hide
+     */
+    public static String metaStateToString(int metaState) {
+        if (metaState == 0) {
+            return "0";
+        }
+        StringBuilder result = null;
+        int i = 0;
+        while (metaState != 0) {
+            final boolean isSet = (metaState & 1) != 0;
+            metaState >>>= 1; // unsigned shift!
+            if (isSet) {
+                final String name = META_SYMBOLIC_NAMES[i];
+                if (result == null) {
+                    if (metaState == 0) {
+                        return name;
+                    }
+                    result = new StringBuilder(name);
+                } else {
+                    result.append('|');
+                    result.append(name);
+                }
+            }
+            i += 1;
+        }
+        return result.toString();
     }
 
     public static final Parcelable.Creator<KeyEvent> CREATOR
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 9411474..195d689 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -1550,8 +1550,54 @@
     @Override
     public String toString() {
         return "MotionEvent{" + Integer.toHexString(System.identityHashCode(this))
-            + " action=" + mAction + " x=" + getX()
-            + " y=" + getY() + " pressure=" + getPressure() + " size=" + getSize() + "}";
+            + " action=" + actionToString(mAction)
+            + " x=" + getX()
+            + " y=" + getY()
+            + " pressure=" + getPressure()
+            + " size=" + getSize()
+            + " touchMajor=" + getTouchMajor()
+            + " touchMinor=" + getTouchMinor()
+            + " toolMajor=" + getToolMajor()
+            + " toolMinor=" + getToolMinor()
+            + " orientation=" + getOrientation()
+            + " meta=" + KeyEvent.metaStateToString(mMetaState)
+            + " pointerCount=" + getPointerCount()
+            + " historySize=" + getHistorySize()
+            + " flags=0x" + Integer.toHexString(mFlags)
+            + " edgeFlags=0x" + Integer.toHexString(mEdgeFlags)
+            + " device=" + mDeviceId
+            + " source=0x" + Integer.toHexString(mSource)
+            + "}";
+    }
+
+    /**
+     * Returns a string that represents the symbolic name of the specified action
+     * such as "ACTION_DOWN", "ACTION_POINTER_DOWN(3)" or "35" (if unknown).
+     *
+     * @param action The action.
+     * @return The symbolic name of the specified action.
+     * @hide
+     */
+    public static String actionToString(int action) {
+        switch (action) {
+            case ACTION_DOWN:
+                return "ACTION_DOWN";
+            case ACTION_UP:
+                return "ACTION_UP";
+            case ACTION_CANCEL:
+                return "ACTION_CANCEL";
+            case ACTION_MOVE:
+                return "ACTION_MOVE";
+        }
+        int index = (action & ACTION_POINTER_INDEX_MASK) >> ACTION_POINTER_INDEX_SHIFT;
+        switch (action & ACTION_MASK) {
+            case ACTION_POINTER_DOWN:
+                return "ACTION_POINTER_DOWN(" + index + ")";
+            case ACTION_POINTER_UP:
+                return "ACTION_POINTER_UP(" + index + ")";
+            default:
+                return Integer.toString(action);
+        }
     }
 
     public static final Parcelable.Creator<MotionEvent> CREATOR
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 7cb4671..0b2d0f6 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -167,7 +167,8 @@
             @ViewDebug.IntToString(from = TYPE_KEYGUARD_DIALOG, to = "TYPE_KEYGUARD_DIALOG"),
             @ViewDebug.IntToString(from = TYPE_SYSTEM_ERROR, to = "TYPE_SYSTEM_ERROR"),
             @ViewDebug.IntToString(from = TYPE_INPUT_METHOD, to = "TYPE_INPUT_METHOD"),
-            @ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG, to = "TYPE_INPUT_METHOD_DIALOG")
+            @ViewDebug.IntToString(from = TYPE_INPUT_METHOD_DIALOG, to = "TYPE_INPUT_METHOD_DIALOG"),
+            @ViewDebug.IntToString(from = TYPE_SECURE_SYSTEM_OVERLAY, to = "TYPE_SECURE_SYSTEM_OVERLAY")
         })
         public int type;
     
@@ -345,13 +346,25 @@
          * Window type: panel that slides out from the status bar
          */
         public static final int TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14;
-        
+
+        /**
+         * Window type: secure system overlay windows, which need to be displayed
+         * on top of everything else.  These windows must not take input
+         * focus, or they will interfere with the keyguard.
+         *
+         * This is exactly like {@link #TYPE_SYSTEM_OVERLAY} except that only the
+         * system itself is allowed to create these overlays.  Applications cannot
+         * obtain permission to create secure system overlays.
+         * @hide
+         */
+        public static final int TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15;
+
         /**
          * Window type: the drag-and-drop pseudowindow.  There is only one
          * drag layer (at most), and it is placed on top of all other windows.
          * @hide
          */
-        public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+15;
+        public static final int TYPE_DRAG               = FIRST_SYSTEM_WINDOW+16;
 
         /**
          * End of types of system windows.
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 9cfab2a..4e5809e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -16,7 +16,6 @@
 
 package android.widget;
 
-import android.view.ViewConfiguration;
 import com.android.internal.util.FastMath;
 import com.android.internal.widget.EditableInputConnection;
 
@@ -97,6 +96,7 @@
 import android.view.MenuItem;
 import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewDebug;
 import android.view.ViewGroup;
 import android.view.ViewGroup.LayoutParams;
@@ -4525,7 +4525,7 @@
         }
 
         hideControllers();
-        stopTextSelectionMode();
+        stopSelectionActionMode();
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
diff --git a/core/java/com/android/internal/os/RuntimeInit.java b/core/java/com/android/internal/os/RuntimeInit.java
index 5767832..18e1b45 100644
--- a/core/java/com/android/internal/os/RuntimeInit.java
+++ b/core/java/com/android/internal/os/RuntimeInit.java
@@ -264,7 +264,9 @@
         // TODO: Doing this here works, but it seems kind of arbitrary. Find
         // a better place. The goal is to set it up for applications, but not
         // tools like am.
+        System.out.close();
         System.setOut(new AndroidPrintStream(Log.INFO, "System.out"));
+        System.err.close();
         System.setErr(new AndroidPrintStream(Log.WARN, "System.err"));
 
         commonInit();
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index ef6d6cb..578191a 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -1056,6 +1056,59 @@
         <enum name="KEYCODE_BUTTON_START" value="108" />
         <enum name="KEYCODE_BUTTON_SELECT" value="109" />
         <enum name="KEYCODE_BUTTON_MODE" value="110" />
+        <enum name="KEYCODE_ESCAPE" value="111" />
+        <enum name="KEYCODE_FORWARD_DEL" value="112" />
+        <enum name="KEYCODE_CTRL_LEFT" value="113" />
+        <enum name="KEYCODE_CTRL_RIGHT" value="114" />
+        <enum name="KEYCODE_CAPS_LOCK" value="115" />
+        <enum name="KEYCODE_SCROLL_LOCK" value="116" />
+        <enum name="KEYCODE_META_LEFT" value="117" />
+        <enum name="KEYCODE_META_RIGHT" value="118" />
+        <enum name="KEYCODE_FUNCTION" value="119" />
+        <enum name="KEYCODE_SYSRQ" value="120" />
+        <enum name="KEYCODE_BREAK" value="121" />
+        <enum name="KEYCODE_MOVE_HOME" value="122" />
+        <enum name="KEYCODE_MOVE_END" value="123" />
+        <enum name="KEYCODE_INSERT" value="124" />
+        <enum name="KEYCODE_FORWARD" value="125" />
+        <enum name="KEYCODE_MEDIA_PLAY" value="126" />
+        <enum name="KEYCODE_MEDIA_PAUSE" value="127" />
+        <enum name="KEYCODE_MEDIA_CLOSE" value="128" />
+        <enum name="KEYCODE_MEDIA_EJECT" value="129" />
+        <enum name="KEYCODE_MEDIA_RECORD" value="130" />
+        <enum name="KEYCODE_F1" value="131" />
+        <enum name="KEYCODE_F2" value="132" />
+        <enum name="KEYCODE_F3" value="133" />
+        <enum name="KEYCODE_F4" value="134" />
+        <enum name="KEYCODE_F5" value="135" />
+        <enum name="KEYCODE_F6" value="136" />
+        <enum name="KEYCODE_F7" value="137" />
+        <enum name="KEYCODE_F8" value="138" />
+        <enum name="KEYCODE_F9" value="139" />
+        <enum name="KEYCODE_F10" value="140" />
+        <enum name="KEYCODE_F11" value="141" />
+        <enum name="KEYCODE_F12" value="142" />
+        <enum name="NUM_LOCK" value="143" />
+        <enum name="NUMPAD_0" value="144" />
+        <enum name="NUMPAD_1" value="145" />
+        <enum name="NUMPAD_2" value="146" />
+        <enum name="NUMPAD_3" value="147" />
+        <enum name="NUMPAD_4" value="148" />
+        <enum name="NUMPAD_5" value="149" />
+        <enum name="NUMPAD_6" value="150" />
+        <enum name="NUMPAD_7" value="151" />
+        <enum name="NUMPAD_8" value="152" />
+        <enum name="NUMPAD_9" value="153" />
+        <enum name="NUMPAD_DIVIDE" value="154" />
+        <enum name="NUMPAD_MULTIPLY" value="155" />
+        <enum name="NUMPAD_SUBTRACT" value="156" />
+        <enum name="NUMPAD_ADD" value="157" />
+        <enum name="NUMPAD_DOT" value="158" />
+        <enum name="NUMPAD_COMMA" value="159" />
+        <enum name="NUMPAD_ENTER" value="160" />
+        <enum name="NUMPAD_EQUALS" value="161" />
+        <enum name="NUMPAD_LEFT_PAREN" value="162" />
+        <enum name="NUMPAD_RIGHT_PAREN" value="163" />
     </attr>
 
     <!-- ***************************************************************** -->
diff --git a/data/keyboards/Android.mk b/data/keyboards/Android.mk
new file mode 100644
index 0000000..7a0eae0
--- /dev/null
+++ b/data/keyboards/Android.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+# This makefile builds the key character map binary files.  (*.kcm.bin)
+
+LOCAL_PATH := $(call my-dir)
+include $(LOCAL_PATH)/common.mk
+
+$(foreach file,$(keycharmaps), \
+    $(eval include $(CLEAR_VARS)) \
+    $(eval LOCAL_SRC_FILES := $(file)) \
+    $(eval LOCAL_MODULE_TAGS := optional) \
+    $(eval include $(BUILD_KEY_CHAR_MAP)) \
+)
diff --git a/data/keyboards/Generic.kcm b/data/keyboards/Generic.kcm
new file mode 100644
index 0000000..f3c52a7
--- /dev/null
+++ b/data/keyboards/Generic.kcm
@@ -0,0 +1,100 @@
+# 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.
+
+#
+# Generic key character map for full alphabetic US English PC style external keyboards.
+#
+# This file is intentionally very generic and is intended to support a broad rang of keyboards.
+# Do not edit the generic key character map to support a specific keyboard; instead, create
+# a new key character map file with the required keyboard configuration.
+#
+
+[type=QWERTY]
+
+# keycode               display number  base    caps    fn      caps_fn
+
+A                       'A'     '2'     'a'     'A'     'a'     'A'
+B                       'B'     '2'     'b'     'B'     'b'     'B'
+C                       'C'     '2'     'c'     'C'     'c'     'C'
+D                       'D'     '3'     'd'     'D'     'd'     'D'
+E                       'E'     '3'     'e'     'E'     'e'     'E'
+F                       'F'     '3'     'f'     'F'     'f'     'F'
+G                       'G'     '4'     'g'     'G'     'g'     'G'
+H                       'H'     '4'     'h'     'H'     'h'     'H'
+I                       'I'     '4'     'i'     'I'     'i'     'I'
+J                       'J'     '5'     'j'     'J'     'j'     'J'
+K                       'K'     '5'     'k'     'K'     'k'     'K'
+L                       'L'     '5'     'l'     'L'     'l'     'L'
+M                       'M'     '6'     'm'     'M'     'm'     'M'
+N                       'N'     '6'     'n'     'N'     'n'     'N'
+O                       'O'     '6'     'o'     'O'     'o'     'O'
+P                       'P'     '7'     'p'     'P'     'p'     'P'
+Q                       'Q'     '7'     'q'     'Q'     'q'     'Q'
+R                       'R'     '7'     'r'     'R'     'r'     'R'
+S                       'S'     '7'     's'     'S'     's'     'S'
+T                       'T'     '8'     't'     'T'     't'     'T'
+U                       'U'     '8'     'u'     'U'     'u'     'U'
+V                       'V'     '8'     'v'     'V'     'v'     'V'
+W                       'W'     '9'     'w'     'W'     'w'     'W'
+X                       'X'     '9'     'x'     'X'     'x'     'X'
+Y                       'Y'     '9'     'y'     'Y'     'y'     'Y'
+Z                       'Z'     '9'     'z'     'Z'     'z'     'Z'
+
+0                       '0'     '0'     '0'     ')'     '0'     ')'
+1                       '1'     '1'     '1'     '!'     '1'     '!'
+2                       '2'     '2'     '2'     '@'     '2'     '@'
+3                       '3'     '3'     '3'     '#'     '3'     '#'
+4                       '4'     '4'     '4'     '$'     '4'     '$'
+5                       '5'     '5'     '5'     '%'     '5'     '%'
+6                       '6'     '6'     '6'     '^'     '6'     '^'
+7                       '7'     '7'     '7'     '&'     '7'     '&'
+8                       '8'     '8'     '8'     '*'     '8'     '*'
+9                       '9'     '9'     '9'     '('     '9'     '('
+
+SPACE                   0x20    0x20    0x20    0x20    0x20    0x20
+ENTER                   0xa     0xa     0xa     0xa     0xa     0xa
+TAB                     0x9     0x9     0x9     0x9     0x9     0x9
+
+COMMA                   ','     ','     ','     '<'     ','     '<'
+PERIOD                  '.'     '.'     '.'     '>'     '.'     '>'
+SLASH                   '/'     '/'     '/'     '?'     '/'     '?'
+GRAVE                   '`'     '`'     '`'     '~'     '`'     '~'
+MINUS                   '-'     '-'     '-'     '_'     '-'     '_'
+EQUALS                  '='     '='     '='     '+'     '='     '+'
+LEFT_BRACKET            '['     '['     '['     '{'     '['     '{'
+RIGHT_BRACKET           ']'     ']'     ']'     '}'     ']'     '}'
+BACKSLASH               '\'     '\'     '\'     '|'     '\'     '|'
+SEMICOLON               ';'     ';'     ';'     ':'     ';'     ':'
+APOSTROPHE              '''     '''     '''     '"'     '''     '"'
+
+NUMPAD_0                '0'     '0'     '0'     '0'     '0'     '0'
+NUMPAD_1                '1'     '1'     '1'     '1'     '1'     '1'
+NUMPAD_2                '2'     '2'     '2'     '2'     '2'     '2'
+NUMPAD_3                '3'     '3'     '3'     '3'     '3'     '3'
+NUMPAD_4                '4'     '4'     '4'     '4'     '4'     '4'
+NUMPAD_5                '5'     '5'     '5'     '5'     '5'     '5'
+NUMPAD_6                '6'     '6'     '6'     '6'     '6'     '6'
+NUMPAD_7                '7'     '7'     '7'     '7'     '7'     '7'
+NUMPAD_8                '8'     '8'     '8'     '8'     '8'     '8'
+NUMPAD_9                '9'     '9'     '9'     '9'     '9'     '9'
+NUMPAD_LEFT_PAREN       '('     '('     '('     '('     '('     '('
+NUMPAD_RIGHT_PAREN      ')'     ')'     ')'     ')'     ')'     ')'
+NUMPAD_DIVIDE           '/'     '/'     '/'     '/'     '/'     '/'
+NUMPAD_MULTIPLY         '*'     '*'     '*'     '*'     '*'     '*'
+NUMPAD_SUBTRACT         '-'     '-'     '-'     '-'     '-'     '-'
+NUMPAD_ADD              '+'     '+'     '+'     '+'     '+'     '+'
+NUMPAD_DOT              '.'     '.'     '.'     '.'     '.'     '.'
+NUMPAD_COMMA            ','     ','     ','     ','     ','     ','
+NUMPAD_EQUALS           '='     '='     '='     '='     '='     '='
+NUMPAD_ENTER            0xa     0xa     0xa     0xa     0xa     0xa
diff --git a/data/keyboards/Generic.kl b/data/keyboards/Generic.kl
new file mode 100644
index 0000000..818397b
--- /dev/null
+++ b/data/keyboards/Generic.kl
@@ -0,0 +1,384 @@
+# 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.
+
+#
+# Generic key layout file for full alphabetic US English PC style external keyboards.
+#
+# This file is intentionally very generic and is intended to support a broad rang of keyboards.
+# Do not edit the generic key layout to support a specific keyboard; instead, create
+# a new key layout file with the required keyboard configuration.
+#
+
+key 1     ESCAPE
+key 2     1
+key 3     2
+key 4     3
+key 5     4
+key 6     5
+key 7     6
+key 8     7
+key 9     8
+key 10    9
+key 11    0
+key 12    MINUS
+key 13    EQUALS
+key 14    DEL
+key 15    TAB
+key 16    Q
+key 17    W
+key 18    E
+key 19    R
+key 20    T
+key 21    Y
+key 22    U
+key 23    I
+key 24    O
+key 25    P
+key 26    LEFT_BRACKET
+key 27    RIGHT_BRACKET
+key 28    ENTER
+key 29    CTRL_LEFT
+key 30    A
+key 31    S
+key 32    D
+key 33    F
+key 34    G
+key 35    H
+key 36    J
+key 37    K
+key 38    L
+key 39    SEMICOLON
+key 40    APOSTROPHE
+key 41    GRAVE
+key 42    SHIFT_LEFT
+key 43    BACKSLASH
+key 44    Z
+key 45    X
+key 46    C
+key 47    V
+key 48    B
+key 49    N
+key 50    M
+key 51    COMMA
+key 52    PERIOD
+key 53    SLASH
+key 54    SHIFT_RIGHT
+key 55    NUMPAD_MULTIPLY
+key 56    ALT_LEFT
+key 57    SPACE
+key 58    CAPS_LOCK
+key 59    F1
+key 60    F2
+key 61    F3
+key 62    F4
+key 63    F5
+key 64    F6
+key 65    F7
+key 66    F8
+key 67    F9
+key 68    F10
+key 69    NUM_LOCK
+key 70    SCROLL_LOCK
+key 71    NUMPAD_7
+key 72    NUMPAD_8
+key 73    NUMPAD_9
+key 74    NUMPAD_SUBTRACT
+key 75    NUMPAD_4
+key 76    NUMPAD_5
+key 77    NUMPAD_6
+key 78    NUMPAD_ADD
+key 79    NUMPAD_1
+key 80    NUMPAD_2
+key 81    NUMPAD_3
+key 82    NUMPAD_0
+key 83    NUMPAD_DOT
+# key 84 (undefined)
+# key 85 "KEY_ZENKAKUHANKAKU"
+# key 86 "KEY_102ND"
+key 87    F11
+key 88    F12
+# key 89 "KEY_RO"
+# key 90 "KEY_KATAKANA"
+# key 91 "KEY_HIRAGANA"
+# key 92 "KEY_HENKAN"
+# key 93 "KEY_KATAKANAHIRAGANA"
+# key 94 "KEY_MUHENKAN"
+key 95    NUMPAD_COMMA
+key 96    NUMPAD_ENTER
+key 97    CTRL_RIGHT
+key 98    NUMPAD_DIVIDE
+key 99    SYSRQ
+key 100   ALT_RIGHT
+# key 101 "KEY_LINEFEED"
+key 102   MOVE_HOME
+key 103   DPAD_UP
+key 104   PAGE_UP
+key 105   DPAD_LEFT
+key 106   DPAD_RIGHT
+key 107   MOVE_END
+key 108   DPAD_DOWN
+key 109   PAGE_DOWN
+key 110   INSERT
+key 111   FORWARD_DEL
+# key 112 "KEY_MACRO"
+key 113   MUTE
+key 114   VOLUME_DOWN
+key 115   VOLUME_UP
+key 116   POWER             WAKE
+key 117   NUMPAD_EQUALS
+# key 118 "KEY_KPPLUSMINUS"
+key 119   BREAK
+# key 120 (undefined)
+key 121   NUMPAD_COMMA
+# key 122 "KEY_HANGEUL"
+# key 123 "KEY_HANJA"
+# key 124 "KEY_YEN"
+key 125   META_LEFT
+key 126   META_RIGHT
+key 127   MENU              WAKE_DROPPED
+key 128   MEDIA_STOP
+# key 129 "KEY_AGAIN"
+# key 130 "KEY_PROPS"
+# key 131 "KEY_UNDO"
+# key 132 "KEY_FRONT"
+# key 133 "KEY_COPY"
+# key 134 "KEY_OPEN"
+# key 135 "KEY_PASTE"
+# key 136 "KEY_FIND"
+# key 137 "KEY_CUT"
+# key 138 "KEY_HELP"
+key 139   MENU              WAKE_DROPPED
+# key 140 "KEY_CALC"
+# key 141 "KEY_SETUP"
+# key 142 "KEY_SLEEP"
+# key 143 "KEY_WAKEUP"
+# key 144 "KEY_FILE"
+# key 145 "KEY_SENDFILE"
+# key 146 "KEY_DELETEFILE"
+# key 147 "KEY_XFER"
+# key 148 "KEY_PROG1"
+# key 149 "KEY_PROG2"
+key 150   EXPLORER
+# key 151 "KEY_MSDOS"
+# key 152 "KEY_COFFEE"
+# key 153 "KEY_DIRECTION"
+# key 154 "KEY_CYCLEWINDOWS"
+key 155   ENVELOPE
+# key 156 "KEY_BOOKMARKS"
+# key 157 "KEY_COMPUTER"
+key 158   BACK              WAKE_DROPPED
+key 159   FORWARD
+key 160   MEDIA_CLOSE
+key 161   MEDIA_EJECT
+key 162   MEDIA_EJECT
+key 163   MEDIA_NEXT
+key 164   MEDIA_PLAY_PAUSE
+key 165   MEDIA_PREVIOUS
+key 166   MEDIA_STOP
+key 167   MEDIA_RECORD
+key 168   MEDIA_REWIND
+key 169   CALL
+# key 170 "KEY_ISO"
+# key 171 "KEY_CONFIG"
+key 172   HOME
+# key 173 "KEY_REFRESH"
+# key 174 "KEY_EXIT"
+# key 175 "KEY_MOVE"
+# key 176 "KEY_EDIT"
+key 177   PAGE_UP
+key 178   PAGE_DOWN
+key 179   NUMPAD_LEFT_PAREN
+key 180   NUMPAD_RIGHT_PAREN
+# key 181 "KEY_NEW"
+# key 182 "KEY_REDO"
+# key 183   F13
+# key 184   F14
+# key 185   F15
+# key 186   F16
+# key 187   F17
+# key 188   F18
+# key 189   F19
+# key 190   F20
+# key 191   F21
+# key 192   F22
+# key 193   F23
+# key 194   F24
+# key 195 (undefined)
+# key 196 (undefined)
+# key 197 (undefined)
+# key 198 (undefined)
+# key 199 (undefined)
+key 200   MEDIA_PLAY
+key 201   MEDIA_PAUSE
+# key 202 "KEY_PROG3"
+# key 203 "KEY_PROG4"
+# key 204 (undefined)
+# key 205 "KEY_SUSPEND"
+# key 206 "KEY_CLOSE"
+key 207   MEDIA_PLAY
+key 208   MEDIA_FAST_FORWARD
+# key 209 "KEY_BASSBOOST"
+# key 210 "KEY_PRINT"
+# key 211 "KEY_HP"
+key 212   CAMERA
+# key 213 "KEY_SOUND"
+# key 214 "KEY_QUESTION"
+key 215   ENVELOPE
+# key 216 "KEY_CHAT"
+key 217   SEARCH
+# key 218 "KEY_CONNECT"
+# key 219 "KEY_FINANCE"
+# key 220 "KEY_SPORT"
+# key 221 "KEY_SHOP"
+# key 222 "KEY_ALTERASE"
+# key 223 "KEY_CANCEL"
+# key 224 "KEY_BRIGHTNESSDOWN"
+# key 225 "KEY_BRIGHTNESSUP"
+key 226   HEADSETHOOK
+key 227   STAR
+key 228   POUND
+key 229   SOFT_LEFT
+key 230   SOFT_RIGHT
+key 231   CALL
+key 232   DPAD_CENTER
+key 233   HEADSETHOOK
+# key 234 "KEY_0_5" or "KEY_SAVE"
+# key 235 "KEY_2_5" or "KEY_DOCUMENTS"
+# key 236 "KEY_SWITCHVIDEOMODE" or "KEY_BATTERY"
+# key 237 "KEY_KBDILLUMTOGGLE"
+# key 238 "KEY_KBDILLUMDOWN"
+# key 239 "KEY_KBDILLUMUP"
+# key 240 "KEY_UNKNOWN"
+
+
+key 304   BUTTON_A
+key 305   BUTTON_B
+key 306   BUTTON_C
+key 307   BUTTON_X
+key 308   BUTTON_Y
+key 309   BUTTON_Z
+key 310   BUTTON_L1
+key 311   BUTTON_R1
+key 312   BUTTON_L2
+key 313   BUTTON_R2
+key 314   BUTTON_SELECT
+key 315   BUTTON_START
+key 316   BUTTON_MODE
+key 317   BUTTON_THUMBL
+key 318   BUTTON_THUMBR
+
+
+# key 352 "KEY_OK"
+# key 353 "KEY_SELECT"
+# key 354 "KEY_GOTO"
+# key 355 "KEY_CLEAR"
+# key 356 "KEY_POWER2"
+# key 357 "KEY_OPTION"
+# key 358 "KEY_INFO"
+# key 359 "KEY_TIME"
+# key 360 "KEY_VENDOR"
+# key 361 "KEY_ARCHIVE"
+# key 362 "KEY_PROGRAM"
+# key 363 "KEY_CHANNEL"
+# key 364 "KEY_FAVORITES"
+# key 365 "KEY_EPG"
+# key 366 "KEY_PVR"
+# key 367 "KEY_MHP"
+# key 368 "KEY_LANGUAGE"
+# key 369 "KEY_TITLE"
+# key 370 "KEY_SUBTITLE"
+# key 371 "KEY_ANGLE"
+# key 372 "KEY_ZOOM"
+# key 373 "KEY_MODE"
+# key 374 "KEY_KEYBOARD"
+# key 375 "KEY_SCREEN"
+# key 376 "KEY_PC"
+# key 377 "KEY_TV"
+# key 378 "KEY_TV2"
+# key 379 "KEY_VCR"
+# key 380 "KEY_VCR2"
+# key 381 "KEY_SAT"
+# key 382 "KEY_SAT2"
+# key 383 "KEY_CD"
+# key 384 "KEY_TAPE"
+# key 385 "KEY_RADIO"
+# key 386 "KEY_TUNER"
+# key 387 "KEY_PLAYER"
+# key 388 "KEY_TEXT"
+# key 389 "KEY_DVD"
+# key 390 "KEY_AUX"
+# key 391 "KEY_MP3"
+# key 392 "KEY_AUDIO"
+# key 393 "KEY_VIDEO"
+# key 394 "KEY_DIRECTORY"
+# key 395 "KEY_LIST"
+# key 396 "KEY_MEMO"
+# key 397 "KEY_CALENDAR"
+# key 398 "KEY_RED"
+# key 399 "KEY_GREEN"
+# key 400 "KEY_YELLOW"
+# key 401 "KEY_BLUE"
+# key 402 "KEY_CHANNELUP"
+# key 403 "KEY_CHANNELDOWN"
+# key 404 "KEY_FIRST"
+# key 405 "KEY_LAST"
+# key 406 "KEY_AB"
+# key 407 "KEY_NEXT"
+# key 408 "KEY_RESTART"
+# key 409 "KEY_SLOW"
+# key 410 "KEY_SHUFFLE"
+# key 411 "KEY_BREAK"
+# key 412 "KEY_PREVIOUS"
+# key 413 "KEY_DIGITS"
+# key 414 "KEY_TEEN"
+# key 415 "KEY_TWEN"
+
+
+# key 448 "KEY_DEL_EOL"
+# key 449 "KEY_DEL_EOS"
+# key 450 "KEY_INS_LINE"
+# key 451 "KEY_DEL_LINE"
+
+
+key 464   FUNCTION
+key 465   ESCAPE            FUNCTION
+key 466   F1                FUNCTION
+key 467   F2                FUNCTION
+key 468   F3                FUNCTION
+key 469   F4                FUNCTION
+key 470   F5                FUNCTION
+key 471   F6                FUNCTION
+key 472   F7                FUNCTION
+key 473   F8                FUNCTION
+key 474   F9                FUNCTION
+key 475   F10               FUNCTION
+key 476   F11               FUNCTION
+key 477   F12               FUNCTION
+key 478   1                 FUNCTION
+key 479   2                 FUNCTION
+key 480   D                 FUNCTION
+key 481   E                 FUNCTION
+key 482   F                 FUNCTION
+key 483   S                 FUNCTION
+key 484   B                 FUNCTION
+
+
+# key 497 KEY_BRL_DOT1
+# key 498 KEY_BRL_DOT2
+# key 499 KEY_BRL_DOT3
+# key 500 KEY_BRL_DOT4
+# key 501 KEY_BRL_DOT5
+# key 502 KEY_BRL_DOT6
+# key 503 KEY_BRL_DOT7
+# key 504 KEY_BRL_DOT8
diff --git a/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kcm b/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kcm
new file mode 100644
index 0000000..0f31683
--- /dev/null
+++ b/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kcm
@@ -0,0 +1,71 @@
+# 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.
+
+[type=QWERTY]
+
+# keycode       display number  base    caps    fn      caps_fn
+
+A               'A'     '2'     'a'     'A'     'a'     'A'
+B               'B'     '2'     'b'     'B'     'b'     'B'
+C               'C'     '2'     'c'     'C'     'c'     'C'
+D               'D'     '3'     'd'     'D'     'd'     'D'
+E               'E'     '3'     'e'     'E'     'e'     'E'
+F               'F'     '3'     'f'     'F'     'f'     'F'
+G               'G'     '4'     'g'     'G'     'g'     'G'
+H               'H'     '4'     'h'     'H'     'h'     'H'
+I               'I'     '4'     'i'     'I'     'i'     'I'
+J               'J'     '5'     'j'     'J'     'j'     'J'
+K               'K'     '5'     'k'     'K'     'k'     'K'
+L               'L'     '5'     'l'     'L'     'l'     'L'
+M               'M'     '6'     'm'     'M'     'm'     'M'
+N               'N'     '6'     'n'     'N'     'n'     'N'
+O               'O'     '6'     'o'     'O'     'o'     'O'
+P               'P'     '7'     'p'     'P'     'p'     'P'
+Q               'Q'     '7'     'q'     'Q'     'q'     'Q'
+R               'R'     '7'     'r'     'R'     'r'     'R'
+S               'S'     '7'     's'     'S'     's'     'S'
+T               'T'     '8'     't'     'T'     't'     'T'
+U               'U'     '8'     'u'     'U'     'u'     'U'
+V               'V'     '8'     'v'     'V'     'v'     'V'
+W               'W'     '9'     'w'     'W'     'w'     'W'
+X               'X'     '9'     'x'     'X'     'x'     'X'
+Y               'Y'     '9'     'y'     'Y'     'y'     'Y'
+Z               'Z'     '9'     'z'     'Z'     'z'     'Z'
+
+0               '0'     '0'     '0'     ')'     '0'     ')'
+1               '1'     '1'     '1'     '!'     '1'     '!'
+2               '2'     '2'     '2'     '@'     '2'     '@'
+3               '3'     '3'     '3'     '#'     '3'     '#'
+4               '4'     '4'     '4'     '$'     '4'     '$'
+5               '5'     '5'     '5'     '%'     '5'     '%'
+6               '6'     '6'     '6'     '^'     '6'     '^'
+7               '7'     '7'     '7'     '&'     '7'     '&'
+8               '8'     '8'     '8'     '*'     '8'     '*'
+9               '9'     '9'     '9'     '('     '9'     '('
+
+SPACE           0x20    0x20    0x20    0x20    0x20    0x20
+ENTER           0xa     0xa     0xa     0xa     0xa     0xa
+TAB             0x9     0x9     0x9     0x9     0x9     0x9
+
+COMMA           ','     ','     ','     '<'     ','     '<'
+PERIOD          '.'     '.'     '.'     '>'     '.'     '>'
+SLASH           '/'     '/'     '/'     '?'     '/'     '?'
+GRAVE           '`'     '`'     '`'     '~'     '`'     '~'
+MINUS           '-'     '-'     '-'     '_'     '-'     '_'
+EQUALS          '='     '='     '='     '+'     '='     '+'
+LEFT_BRACKET    '['     '['     '['     '{'     '['     '{'
+RIGHT_BRACKET   ']'     ']'     ']'     '}'     ']'     '}'
+BACKSLASH       '\'     '\'     '\'     '|'     '\'     '|'
+SEMICOLON       ';'     ';'     ';'     ':'     ';'     ':'
+APOSTROPHE      '''     '''     '''     '"'     '''     '"'
diff --git a/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl b/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl
new file mode 100644
index 0000000..1298d53
--- /dev/null
+++ b/data/keyboards/Motorola_Bluetooth_Wireless_Keyboard.kl
@@ -0,0 +1,96 @@
+# 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.
+
+key 1     BACK
+key 2     1
+key 3     2
+key 4     3
+key 5     4
+key 6     5
+key 7     6
+key 8     7
+key 9     8
+key 10    9
+key 11    0
+key 12    MINUS
+key 13    EQUALS
+key 14    DEL
+key 15    TAB
+key 16    Q
+key 17    W
+key 18    E
+key 19    R
+key 20    T
+key 21    Y
+key 22    U
+key 23    I
+key 24    O
+key 25    P
+key 26    LEFT_BRACKET
+key 27    RIGHT_BRACKET
+key 28    ENTER
+key 29    CTRL_LEFT
+key 30    A
+key 31    S
+key 32    D
+key 33    F
+key 34    G
+key 35    H
+key 36    J
+key 37    K
+key 38    L
+key 39    SEMICOLON
+key 40    APOSTROPHE
+key 41    GRAVE
+key 42    SHIFT_LEFT
+key 43    BACKSLASH
+key 44    Z
+key 45    X
+key 46    C
+key 47    V
+key 48    B
+key 49    N
+key 50    M
+key 51    COMMA
+key 52    PERIOD
+key 53    SLASH
+key 54    SHIFT_RIGHT
+key 57    SPACE
+key 58    CAPS_LOCK
+key 59    F1
+key 60    F2
+key 61    F3
+key 62    F4
+key 63    F5
+key 64    F6
+key 65    F7
+key 66    F8
+key 67    F9
+key 97    CTRL_RIGHT
+key 102   HOME
+key 103   DPAD_UP
+key 105   DPAD_LEFT
+key 106   DPAD_RIGHT
+key 107   MOVE_END
+key 110   INSERT
+key 111   FORWARD_DEL
+key 113   MUTE
+key 114   VOLUME_DOWN
+key 115   VOLUME_UP
+key 125   MENU
+key 127   SEARCH
+key 163   MEDIA_NEXT
+key 164   MEDIA_PLAY_PAUSE
+key 165   MEDIA_PREVIOUS
+key 166   MEDIA_STOP
diff --git a/data/keyboards/common.mk b/data/keyboards/common.mk
new file mode 100644
index 0000000..7a58b07
--- /dev/null
+++ b/data/keyboards/common.mk
@@ -0,0 +1,24 @@
+# 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.
+
+# This is the list of keylayouts and key character maps to build.
+# Used by Android.mk and keyboards.mk.
+
+keylayouts := \
+    Generic.kl \
+    Motorola_Bluetooth_Wireless_Keyboard.kl
+
+keycharmaps := \
+    Generic.kcm \
+    Motorola_Bluetooth_Wireless_Keyboard.kcm
diff --git a/data/keyboards/keyboards.mk b/data/keyboards/keyboards.mk
new file mode 100644
index 0000000..665c8bf
--- /dev/null
+++ b/data/keyboards/keyboards.mk
@@ -0,0 +1,22 @@
+# 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.
+
+# Warning: this is actually a product definition, to be inherited from
+
+include $(LOCAL_PATH)/common.mk
+
+PRODUCT_COPY_FILES := $(foreach file,$(keylayouts),\
+    frameworks/base/data/keyboards/$(file):system/usr/keylayout/$(file))
+
+PRODUCT_PACKAGES := $(keycharmaps)
diff --git a/include/ui/EventHub.h b/include/ui/EventHub.h
index d78e35f..1431964 100644
--- a/include/ui/EventHub.h
+++ b/include/ui/EventHub.h
@@ -187,6 +187,9 @@
     virtual bool markSupportedKeyCodes(int32_t deviceId, size_t numCodes, const int32_t* keyCodes,
             uint8_t* outFlags) const = 0;
 
+    virtual bool hasLed(int32_t deviceId, int32_t led) const = 0;
+    virtual void setLedState(int32_t deviceId, int32_t led, bool on) = 0;
+
     virtual void dump(String8& dump) = 0;
 };
 
@@ -198,9 +201,9 @@
     status_t errorCheck() const;
 
     virtual uint32_t getDeviceClasses(int32_t deviceId) const;
-    
+
     virtual String8 getDeviceName(int32_t deviceId) const;
-    
+
     virtual status_t getAbsoluteAxisInfo(int32_t deviceId, int axis,
             RawAbsoluteAxisInfo* outAxisInfo) const;
 
@@ -218,6 +221,9 @@
 
     virtual bool getEvent(RawEvent* outEvent);
 
+    virtual bool hasLed(int32_t deviceId, int32_t led) const;
+    virtual void setLedState(int32_t deviceId, int32_t led, bool on);
+
     virtual void dump(String8& dump);
 
 protected:
@@ -240,7 +246,10 @@
         uint32_t        classes;
         uint8_t*        keyBitmask;
         KeyLayoutMap*   layoutMap;
-        String8         keylayoutFilename;
+        String8         keyMapName;
+        bool            defaultKeyMap;
+        String8         keyLayoutFilename;
+        String8         keyCharacterMapFilename;
         int             fd;
         device_t*       next;
         
@@ -250,13 +259,19 @@
 
     device_t* getDeviceLocked(int32_t deviceId) const;
     bool hasKeycodeLocked(device_t* device, int keycode) const;
-    
+
     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;
 
+    void configureKeyMap(device_t* device);
+    bool probeKeyMap(device_t* device, const String8& keyMapName, bool defaultKeyMap);
+    void selectKeyMap(device_t* device, const String8& keyMapName, bool defaultKeyMap);
+    void setKeyboardProperties(device_t* device, bool firstKeyboard);
+    void clearKeyboardProperties(device_t* device, bool firstKeyboard);
+
     // Protect all internal state.
     mutable Mutex   mLock;
     
diff --git a/include/ui/Input.h b/include/ui/Input.h
index 8c6018b..1355bab 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -76,7 +76,7 @@
  */
 enum {
     /* These flags originate in RawEvents and are generally set in the key map.
-     * See also labels for policy flags in KeycodeLabels.h. */
+     * NOTE: If you edit these flags, also edit labels in KeycodeLabels.h. */
 
     POLICY_FLAG_WAKE = 0x00000001,
     POLICY_FLAG_WAKE_DROPPED = 0x00000002,
@@ -87,6 +87,7 @@
     POLICY_FLAG_MENU = 0x00000040,
     POLICY_FLAG_LAUNCHER = 0x00000080,
     POLICY_FLAG_VIRTUAL = 0x00000100,
+    POLICY_FLAG_FUNCTION = 0x00000200,
 
     POLICY_FLAG_RAW_MASK = 0x0000ffff,
 
diff --git a/include/ui/InputDispatcher.h b/include/ui/InputDispatcher.h
index 63185d3..b811ace 100644
--- a/include/ui/InputDispatcher.h
+++ b/include/ui/InputDispatcher.h
@@ -183,6 +183,7 @@
         TYPE_INPUT_METHOD_DIALOG= FIRST_SYSTEM_WINDOW+12,
         TYPE_WALLPAPER          = FIRST_SYSTEM_WINDOW+13,
         TYPE_STATUS_BAR_PANEL   = FIRST_SYSTEM_WINDOW+14,
+        TYPE_SECURE_SYSTEM_OVERLAY = FIRST_SYSTEM_WINDOW+15,
         LAST_SYSTEM_WINDOW      = 2999,
     };
 
diff --git a/include/ui/InputReader.h b/include/ui/InputReader.h
index c15e382..a1b59e6 100644
--- a/include/ui/InputReader.h
+++ b/include/ui/InputReader.h
@@ -419,9 +419,18 @@
         Vector<KeyDown> keyDowns; // keys that are down
         int32_t metaState;
         nsecs_t downTime; // time of most recent key down
+
+        struct LedState {
+            bool avail; // led is available
+            bool on;    // we think the led is currently on
+        };
+        LedState capsLockLedState;
+        LedState numLockLedState;
+        LedState scrollLockLedState;
     } mLocked;
 
     void initializeLocked();
+    void initializeLedStateLocked(LockedState::LedState& ledState, int32_t led);
 
     bool isKeyboardOrGamepadKey(int32_t scanCode);
 
@@ -429,6 +438,10 @@
             uint32_t policyFlags);
 
     ssize_t findKeyDownLocked(int32_t scanCode);
+
+    void updateLedStateLocked(bool reset);
+    void updateLedStateForModifierLocked(LockedState::LedState& ledState, int32_t led,
+            int32_t modifier, bool reset);
 };
 
 
diff --git a/include/ui/KeycodeLabels.h b/include/ui/KeycodeLabels.h
index f71d9cd..ef2b6b3 100755
--- a/include/ui/KeycodeLabels.h
+++ b/include/ui/KeycodeLabels.h
@@ -135,6 +135,59 @@
     { "BUTTON_START", 108 },
     { "BUTTON_SELECT", 109 },
     { "BUTTON_MODE", 110 },
+    { "ESCAPE", 111 },
+    { "FORWARD_DEL", 112 },
+    { "CTRL_LEFT", 113 },
+    { "CTRL_RIGHT", 114 },
+    { "CAPS_LOCK", 115 },
+    { "SCROLL_LOCK", 116 },
+    { "META_LEFT", 117 },
+    { "META_RIGHT", 118 },
+    { "FUNCTION", 119 },
+    { "SYSRQ", 120 },
+    { "BREAK", 121 },
+    { "MOVE_HOME", 122 },
+    { "MOVE_END", 123 },
+    { "INSERT", 124 },
+    { "FORWARD", 125 },
+    { "MEDIA_PLAY", 126 },
+    { "MEDIA_PAUSE", 127 },
+    { "MEDIA_CLOSE", 128 },
+    { "MEDIA_EJECT", 129 },
+    { "MEDIA_RECORD", 130 },
+    { "F1", 131 },
+    { "F2", 132 },
+    { "F3", 133 },
+    { "F4", 134 },
+    { "F5", 135 },
+    { "F6", 136 },
+    { "F7", 137 },
+    { "F8", 138 },
+    { "F9", 139 },
+    { "F10", 140 },
+    { "F11", 141 },
+    { "F12", 142 },
+    { "NUM_LOCK", 143 },
+    { "NUMPAD_0", 144 },
+    { "NUMPAD_1", 145 },
+    { "NUMPAD_2", 146 },
+    { "NUMPAD_3", 147 },
+    { "NUMPAD_4", 148 },
+    { "NUMPAD_5", 149 },
+    { "NUMPAD_6", 150 },
+    { "NUMPAD_7", 151 },
+    { "NUMPAD_8", 152 },
+    { "NUMPAD_9", 153 },
+    { "NUMPAD_DIVIDE", 154 },
+    { "NUMPAD_MULTIPLY", 155 },
+    { "NUMPAD_SUBTRACT", 156 },
+    { "NUMPAD_ADD", 157 },
+    { "NUMPAD_DOT", 158 },
+    { "NUMPAD_COMMA", 159 },
+    { "NUMPAD_ENTER", 160 },
+    { "NUMPAD_EQUALS", 161 },
+    { "NUMPAD_LEFT_PAREN", 162 },
+    { "NUMPAD_RIGHT_PAREN", 163 },
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
@@ -142,7 +195,7 @@
     { NULL, 0 }
 };
 
-// See also policy flags in Input.h.
+// NOTE: If you edit these flags, also edit policy flags in Input.h.
 static const KeycodeLabel FLAGS[] = {
     { "WAKE", 0x00000001 },
     { "WAKE_DROPPED", 0x00000002 },
@@ -153,6 +206,7 @@
     { "MENU", 0x00000040 },
     { "LAUNCHER", 0x00000080 },
     { "VIRTUAL", 0x00000100 },
+    { "FUNCTION", 0x00000200 },
     { NULL, 0 }
 };
 
diff --git a/include/utils/String8.h b/include/utils/String8.h
index ef0b51a..cef8eca 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -157,9 +157,12 @@
     inline  size_t              size() const;
     inline  size_t              length() const;
     inline  size_t              bytes() const;
+    inline  bool                isEmpty() const;
     
     inline  const SharedBuffer* sharedBuffer() const;
     
+            void                clear();
+
             void                setTo(const String8& other);
             status_t            setTo(const char* other);
             status_t            setTo(const char* other, size_t numChars);
@@ -345,6 +348,11 @@
     return length();
 }
 
+inline bool String8::isEmpty() const
+{
+    return length() == 0;
+}
+
 inline size_t String8::bytes() const
 {
     return SharedBuffer::sizeFromData(mString)-1;
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 0a95408..97bb73f 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -865,6 +865,10 @@
     fontRenderer.setFont(paint, SkTypeface::UniqueID(paint->getTypeface()),
             paint->getTextSize());
 
+    Rect clipRect(*mSnapshot->clipRect);
+    glScissor(clipRect.left, mSnapshot->height - clipRect.bottom,
+            clipRect.getWidth(), clipRect.getHeight());
+
     if (mHasShadow) {
         glActiveTexture(gTextureUnits[0]);
         mCaches.dropShadowCache.setFontRenderer(fontRenderer);
@@ -889,12 +893,15 @@
 
     const Rect& clip = mSnapshot->getLocalClip();
     clearLayerRegions();
+
     fontRenderer.renderText(paint, &clip, text, 0, bytesCount, count, x, y);
 
     glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
     glDisableVertexAttribArray(mCaches.currentProgram->getAttrib("texCoords"));
 
     drawTextDecorations(text, bytesCount, length, x, y, paint);
+
+    setScissorFromClip();
 }
 
 void OpenGLRenderer::drawPath(SkPath* path, SkPaint* paint) {
diff --git a/libs/ui/EventHub.cpp b/libs/ui/EventHub.cpp
index 944731d..97a7528 100644
--- a/libs/ui/EventHub.cpp
+++ b/libs/ui/EventHub.cpp
@@ -94,7 +94,7 @@
 
 EventHub::device_t::device_t(int32_t _id, const char* _path, const char* name)
     : id(_id), path(_path), name(name), classes(0)
-    , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), fd(-1), next(NULL) {
+    , keyBitmask(NULL), layoutMap(new KeyLayoutMap()), defaultKeyMap(false), fd(-1), next(NULL) {
 }
 
 EventHub::device_t::~device_t() {
@@ -103,7 +103,7 @@
 }
 
 EventHub::EventHub(void)
-    : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(0)
+    : mError(NO_INIT), mHaveFirstKeyboard(false), mFirstKeyboardId(-1)
     , mDevicesById(0), mNumDevicesById(0)
     , mOpeningDevices(0), mClosingDevices(0)
     , mDevices(0), mFDs(0), mFDCount(0), mOpened(false), mNeedToSendFinishedDeviceScan(false)
@@ -325,6 +325,39 @@
     mExcludedDevices.push_back(name);
 }
 
+bool EventHub::hasLed(int32_t deviceId, int32_t led) const {
+    AutoMutex _l(mLock);
+    device_t* device = getDeviceLocked(deviceId);
+    if (device) {
+        uint8_t bitmask[sizeof_bit_array(LED_MAX + 1)];
+        memset(bitmask, 0, sizeof(bitmask));
+        if (ioctl(device->fd, EVIOCGBIT(EV_LED, sizeof(bitmask)), bitmask) >= 0) {
+            if (test_bit(led, bitmask)) {
+                return true;
+            }
+        }
+    }
+    return false;
+}
+
+void EventHub::setLedState(int32_t deviceId, int32_t led, bool on) {
+    AutoMutex _l(mLock);
+    device_t* device = getDeviceLocked(deviceId);
+    if (device) {
+        struct input_event ev;
+        ev.time.tv_sec = 0;
+        ev.time.tv_usec = 0;
+        ev.type = EV_LED;
+        ev.code = led;
+        ev.value = on ? 1 : 0;
+
+        ssize_t nWrite;
+        do {
+            nWrite = write(device->fd, &ev, sizeof(struct input_event));
+        } while (nWrite == -1 && errno == EINTR);
+    }
+}
+
 EventHub::device_t* EventHub::getDeviceLocked(int32_t deviceId) const
 {
     if (deviceId == 0) deviceId = mFirstKeyboardId;
@@ -760,54 +793,42 @@
 #endif
 
     if ((device->classes & INPUT_DEVICE_CLASS_KEYBOARD) != 0) {
-        char tmpfn[sizeof(name)];
-        char keylayoutFilename[300];
-
         // a more descriptive name
         device->name = name;
 
-        // replace all the spaces with underscores
-        strcpy(tmpfn, name);
-        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
-            *p = '_';
+        // Configure the keymap for the device.
+        configureKeyMap(device);
 
-        // find the .kl file we need for this device
-        const char* root = getenv("ANDROID_ROOT");
-        snprintf(keylayoutFilename, sizeof(keylayoutFilename),
-                 "%s/usr/keylayout/%s.kl", root, tmpfn);
-        bool defaultKeymap = false;
-        if (access(keylayoutFilename, R_OK)) {
-            snprintf(keylayoutFilename, sizeof(keylayoutFilename),
-                     "%s/usr/keylayout/%s", root, "qwerty.kl");
-            defaultKeymap = true;
-        }
-        status_t status = device->layoutMap->load(keylayoutFilename);
-        if (status) {
-            LOGE("Error %d loading key layout.", status);
-        }
-
-        // tell the world about the devname (the descriptive name)
-        if (!mHaveFirstKeyboard && !defaultKeymap && strstr(name, "-keypad")) {
+        // Tell the world about the devname (the descriptive name)
+        if (!mHaveFirstKeyboard && !device->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);
+            setKeyboardProperties(device, true);
         } else {
             // ensure mFirstKeyboardId is set to -something-.
-            if (mFirstKeyboardId == 0) {
+            if (mFirstKeyboardId == -1) {
                 mFirstKeyboardId = device->id;
+                setKeyboardProperties(device, true);
             }
         }
-        char propName[100];
-        sprintf(propName, "hw.keyboards.%u.devname", device->id);
-        property_set(propName, name);
+        setKeyboardProperties(device, false);
+
+        // Load the keylayout.
+        if (!device->keyLayoutFilename.isEmpty()) {
+            status_t status = device->layoutMap->load(device->keyLayoutFilename);
+            if (status) {
+                LOGE("Error %d loading key layout file '%s'.", status,
+                        device->keyLayoutFilename.string());
+            }
+        }
 
         // 'Q' key support = cheap test of whether this is an alpha-capable kbd
         if (hasKeycodeLocked(device, AKEYCODE_Q)) {
             device->classes |= INPUT_DEVICE_CLASS_ALPHAKEY;
         }
-        
+
         // See if this device has a DPAD.
         if (hasKeycodeLocked(device, AKEYCODE_DPAD_UP) &&
                 hasKeycodeLocked(device, AKEYCODE_DPAD_DOWN) &&
@@ -816,7 +837,7 @@
                 hasKeycodeLocked(device, AKEYCODE_DPAD_CENTER)) {
             device->classes |= INPUT_DEVICE_CLASS_DPAD;
         }
-        
+
         // See if this device has a gamepad.
         for (size_t i = 0; i < sizeof(GAMEPAD_KEYCODES); i++) {
             if (hasKeycodeLocked(device, GAMEPAD_KEYCODES[i])) {
@@ -825,8 +846,9 @@
             }
         }
 
-        LOGI("New keyboard: device->id=0x%x devname='%s' propName='%s' keylayout='%s'\n",
-                device->id, name, propName, keylayoutFilename);
+        LOGI("New keyboard: device->id=0x%x devname='%s' keylayout='%s' keycharactermap='%s'\n",
+                device->id, name,
+                device->keyLayoutFilename.string(), device->keyCharacterMapFilename.string());
     }
 
     // If the device isn't recognized as something we handle, don't monitor it.
@@ -852,6 +874,109 @@
     return 0;
 }
 
+void EventHub::configureKeyMap(device_t* device) {
+    // As an initial key map name, try using the device name.
+    String8 keyMapName(device->name);
+    char* p = keyMapName.lockBuffer(keyMapName.size());
+    while (*p) {
+        if (*p == ' ') *p = '_';
+        p++;
+    }
+    keyMapName.unlockBuffer();
+
+    if (probeKeyMap(device, keyMapName, false)) return;
+
+    // TODO Consider allowing the user to configure a specific key map somehow.
+
+    // Try the Generic key map.
+    // TODO Apply some additional heuristics here to figure out what kind of
+    //      generic key map to use (US English, etc.).
+    keyMapName.setTo("Generic");
+    if (probeKeyMap(device, keyMapName, true)) return;
+
+    // Fall back on the old style catchall qwerty key map.
+    keyMapName.setTo("qwerty");
+    if (probeKeyMap(device, keyMapName, true)) return;
+
+    // Give up!
+    keyMapName.setTo("unknown");
+    selectKeyMap(device, keyMapName, true);
+    LOGE("Could not determine key map for device '%s'.", device->name.string());
+}
+
+bool EventHub::probeKeyMap(device_t* device, const String8& keyMapName, bool defaultKeyMap) {
+    const char* root = getenv("ANDROID_ROOT");
+
+    // TODO Consider also looking somewhere in a writeable partition like /data for a
+    //      custom keymap supplied by the user for this device.
+    bool haveKeyLayout = !device->keyLayoutFilename.isEmpty();
+    if (!haveKeyLayout) {
+        device->keyLayoutFilename.setTo(root);
+        device->keyLayoutFilename.append("/usr/keylayout/");
+        device->keyLayoutFilename.append(keyMapName);
+        device->keyLayoutFilename.append(".kl");
+        if (access(device->keyLayoutFilename.string(), R_OK)) {
+            device->keyLayoutFilename.clear();
+        } else {
+            haveKeyLayout = true;
+        }
+    }
+
+    bool haveKeyCharacterMap = !device->keyCharacterMapFilename.isEmpty();
+    if (!haveKeyCharacterMap) {
+        device->keyCharacterMapFilename.setTo(root);
+        device->keyCharacterMapFilename.append("/usr/keychars/");
+        device->keyCharacterMapFilename.append(keyMapName);
+        device->keyCharacterMapFilename.append(".kcm.bin");
+        if (access(device->keyCharacterMapFilename.string(), R_OK)) {
+            device->keyCharacterMapFilename.clear();
+        } else {
+            haveKeyCharacterMap = true;
+        }
+    }
+
+    if (haveKeyLayout || haveKeyCharacterMap) {
+        selectKeyMap(device, keyMapName, defaultKeyMap);
+    }
+    return haveKeyLayout && haveKeyCharacterMap;
+}
+
+void EventHub::selectKeyMap(device_t* device,
+        const String8& keyMapName, bool defaultKeyMap) {
+    if (device->keyMapName.isEmpty()) {
+        device->keyMapName.setTo(keyMapName);
+        device->defaultKeyMap = defaultKeyMap;
+    }
+}
+
+void EventHub::setKeyboardProperties(device_t* device, bool firstKeyboard) {
+    int32_t id = firstKeyboard ? 0 : device->id;
+
+    char propName[100];
+    sprintf(propName, "hw.keyboards.%u.devname", id);
+    property_set(propName, device->name.string());
+    sprintf(propName, "hw.keyboards.%u.keymap", id);
+    property_set(propName, device->keyMapName.string());
+    sprintf(propName, "hw.keyboards.%u.klfile", id);
+    property_set(propName, device->keyLayoutFilename.string());
+    sprintf(propName, "hw.keyboards.%u.kcmfile", id);
+    property_set(propName, device->keyCharacterMapFilename.string());
+}
+
+void EventHub::clearKeyboardProperties(device_t* device, bool firstKeyboard) {
+    int32_t id = firstKeyboard ? 0 : device->id;
+
+    char propName[100];
+    sprintf(propName, "hw.keyboards.%u.devname", id);
+    property_set(propName, "");
+    sprintf(propName, "hw.keyboards.%u.keymap", id);
+    property_set(propName, "");
+    sprintf(propName, "hw.keyboards.%u.klfile", id);
+    property_set(propName, "");
+    sprintf(propName, "hw.keyboards.%u.kcmfile", id);
+    property_set(propName, "");
+}
+
 bool EventHub::hasKeycodeLocked(device_t* device, int keycode) const
 {
     if (device->keyBitmask == NULL || device->layoutMap == NULL) {
@@ -909,13 +1034,10 @@
             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;
-                property_set("hw.keyboards.0.devname", NULL);
+                mFirstKeyboardId = -1;
+                clearKeyboardProperties(device, true);
             }
-            // clear the property
-            char propName[100];
-            sprintf(propName, "hw.keyboards.%u.devname", device->id);
-            property_set(propName, NULL);
+            clearKeyboardProperties(device, false);
             return 0;
         }
     }
@@ -1014,7 +1136,11 @@
                 }
                 dump.appendFormat(INDENT3 "Classes: 0x%08x\n", device->classes);
                 dump.appendFormat(INDENT3 "Path: %s\n", device->path.string());
-                dump.appendFormat(INDENT3 "KeyLayoutFile: %s\n", device->keylayoutFilename.string());
+                dump.appendFormat(INDENT3 "KeyMapName: %s\n", device->keyMapName.string());
+                dump.appendFormat(INDENT3 "KeyLayoutFilename: %s\n",
+                        device->keyLayoutFilename.string());
+                dump.appendFormat(INDENT3 "KeyCharacterMapFilename: %s\n",
+                        device->keyCharacterMapFilename.string());
             }
         }
     } // release lock
diff --git a/libs/ui/InputDispatcher.cpp b/libs/ui/InputDispatcher.cpp
index 84c3db8..949dc4d 100644
--- a/libs/ui/InputDispatcher.cpp
+++ b/libs/ui/InputDispatcher.cpp
@@ -149,7 +149,8 @@
 
 bool InputWindow::isTrustedOverlay() const {
     return layoutParamsType == TYPE_INPUT_METHOD
-            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG;
+            || layoutParamsType == TYPE_INPUT_METHOD_DIALOG
+            || layoutParamsType == TYPE_SECURE_SYSTEM_OVERLAY;
 }
 
 
@@ -1350,7 +1351,7 @@
         target.flags = 0;
         target.xOffset = 0;
         target.yOffset = 0;
-        target.windowType = InputWindow::TYPE_SYSTEM_OVERLAY;
+        target.windowType = -1;
     }
 }
 
diff --git a/libs/ui/InputReader.cpp b/libs/ui/InputReader.cpp
index 0560bb8..6225121 100644
--- a/libs/ui/InputReader.cpp
+++ b/libs/ui/InputReader.cpp
@@ -70,32 +70,15 @@
     return value ? "true" : "false";
 }
 
-
-int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
-    int32_t mask;
-    switch (keyCode) {
-    case AKEYCODE_ALT_LEFT:
-        mask = AMETA_ALT_LEFT_ON;
-        break;
-    case AKEYCODE_ALT_RIGHT:
-        mask = AMETA_ALT_RIGHT_ON;
-        break;
-    case AKEYCODE_SHIFT_LEFT:
-        mask = AMETA_SHIFT_LEFT_ON;
-        break;
-    case AKEYCODE_SHIFT_RIGHT:
-        mask = AMETA_SHIFT_RIGHT_ON;
-        break;
-    case AKEYCODE_SYM:
-        mask = AMETA_SYM_ON;
-        break;
-    default:
-        return oldMetaState;
+int32_t setEphemeralMetaState(int32_t mask, bool down, int32_t oldMetaState) {
+    int32_t newMetaState;
+    if (down) {
+        newMetaState = oldMetaState | mask;
+    } else {
+        newMetaState = oldMetaState &
+                ~(mask | AMETA_ALT_ON | AMETA_SHIFT_ON | AMETA_CTRL_ON | AMETA_META_ON);
     }
 
-    int32_t newMetaState = down ? oldMetaState | mask : oldMetaState & ~ mask
-            & ~ (AMETA_ALT_ON | AMETA_SHIFT_ON);
-
     if (newMetaState & (AMETA_ALT_LEFT_ON | AMETA_ALT_RIGHT_ON)) {
         newMetaState |= AMETA_ALT_ON;
     }
@@ -104,9 +87,58 @@
         newMetaState |= AMETA_SHIFT_ON;
     }
 
+    if (newMetaState & (AMETA_CTRL_LEFT_ON | AMETA_CTRL_RIGHT_ON)) {
+        newMetaState |= AMETA_CTRL_ON;
+    }
+
+    if (newMetaState & (AMETA_META_LEFT_ON | AMETA_META_RIGHT_ON)) {
+        newMetaState |= AMETA_META_ON;
+    }
     return newMetaState;
 }
 
+int32_t toggleLockedMetaState(int32_t mask, bool down, int32_t oldMetaState) {
+    if (down) {
+        return oldMetaState;
+    } else {
+        return oldMetaState ^ mask;
+    }
+}
+
+int32_t updateMetaState(int32_t keyCode, bool down, int32_t oldMetaState) {
+    int32_t mask;
+    switch (keyCode) {
+    case AKEYCODE_ALT_LEFT:
+        return setEphemeralMetaState(AMETA_ALT_LEFT_ON, down, oldMetaState);
+    case AKEYCODE_ALT_RIGHT:
+        return setEphemeralMetaState(AMETA_ALT_RIGHT_ON, down, oldMetaState);
+    case AKEYCODE_SHIFT_LEFT:
+        return setEphemeralMetaState(AMETA_SHIFT_LEFT_ON, down, oldMetaState);
+    case AKEYCODE_SHIFT_RIGHT:
+        return setEphemeralMetaState(AMETA_SHIFT_RIGHT_ON, down, oldMetaState);
+    case AKEYCODE_SYM:
+        return setEphemeralMetaState(AMETA_SYM_ON, down, oldMetaState);
+    case AKEYCODE_FUNCTION:
+        return setEphemeralMetaState(AMETA_FUNCTION_ON, down, oldMetaState);
+    case AKEYCODE_CTRL_LEFT:
+        return setEphemeralMetaState(AMETA_CTRL_LEFT_ON, down, oldMetaState);
+    case AKEYCODE_CTRL_RIGHT:
+        return setEphemeralMetaState(AMETA_CTRL_RIGHT_ON, down, oldMetaState);
+    case AKEYCODE_META_LEFT:
+        return setEphemeralMetaState(AMETA_META_LEFT_ON, down, oldMetaState);
+    case AKEYCODE_META_RIGHT:
+        return setEphemeralMetaState(AMETA_META_RIGHT_ON, down, oldMetaState);
+    case AKEYCODE_CAPS_LOCK:
+        return toggleLockedMetaState(AMETA_CAPS_LOCK_LATCHED, down, oldMetaState);
+    case AKEYCODE_NUM_LOCK:
+        return toggleLockedMetaState(AMETA_NUM_LOCK_LATCHED, down, oldMetaState);
+    case AKEYCODE_SCROLL_LOCK:
+        return toggleLockedMetaState(AMETA_SCROLL_LOCK_LATCHED, down, oldMetaState);
+    default:
+        return oldMetaState;
+    }
+}
+
 static const int32_t keyCodeRotationMap[][4] = {
         // key codes enumerated counter-clockwise with the original (unrotated) key first
         // no rotation,        90 degree rotation,  180 degree rotation, 270 degree rotation
@@ -842,6 +874,17 @@
 void KeyboardInputMapper::initializeLocked() {
     mLocked.metaState = AMETA_NONE;
     mLocked.downTime = 0;
+
+    initializeLedStateLocked(mLocked.capsLockLedState, LED_CAPSL);
+    initializeLedStateLocked(mLocked.numLockLedState, LED_NUML);
+    initializeLedStateLocked(mLocked.scrollLockLedState, LED_SCROLLL);
+
+    updateLedStateLocked(true);
+}
+
+void KeyboardInputMapper::initializeLedStateLocked(LockedState::LedState& ledState, int32_t led) {
+    ledState.avail = getEventHub()->hasLed(getDeviceId(), led);
+    ledState.on = false;
 }
 
 uint32_t KeyboardInputMapper::getSources() {
@@ -966,6 +1009,7 @@
         if (oldMetaState != newMetaState) {
             mLocked.metaState = newMetaState;
             metaStateChanged = true;
+            updateLedStateLocked(false);
         }
 
         downTime = mLocked.downTime;
@@ -975,6 +1019,9 @@
         getContext()->updateGlobalMetaState();
     }
 
+    if (policyFlags & POLICY_FLAG_FUNCTION) {
+        newMetaState |= AMETA_FUNCTION_ON;
+    }
     getDispatcher()->notifyKey(when, getDeviceId(), AINPUT_SOURCE_KEYBOARD, policyFlags,
             down ? AKEY_EVENT_ACTION_DOWN : AKEY_EVENT_ACTION_UP,
             AKEY_EVENT_FLAG_FROM_SYSTEM, keyCode, scanCode, newMetaState, downTime);
@@ -1010,6 +1057,26 @@
     } // release lock
 }
 
+void KeyboardInputMapper::updateLedStateLocked(bool reset) {
+    updateLedStateForModifierLocked(mLocked.capsLockLedState, LED_CAPSL,
+            AMETA_CAPS_LOCK_LATCHED, reset);
+    updateLedStateForModifierLocked(mLocked.numLockLedState, LED_NUML,
+            AMETA_NUM_LOCK_LATCHED, reset);
+    updateLedStateForModifierLocked(mLocked.scrollLockLedState, LED_SCROLLL,
+            AMETA_SCROLL_LOCK_LATCHED, reset);
+}
+
+void KeyboardInputMapper::updateLedStateForModifierLocked(LockedState::LedState& ledState,
+        int32_t led, int32_t modifier, bool reset) {
+    if (ledState.avail) {
+        bool desiredState = (mLocked.metaState & modifier) != 0;
+        if (ledState.on != desiredState) {
+            getEventHub()->setLedState(getDeviceId(), led, desiredState);
+            ledState.on = desiredState;
+        }
+    }
+}
+
 
 // --- TrackballInputMapper ---
 
diff --git a/libs/ui/KeyCharacterMap.cpp b/libs/ui/KeyCharacterMap.cpp
index e891181..870a45c 100644
--- a/libs/ui/KeyCharacterMap.cpp
+++ b/libs/ui/KeyCharacterMap.cpp
@@ -156,26 +156,38 @@
 KeyCharacterMap*
 KeyCharacterMap::load(int id)
 {
-    KeyCharacterMap* rv = NULL;
+    KeyCharacterMap* map;
     char path[PATH_MAX];
     char propName[100];
     char dev[PROPERTY_VALUE_MAX];
-    char tmpfn[PROPERTY_VALUE_MAX];
+    char fn[PROPERTY_VALUE_MAX];
     int err;
+
+    // Check whether the EventHub has set a key character map filename for us already.
+    sprintf(propName, "hw.keyboards.%u.kcmfile", id);
+    err = property_get(propName, fn, "");
+    if (err > 0) {
+        map = try_file(fn);
+        if (map) {
+            return map;
+        }
+        LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, fn);
+    }
+
+    // Try using the device name.
     const char* root = getenv("ANDROID_ROOT");
 
     sprintf(propName, "hw.keyboards.%u.devname", id);
     err = property_get(propName, dev, "");
     if (err > 0) {
         // replace all the spaces with underscores
-        strcpy(tmpfn, dev);
-        for (char *p = strchr(tmpfn, ' '); p && *p; p = strchr(tmpfn, ' '))
+        strcpy(fn, dev);
+        for (char *p = strchr(fn, ' '); p && *p; p = strchr(p + 1, ' '))
             *p = '_';
-        snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, tmpfn);
-        //LOGD("load: dev='%s' path='%s'\n", dev, path);
-        rv = try_file(path);
-        if (rv != NULL) {
-            return rv;
+        snprintf(path, sizeof(path), "%s/usr/keychars/%s.kcm.bin", root, fn);
+        map = try_file(path);
+        if (map) {
+            return map;
         }
         LOGW("Error loading keycharmap file '%s'. %s='%s'", path, propName, dev);
     } else {
@@ -183,14 +195,14 @@
     }
 
     snprintf(path, sizeof(path), "%s/usr/keychars/qwerty.kcm.bin", root);
-    rv = try_file(path);
-    if (rv == NULL) {
-        LOGE("Can't find any keycharmaps (also tried %s)", path);
-        return NULL;
+    map = try_file(path);
+    if (map) {
+        LOGW("Using default keymap: %s", path);
+        return map;
     }
-    LOGW("Using default keymap: %s", path);
 
-    return rv;
+    LOGE("Can't find any keycharmaps (also tried %s)", path);
+    return NULL;
 }
 
 KeyCharacterMap*
diff --git a/libs/utils/String8.cpp b/libs/utils/String8.cpp
index 1c4f80c..6358fc4 100644
--- a/libs/utils/String8.cpp
+++ b/libs/utils/String8.cpp
@@ -292,6 +292,11 @@
     SharedBuffer::bufferFromData(mString)->release();
 }
 
+void String8::clear() {
+    SharedBuffer::bufferFromData(mString)->release();
+    mString = getEmptyString();
+}
+
 void String8::setTo(const String8& other)
 {
     SharedBuffer::bufferFromData(other.mString)->acquire();
diff --git a/native/include/android/input.h b/native/include/android/input.h
index 5580700..d190e49 100644
--- a/native/include/android/input.h
+++ b/native/include/android/input.h
@@ -93,7 +93,37 @@
     AMETA_SHIFT_RIGHT_ON = 0x80,
 
     /* This mask is used to check whether the SYM meta key is pressed. */
-    AMETA_SYM_ON = 0x04
+    AMETA_SYM_ON = 0x04,
+
+    /* This mask is used to check whether the FUNCTION meta key is pressed. */
+    AMETA_FUNCTION_ON = 0x08,
+
+    /* This mask is used to check whether one of the CTRL meta keys is pressed. */
+    AMETA_CTRL_ON = 0x1000,
+
+    /* This mask is used to check whether the left CTRL meta key is pressed. */
+    AMETA_CTRL_LEFT_ON = 0x2000,
+
+    /* This mask is used to check whether the right CTRL meta key is pressed. */
+    AMETA_CTRL_RIGHT_ON = 0x4000,
+
+    /* This mask is used to check whether one of the META meta keys is pressed. */
+    AMETA_META_ON = 0x10000,
+
+    /* This mask is used to check whether the left META meta key is pressed. */
+    AMETA_META_LEFT_ON = 0x20000,
+
+    /* This mask is used to check whether the right META meta key is pressed. */
+    AMETA_META_RIGHT_ON = 0x40000,
+
+    /* This mask is used to check whether the CAPS LOCK meta key is latched. */
+    AMETA_CAPS_LOCK_LATCHED = 0x100000,
+
+    /* This mask is used to check whether the NUM LOCK meta key is latched. */
+    AMETA_NUM_LOCK_LATCHED = 0x200000,
+
+    /* This mask is used to check whether the SCROLL LOCK meta key is latched. */
+    AMETA_SCROLL_LOCK_LATCHED = 0x400000,
 };
 
 /*
diff --git a/native/include/android/keycodes.h b/native/include/android/keycodes.h
index 496eccc0..3fcf977 100644
--- a/native/include/android/keycodes.h
+++ b/native/include/android/keycodes.h
@@ -154,6 +154,60 @@
     AKEYCODE_BUTTON_START    = 108,
     AKEYCODE_BUTTON_SELECT   = 109,
     AKEYCODE_BUTTON_MODE     = 110,
+    AKEYCODE_ESCAPE          = 111,
+    AKEYCODE_FORWARD_DEL     = 112,
+    AKEYCODE_CTRL_LEFT       = 113,
+    AKEYCODE_CTRL_RIGHT      = 114,
+    AKEYCODE_CAPS_LOCK       = 115,
+    AKEYCODE_SCROLL_LOCK     = 116,
+    AKEYCODE_META_LEFT       = 117,
+    AKEYCODE_META_RIGHT      = 118,
+    AKEYCODE_FUNCTION        = 119,
+    AKEYCODE_SYSRQ           = 120,
+    AKEYCODE_BREAK           = 121,
+    AKEYCODE_MOVE_HOME       = 122,
+    AKEYCODE_MOVE_END        = 123,
+    AKEYCODE_INSERT          = 124,
+    AKEYCODE_FORWARD         = 125,
+    AKEYCODE_MEDIA_PLAY      = 126,
+    AKEYCODE_MEDIA_PAUSE     = 127,
+    AKEYCODE_MEDIA_CLOSE     = 128,
+    AKEYCODE_MEDIA_EJECT     = 129,
+    AKEYCODE_MEDIA_RECORD    = 130,
+    AKEYCODE_F1              = 131,
+    AKEYCODE_F2              = 132,
+    AKEYCODE_F3              = 133,
+    AKEYCODE_F4              = 134,
+    AKEYCODE_F5              = 135,
+    AKEYCODE_F6              = 136,
+    AKEYCODE_F7              = 137,
+    AKEYCODE_F8              = 138,
+    AKEYCODE_F9              = 139,
+    AKEYCODE_F10             = 140,
+    AKEYCODE_F11             = 141,
+    AKEYCODE_F12             = 142,
+    AKEYCODE_NUM_LOCK        = 143,
+    AKEYCODE_NUMPAD_0        = 144,
+    AKEYCODE_NUMPAD_1        = 145,
+    AKEYCODE_NUMPAD_2        = 146,
+    AKEYCODE_NUMPAD_3        = 147,
+    AKEYCODE_NUMPAD_4        = 148,
+    AKEYCODE_NUMPAD_5        = 149,
+    AKEYCODE_NUMPAD_6        = 150,
+    AKEYCODE_NUMPAD_7        = 151,
+    AKEYCODE_NUMPAD_8        = 152,
+    AKEYCODE_NUMPAD_9        = 153,
+    AKEYCODE_NUMPAD_DIVIDE   = 154,
+    AKEYCODE_NUMPAD_MULTIPLY = 155,
+    AKEYCODE_NUMPAD_SUBTRACT = 156,
+    AKEYCODE_NUMPAD_ADD      = 157,
+    AKEYCODE_NUMPAD_DOT      = 158,
+    AKEYCODE_NUMPAD_COMMA    = 159,
+    AKEYCODE_NUMPAD_ENTER    = 160,
+    AKEYCODE_NUMPAD_EQUALS   = 161,
+    AKEYCODE_NUMPAD_LEFT_PAREN = 162,
+    AKEYCODE_NUMPAD_RIGHT_PAREN = 163,
+
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index c6898d4..2cd615d 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -96,6 +96,7 @@
 import static android.view.WindowManager.LayoutParams.TYPE_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_PRIORITY_PHONE;
 import static android.view.WindowManager.LayoutParams.TYPE_SEARCH_BAR;
+import static android.view.WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR;
 import static android.view.WindowManager.LayoutParams.TYPE_STATUS_BAR_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG;
@@ -163,6 +164,7 @@
     static final int DRAG_LAYER = 16;
     // things in here CAN NOT take focus, but are shown on top of everything else.
     static final int SYSTEM_OVERLAY_LAYER = 17;
+    static final int SECURE_SYSTEM_OVERLAY_LAYER = 18;
 
     static final int APPLICATION_MEDIA_SUBLAYER = -2;
     static final int APPLICATION_MEDIA_OVERLAY_SUBLAYER = -1;
@@ -691,7 +693,7 @@
             WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
                     WindowManager.LayoutParams.MATCH_PARENT,
                     WindowManager.LayoutParams.MATCH_PARENT);
-            lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+            lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
             lp.flags = 
                 WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE|
                 WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
@@ -787,6 +789,7 @@
     public void adjustWindowParamsLw(WindowManager.LayoutParams attrs) {
         switch (attrs.type) {
             case TYPE_SYSTEM_OVERLAY:
+            case TYPE_SECURE_SYSTEM_OVERLAY:
             case TYPE_TOAST:
                 // These types of windows can't receive input events.
                 attrs.flags |= WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
@@ -864,6 +867,8 @@
             return INPUT_METHOD_DIALOG_LAYER;
         case TYPE_SYSTEM_OVERLAY:
             return SYSTEM_OVERLAY_LAYER;
+        case TYPE_SECURE_SYSTEM_OVERLAY:
+            return SECURE_SYSTEM_OVERLAY_LAYER;
         case TYPE_PRIORITY_PHONE:
             return PRIORITY_PHONE_LAYER;
         case TYPE_TOAST:
diff --git a/services/java/com/android/server/LoadAverageService.java b/services/java/com/android/server/LoadAverageService.java
index 0d86429..b6baadb 100644
--- a/services/java/com/android/server/LoadAverageService.java
+++ b/services/java/com/android/server/LoadAverageService.java
@@ -272,7 +272,7 @@
         WindowManager.LayoutParams params = new WindowManager.LayoutParams(
             WindowManager.LayoutParams.WRAP_CONTENT,
             WindowManager.LayoutParams.WRAP_CONTENT,
-            WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY,
+            WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY,
             WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE|
             WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE,
             PixelFormat.TRANSLUCENT);
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 83351bc..c8c88c5 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -5965,7 +5965,7 @@
                 View v = LayoutInflater.from(mContext).inflate(
                         com.android.internal.R.layout.safe_mode, null);
                 WindowManager.LayoutParams lp = new WindowManager.LayoutParams();
-                lp.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY;
+                lp.type = WindowManager.LayoutParams.TYPE_SECURE_SYSTEM_OVERLAY;
                 lp.width = WindowManager.LayoutParams.WRAP_CONTENT;
                 lp.height = WindowManager.LayoutParams.WRAP_CONTENT;
                 lp.gravity = Gravity.BOTTOM | Gravity.LEFT;