auto import from //branches/cupcake_rel/...@140373
diff --git a/api/current.xml b/api/current.xml
index f45b68f..c9ed3c4 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -3771,6 +3771,39 @@
  visibility="public"
 >
 </field>
+<field name="imeExtractEnterAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843368"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="imeExtractExitAnimation"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843369"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="imeFullscreenBackground"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16843367"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="imeOptions"
  type="int"
  transient="false"
@@ -18918,6 +18951,16 @@
  visibility="public"
 >
 </field>
+<field name="extras"
+ type="android.os.Bundle"
+ transient="false"
+ volatile="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="icon"
  type="android.graphics.drawable.Drawable"
  transient="false"
@@ -21482,6 +21525,28 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_CUSTOM_EXTRAS"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;customExtras&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="EXTRA_CUSTOM_INFO"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;customInfo&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INVALID_APPWIDGET_ID"
  type="int"
  transient="false"
@@ -33631,6 +33696,17 @@
  visibility="public"
 >
 </field>
+<field name="INSTALL_FAILED_CONFLICTING_PROVIDER"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="-13"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="INSTALL_FAILED_DEXOPT"
  type="int"
  transient="false"
@@ -58771,6 +58847,17 @@
  visibility="public"
 >
 </method>
+<method name="isExtractViewShown"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isFullscreenMode"
  return="boolean"
  abstract="false"
@@ -58860,17 +58947,6 @@
 <parameter name="isCandidatesOnly" type="boolean">
 </parameter>
 </method>
-<method name="onCreateBackgroundDrawable"
- return="android.graphics.drawable.Drawable"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="onCreateCandidatesView"
  return="android.view.View"
  abstract="false"
@@ -59222,7 +59298,20 @@
 <parameter name="text" type="android.view.inputmethod.ExtractedText">
 </parameter>
 </method>
-<method name="onUpdateExtractingAccessories"
+<method name="onUpdateExtractingViews"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="ei" type="android.view.inputmethod.EditorInfo">
+</parameter>
+</method>
+<method name="onUpdateExtractingVisibility"
  return="void"
  abstract="false"
  native="false"
@@ -59371,6 +59460,19 @@
 <parameter name="view" type="android.view.View">
 </parameter>
 </method>
+<method name="setExtractViewShown"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="shown" type="boolean">
+</parameter>
+</method>
 <method name="setInputView"
  return="void"
  abstract="false"
@@ -60694,6 +60796,25 @@
 <parameter name="heightMeasureSpec" type="int">
 </parameter>
 </method>
+<method name="onSizeChanged"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="w" type="int">
+</parameter>
+<parameter name="h" type="int">
+</parameter>
+<parameter name="oldw" type="int">
+</parameter>
+<parameter name="oldh" type="int">
+</parameter>
+</method>
 <method name="setKeyboard"
  return="void"
  abstract="false"
@@ -63553,6 +63674,21 @@
 <parameter name="effectType" type="int">
 </parameter>
 </method>
+<method name="playSoundEffect"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="effectType" type="int">
+</parameter>
+<parameter name="volume" type="float">
+</parameter>
+</method>
 <method name="setBluetoothA2dpOn"
  return="void"
  abstract="false"
@@ -63910,6 +64046,50 @@
  visibility="public"
 >
 </field>
+<field name="FX_KEYPRESS_DELETE"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="7"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FX_KEYPRESS_RETURN"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FX_KEYPRESS_SPACEBAR"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="6"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FX_KEYPRESS_STANDARD"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="5"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FX_KEY_CLICK"
  type="int"
  transient="false"
@@ -65551,7 +65731,22 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="listener" type="android.media.JetPlayer.JetEventListener">
+<parameter name="listener" type="android.media.JetPlayer.OnJetEventListener">
+</parameter>
+</method>
+<method name="setEventListener"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="listener" type="android.media.JetPlayer.OnJetEventListener">
+</parameter>
+<parameter name="handler" type="android.os.Handler">
 </parameter>
 </method>
 <method name="setMuteArray"
@@ -65601,19 +65796,6 @@
 <parameter name="sync" type="boolean">
 </parameter>
 </method>
-<method name="setStatusUpdateListener"
- return="void"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="listener" type="android.media.JetPlayer.JetStatusUpdateListener">
-</parameter>
-</method>
 <method name="triggerClip"
  return="boolean"
  abstract="false"
@@ -65628,7 +65810,7 @@
 </parameter>
 </method>
 </class>
-<interface name="JetPlayer.JetEventListener"
+<interface name="JetPlayer.OnJetEventListener"
  abstract="true"
  static="true"
  final="false"
@@ -65658,14 +65840,6 @@
 <parameter name="value" type="byte">
 </parameter>
 </method>
-</interface>
-<interface name="JetPlayer.JetStatusUpdateListener"
- abstract="true"
- static="true"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
 <method name="onJetNumQueuedSegmentUpdate"
  return="void"
  abstract="true"
@@ -66054,7 +66228,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="l" type="android.media.MediaPlayer.OnBufferingUpdateListener">
+<parameter name="listener" type="android.media.MediaPlayer.OnBufferingUpdateListener">
 </parameter>
 </method>
 <method name="setOnCompletionListener"
@@ -66067,7 +66241,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="l" type="android.media.MediaPlayer.OnCompletionListener">
+<parameter name="listener" type="android.media.MediaPlayer.OnCompletionListener">
 </parameter>
 </method>
 <method name="setOnErrorListener"
@@ -66093,7 +66267,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="l" type="android.media.MediaPlayer.OnPreparedListener">
+<parameter name="listener" type="android.media.MediaPlayer.OnPreparedListener">
 </parameter>
 </method>
 <method name="setOnSeekCompleteListener"
@@ -66106,7 +66280,7 @@
  deprecated="not deprecated"
  visibility="public"
 >
-<parameter name="l" type="android.media.MediaPlayer.OnSeekCompleteListener">
+<parameter name="listener" type="android.media.MediaPlayer.OnSeekCompleteListener">
 </parameter>
 </method>
 <method name="setScreenOnWhilePlaying"
@@ -66436,6 +66610,21 @@
 <exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
 </exception>
 </method>
+<method name="setMaxFileSize"
+ return="void"
+ abstract="false"
+ native="true"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="max_filesize_bytes" type="long">
+</parameter>
+<exception name="IllegalArgumentException" type="java.lang.IllegalArgumentException">
+</exception>
+</method>
 <method name="setOnErrorListener"
  return="void"
  abstract="false"
@@ -66630,6 +66819,17 @@
  visibility="public"
 >
 </field>
+<field name="MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="801"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="MEDIA_RECORDER_INFO_UNKNOWN"
  type="int"
  transient="false"
@@ -86042,6 +86242,17 @@
  visibility="public"
 >
 </field>
+<field name="EXTRA_CREATE_DESCRIPTION"
+ type="java.lang.String"
+ transient="false"
+ volatile="false"
+ value="&quot;com.android.contacts.action.CREATE_DESCRIPTION&quot;"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="EXTRA_FORCE_CREATE"
  type="java.lang.String"
  transient="false"
@@ -118562,10 +118773,6 @@
 >
 <parameter name="origEvent" type="android.view.KeyEvent">
 </parameter>
-<parameter name="eventTime" type="long">
-</parameter>
-<parameter name="newRepeat" type="int">
-</parameter>
 </constructor>
 <constructor name="KeyEvent"
  type="android.view.KeyEvent"
@@ -118576,9 +118783,58 @@
 >
 <parameter name="origEvent" type="android.view.KeyEvent">
 </parameter>
-<parameter name="action" type="int">
+<parameter name="eventTime" type="long">
+</parameter>
+<parameter name="newRepeat" type="int">
 </parameter>
 </constructor>
+<method name="changeAction"
+ return="android.view.KeyEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+<parameter name="action" type="int">
+</parameter>
+</method>
+<method name="changeFlags"
+ return="android.view.KeyEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+<parameter name="flags" type="int">
+</parameter>
+</method>
+<method name="changeTimeRepeat"
+ return="android.view.KeyEvent"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+<parameter name="eventTime" type="long">
+</parameter>
+<parameter name="newRepeat" type="int">
+</parameter>
+</method>
 <method name="describeContents"
  return="int"
  abstract="false"
@@ -118952,6 +119208,28 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_EDITOR_ACTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="16"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
+<field name="FLAG_FROM_SYSTEM"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="8"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_KEEP_TOUCH_MODE"
  type="int"
  transient="false"
@@ -135470,6 +135748,17 @@
  visibility="public"
 >
 </field>
+<field name="IME_FLAG_NO_ACCESSORY_ACTION"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="536870912"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_FLAG_NO_ENTER_ACTION"
  type="int"
  transient="false"
@@ -135481,6 +135770,17 @@
  visibility="public"
 >
 </field>
+<field name="IME_FLAG_NO_EXTRACT_UI"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="268435456"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="IME_MASK_ACTION"
  type="int"
  transient="false"
@@ -139932,6 +140232,17 @@
  visibility="public"
 >
 </method>
+<method name="getBuiltInZoomControls"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getCacheMode"
  return="int"
  abstract="false"
@@ -140255,6 +140566,19 @@
 <parameter name="flag" type="boolean">
 </parameter>
 </method>
+<method name="setBuiltInZoomControls"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="setCacheMode"
  return="void"
  abstract="false"
@@ -141386,7 +141710,7 @@
  synchronized="false"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 </method>
diff --git a/cmds/pm/src/com/android/commands/pm/Pm.java b/cmds/pm/src/com/android/commands/pm/Pm.java
index c2d8da5..161bb46 100644
--- a/cmds/pm/src/com/android/commands/pm/Pm.java
+++ b/cmds/pm/src/com/android/commands/pm/Pm.java
@@ -528,8 +528,14 @@
         case PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY:
             s = "INSTALL_FAILED_MISSING_SHARED_LIBRARY";
             break;
-        case PackageManager.INSTALL_FAILED_REPLACE_COULDNT_DELETE:
-            s = "INSTALL_FAILED_REPLACE_COULDNT_DELETE";
+        case PackageManager.INSTALL_FAILED_DEXOPT:
+            s = "INSTALL_FAILED_DEXOPT";
+            break;
+        case PackageManager.INSTALL_FAILED_OLDER_SDK:
+            s = "INSTALL_FAILED_OLDER_SDK";
+            break;
+        case PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER:
+            s = "INSTALL_FAILED_CONFLICTING_PROVIDER";
             break;
         case PackageManager.INSTALL_PARSE_FAILED_NOT_APK:
             s = "INSTALL_PARSE_FAILED_NOT_APK";
@@ -561,9 +567,6 @@
         case PackageManager.INSTALL_PARSE_FAILED_MANIFEST_EMPTY:
             s = "INSTALL_PARSE_FAILED_MANIFEST_EMPTY";
             break;
-        case PackageManager.INSTALL_FAILED_OLDER_SDK:
-            s = "INSTALL_FAILED_OLDER_SDK";
-            break;
         default:
             s = Integer.toString(result);
         break;
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index f49005e..cb1e903 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -3250,8 +3250,21 @@
         r.window = null;
         r.hideForNow = false;
         r.nextIdle = null;
-        r.pendingResults = tmp.pendingResults;
-        r.pendingIntents = tmp.pendingIntents;
+        // Merge any pending results and pending intents; don't just replace them
+        if (tmp.pendingResults != null) {
+            if (r.pendingResults == null) {
+                r.pendingResults = tmp.pendingResults;
+            } else {
+                r.pendingResults.addAll(tmp.pendingResults);
+            }
+        }
+        if (tmp.pendingIntents != null) {
+            if (r.pendingIntents == null) {
+                r.pendingIntents = tmp.pendingIntents;
+            } else {
+                r.pendingIntents.addAll(tmp.pendingIntents);
+            }
+        }
         r.startsNotResumed = tmp.startsNotResumed;
         if (savedState != null) {
             r.state = savedState;
diff --git a/core/java/android/app/ApplicationContext.java b/core/java/android/app/ApplicationContext.java
index 3b5ad86..ecef38f 100644
--- a/core/java/android/app/ApplicationContext.java
+++ b/core/java/android/app/ApplicationContext.java
@@ -103,6 +103,9 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.WeakHashMap;
+import java.util.Set;
+import java.util.HashSet;
 import java.util.Map.Entry;
 
 import org.xmlpull.v1.XmlPullParserException;
@@ -2476,7 +2479,8 @@
         private final FileStatus mFileStatus = new FileStatus();
         private long mTimestamp;
 
-        private List<OnSharedPreferenceChangeListener> mListeners;
+        private static final Object mContent = new Object();
+        private WeakHashMap<OnSharedPreferenceChangeListener, Object> mListeners;
 
         SharedPreferencesImpl(
             File file, int mode, Map initialContents) {
@@ -2487,7 +2491,7 @@
             if (FileUtils.getFileStatus(file.getPath(), mFileStatus)) {
                 mTimestamp = mFileStatus.mtime;
             }
-            mListeners = new ArrayList<OnSharedPreferenceChangeListener>();
+            mListeners = new WeakHashMap<OnSharedPreferenceChangeListener, Object>();
         }
 
         public boolean hasFileChanged() {
@@ -2509,9 +2513,7 @@
         
         public void registerOnSharedPreferenceChangeListener(OnSharedPreferenceChangeListener listener) {
             synchronized(this) {
-                if (!mListeners.contains(listener)) {
-                    mListeners.add(listener);
-                }
+                mListeners.put(listener, mContent);
             }
         }
 
@@ -2620,13 +2622,14 @@
 
                 boolean hasListeners;
                 List<String> keysModified = null;
-                List<OnSharedPreferenceChangeListener> listeners = null;
+                Set<OnSharedPreferenceChangeListener> listeners = null;
 
                 synchronized (SharedPreferencesImpl.this) {
                     hasListeners = mListeners.size() > 0;
                     if (hasListeners) {
                         keysModified = new ArrayList<String>();
-                        listeners = new ArrayList<OnSharedPreferenceChangeListener>(mListeners);
+                        listeners =
+                                new HashSet<OnSharedPreferenceChangeListener>(mListeners.keySet());
                     }
 
                     synchronized (this) {
@@ -2635,9 +2638,7 @@
                             mClear = false;
                         }
 
-                        Iterator<Entry<String, Object>> it = mModified.entrySet().iterator();
-                        while (it.hasNext()) {
-                            Map.Entry<String, Object> e = it.next();
+                        for (Entry<String, Object> e : mModified.entrySet()) {
                             String k = e.getKey();
                             Object v = e.getValue();
                             if (v == this) {
@@ -2660,10 +2661,10 @@
                 if (hasListeners) {
                     for (int i = keysModified.size() - 1; i >= 0; i--) {
                         final String key = keysModified.get(i);
-                        // Call in the order they were registered
-                        final int listenersSize = listeners.size();
-                        for (int j = 0; j < listenersSize; j++) {
-                            listeners.get(j).onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
+                        for (OnSharedPreferenceChangeListener listener : listeners) {
+                            if (listener != null) {
+                                listener.onSharedPreferenceChanged(SharedPreferencesImpl.this, key);
+                            }
                         }
                     }
                 }
diff --git a/core/java/android/app/LauncherActivity.java b/core/java/android/app/LauncherActivity.java
index d6fcbb1..8d249da 100644
--- a/core/java/android/app/LauncherActivity.java
+++ b/core/java/android/app/LauncherActivity.java
@@ -65,6 +65,7 @@
         public Drawable icon;
         public String packageName;
         public String className;
+        public Bundle extras;
         
         ListItem(PackageManager pm, ResolveInfo resolveInfo, IconResizer resizer) {
             label = resolveInfo.loadLabel(pm);
@@ -115,6 +116,9 @@
             Intent intent = new Intent(mIntent);
             ListItem item = mActivitiesList.get(position);
             intent.setClassName(item.packageName, item.className);
+            if (item.extras != null) {
+                intent.putExtras(item.extras);
+            }
             return intent;
         }
 
diff --git a/core/java/android/app/Service.java b/core/java/android/app/Service.java
index a6a436f..d2fb605 100644
--- a/core/java/android/app/Service.java
+++ b/core/java/android/app/Service.java
@@ -278,11 +278,11 @@
     }
     
     /**
-     * Stop the service, if the most recent time it was started was 
+     * Stop the service if the most recent time it was started was 
      * <var>startId</var>.  This is the same as calling {@link 
      * android.content.Context#stopService} for this particular service but allows you to 
      * safely avoid stopping if there is a start request from a client that you 
-     * haven't yet see in {@link #onStart}. 
+     * haven't yet seen in {@link #onStart}. 
      * 
      * @param startId The most recent start identifier received in {@link 
      *                #onStart}.
diff --git a/core/java/android/appwidget/AppWidgetManager.java b/core/java/android/appwidget/AppWidgetManager.java
index 3b10ed2..eca04b3 100644
--- a/core/java/android/appwidget/AppWidgetManager.java
+++ b/core/java/android/appwidget/AppWidgetManager.java
@@ -109,6 +109,23 @@
     public static final String EXTRA_APPWIDGET_IDS = "appWidgetIds";
 
     /**
+     * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
+     * {@link AppWidgetProviderInfo} objects to mix in to the list of AppWidgets that are
+     * installed.  (This is how the launcher shows the search widget).
+     */
+    public static final String EXTRA_CUSTOM_INFO = "customInfo";
+
+    /**
+     * An intent extra to pass to the AppWidget picker containing a {@link java.util.List} of
+     * {@link android.os.Bundle} objects to mix in to the list of AppWidgets that are
+     * installed.  It will be added to the extras object on the {@link android.content.Intent}
+     * that is returned from the picker activity.
+     *
+     * {@more}
+     */
+    public static final String EXTRA_CUSTOM_EXTRAS = "customExtras";
+
+    /**
      * A sentiel value that the AppWidget manager will never return as a appWidgetId.
      */
     public static final int INVALID_APPWIDGET_ID = 0;
diff --git a/core/java/android/bluetooth/BluetoothDevice.java b/core/java/android/bluetooth/BluetoothDevice.java
index 1ba1c1e..abf08cb 100644
--- a/core/java/android/bluetooth/BluetoothDevice.java
+++ b/core/java/android/bluetooth/BluetoothDevice.java
@@ -31,6 +31,12 @@
  * @hide
  */
 public class BluetoothDevice {
+
+    public static final int BLUETOOTH_STATE_OFF = 0;
+    public static final int BLUETOOTH_STATE_TURNING_ON = 1;
+    public static final int BLUETOOTH_STATE_ON = 2;
+    public static final int BLUETOOTH_STATE_TURNING_OFF = 3;
+
     /** Inquiry scan and page scan are both off.
      *  Device is neither discoverable nor connectable */
     public static final int SCAN_MODE_NONE = 0;
@@ -83,7 +89,7 @@
     }
 
     /**
-     * Get the current status of Bluetooth hardware.
+     * Is Bluetooth currently turned on.
      *
      * @return true if Bluetooth enabled, false otherwise.
      */
@@ -95,37 +101,30 @@
     }
 
     /**
+     * Get the current state of Bluetooth.
+     *
+     * @return One of BLUETOOTH_STATE_ or BluetoothError.ERROR.
+     */
+    public int getBluetoothState() {
+        try {
+            return mService.getBluetoothState();
+        } catch (RemoteException e) {Log.e(TAG, "", e);}
+        return BluetoothError.ERROR;
+    }
+
+    /**
      * Enable the Bluetooth device.
      * Turn on the underlying hardware.
-     * This is an asynchronous call, BluetoothIntent.ENABLED_ACTION will be
-     * sent if and when the device is successfully enabled.
+     * This is an asynchronous call,
+     * BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION can be used to check if
+     * and when the device is sucessfully enabled.
      * @return false if we cannot enable the Bluetooth device. True does not
      * imply the device was enabled, it only implies that so far there were no
      * problems.
      */
     public boolean enable() {
-        return enable(null);
-    }
-
-    /**
-     * Enable the Bluetooth device.
-     * Turns on the underlying hardware.
-     * This is an asynchronous call. onEnableResult() of your callback will be
-     * called when the call is complete, with either RESULT_SUCCESS or
-     * RESULT_FAILURE.
-     *
-     * Your callback will be called from a binder thread, not the main thread.
-     *
-     * In addition to the callback, BluetoothIntent.ENABLED_ACTION will be
-     * broadcast if the device is successfully enabled.
-     *
-     * @param callback Your callback, null is ok.
-     * @return true if your callback was successfully registered, or false if
-     * there was an error, implying your callback will never be called.
-     */
-    public boolean enable(IBluetoothDeviceCallback callback) {
         try {
-            return mService.enable(callback);
+            return mService.enable();
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -138,7 +137,7 @@
      */
     public boolean disable() {
         try {
-            return mService.disable();
+            return mService.disable(true);
         } catch (RemoteException e) {Log.e(TAG, "", e);}
         return false;
     }
@@ -551,7 +550,6 @@
         }
         return pinBytes;
     }
-    
 
     private static final int ADDRESS_LENGTH = 17;
     /** Sanity check a bluetooth address, such as "00:43:A8:23:10:F0" */
diff --git a/core/java/android/bluetooth/BluetoothIntent.java b/core/java/android/bluetooth/BluetoothIntent.java
index 9273d0d..344601b 100644
--- a/core/java/android/bluetooth/BluetoothIntent.java
+++ b/core/java/android/bluetooth/BluetoothIntent.java
@@ -41,6 +41,10 @@
         "android.bluetooth.intent.RSSI";
     public static final String CLASS =
         "android.bluetooth.intent.CLASS";
+    public static final String BLUETOOTH_STATE =
+        "android.bluetooth.intent.BLUETOOTH_STATE";
+    public static final String BLUETOOTH_PREVIOUS_STATE =
+        "android.bluetooth.intent.BLUETOOTH_PREVIOUS_STATE";
     public static final String HEADSET_STATE =
         "android.bluetooth.intent.HEADSET_STATE";
     public static final String HEADSET_PREVIOUS_STATE =
@@ -54,12 +58,12 @@
     public static final String REASON =
         "android.bluetooth.intent.REASON";
 
+    /** Broadcast when the local Bluetooth device state changes, for example
+     *  when Bluetooth is enabled. Will contain int extra's BLUETOOTH_STATE and
+     *  BLUETOOTH_PREVIOUS_STATE. */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String ENABLED_ACTION          =
-        "android.bluetooth.intent.action.ENABLED";
-    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
-    public static final String DISABLED_ACTION         =
-        "android.bluetooth.intent.action.DISABLED";
+    public static final String BLUETOOTH_STATE_CHANGED_ACTION =
+        "android.bluetooth.intent.action.BLUETOOTH_STATE_CHANGED";
 
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String NAME_CHANGED_ACTION  =
diff --git a/core/java/android/bluetooth/IBluetoothDevice.aidl b/core/java/android/bluetooth/IBluetoothDevice.aidl
index 4351d2e..6cd792e 100644
--- a/core/java/android/bluetooth/IBluetoothDevice.aidl
+++ b/core/java/android/bluetooth/IBluetoothDevice.aidl
@@ -26,8 +26,9 @@
 interface IBluetoothDevice
 {
     boolean isEnabled();
-    boolean enable(in IBluetoothDeviceCallback callback);  // async
-    boolean disable();
+    int getBluetoothState();
+    boolean enable();
+    boolean disable(boolean persistSetting);
 
     String getAddress();
     String getName();
diff --git a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl
index d25bd56..d057093 100644
--- a/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl
+++ b/core/java/android/bluetooth/IBluetoothDeviceCallback.aidl
@@ -22,6 +22,4 @@
 oneway interface IBluetoothDeviceCallback
 {
     void onGetRemoteServiceChannelResult(in String address, int channel);
-
-    void onEnableResult(int result);
 }
diff --git a/core/java/android/bluetooth/ScoSocket.java b/core/java/android/bluetooth/ScoSocket.java
index a43a08b..1bf786f 100644
--- a/core/java/android/bluetooth/ScoSocket.java
+++ b/core/java/android/bluetooth/ScoSocket.java
@@ -76,7 +76,7 @@
         try {
             if (VDBG) log(this + " SCO OBJECT DTOR");
             destroyNative();
-            releaseWakeLock();
+            releaseWakeLockNow();
         } finally {
             super.finalize();
         }
@@ -98,7 +98,7 @@
             return true;
         } else {
             mState = STATE_CLOSED;
-            releaseWakeLock();
+            releaseWakeLockNow();
             return false;
         }
     }
@@ -148,7 +148,7 @@
             mState = STATE_CLOSED;
         }
         mHandler.obtainMessage(mConnectedCode, mState, -1, this).sendToTarget();
-        releaseWakeLock();
+        releaseWakeLockNow();
     }
 
     private synchronized void onAccepted(int result) {
@@ -183,7 +183,19 @@
 
     private void releaseWakeLock() {
         if (mWakeLock.isHeld()) {
-            if (VDBG) log("mWakeLock.release() " + this);
+            // Keep apps processor awake for a further 2 seconds.
+            // This is a hack to resolve issue http://b/1616263 - in which
+            // we are left in a 80 mA power state when remotely terminating a
+            // call while connected to BT headset "HTC BH S100 " with A2DP and
+            // HFP profiles.
+            if (VDBG) log("mWakeLock.release() in 2 sec" + this);
+            mWakeLock.acquire(2000);
+        }
+    }
+
+    private void releaseWakeLockNow() {
+        if (mWakeLock.isHeld()) {
+            if (VDBG) log("mWakeLock.release() now" + this);
             mWakeLock.release();
         }
     }
diff --git a/core/java/android/content/BroadcastReceiver.java b/core/java/android/content/BroadcastReceiver.java
index 08f6191..a41627a 100644
--- a/core/java/android/content/BroadcastReceiver.java
+++ b/core/java/android/content/BroadcastReceiver.java
@@ -68,7 +68,7 @@
  * these broadcasts, the Intent broadcast mechanism here is completely separate
  * from Intents that are used to start Activities with
  * {@link Context#startActivity Context.startActivity()}.
- * There is no way for an BroadcastReceiver
+ * There is no way for a BroadcastReceiver
  * to see or capture Intents used with startActivity(); likewise, when
  * you broadcast an Intent, you will never find or start an Activity.
  * These two operations are semantically very different: starting an
@@ -103,7 +103,7 @@
  * its process before the asynchronous operation completes.
  * 
  * <p>In particular, you may <i>not</i> show a dialog or bind to a service from
- * within an BroadcastReceiver.  For the former, you should instead use the
+ * within a BroadcastReceiver.  For the former, you should instead use the
  * {@link android.app.NotificationManager} API.  For the latter, you can
  * use {@link android.content.Context#startService Context.startService()} to
  * send a command to the service.
@@ -141,7 +141,7 @@
  * <a name="ProcessLifecycle"></a>
  * <h3>Process Lifecycle</h3>
  * 
- * <p>A process that is currently executing an BroadcastReceiver (that is,
+ * <p>A process that is currently executing a BroadcastReceiver (that is,
  * currently running the code in its {@link #onReceive} method) is
  * considered to be a foreground process and will be kept running by the
  * system except under cases of extreme memory pressure.
@@ -156,7 +156,7 @@
  * more important processes.
  * 
  * <p>This means that for longer-running operations you will often use
- * a {@link android.app.Service} in conjunction with an BroadcastReceiver to keep
+ * an {@link android.app.Service} in conjunction with a BroadcastReceiver to keep
  * the containing process active for the entire time of your operation.
  */
 public abstract class BroadcastReceiver {
diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java
index 90ff78a..306c02e 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -1035,7 +1035,7 @@
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_SEARCH_LONG_PRESS = "android.intent.action.SEARCH_LONG_PRESS";
-    
+
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Standard intent broadcast actions (see action variable).
@@ -1052,7 +1052,7 @@
     public static final String ACTION_SCREEN_ON = "android.intent.action.SCREEN_ON";
 
     /**
-     * Broadcast Action: Sent when the user is present after device wakes up (e.g when the 
+     * Broadcast Action: Sent when the user is present after device wakes up (e.g when the
      * keyguard is gone).
      */
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
@@ -1210,7 +1210,7 @@
     /**
      * Broadcast Action:  The charging state, or charge level of the battery has
      * changed.
-     * 
+     *
      * <p class="note">
      * You can <em>not</em> receive this through components declared
      * in manifests, only by exlicitly registering for it with
@@ -1380,7 +1380,7 @@
     @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
     public static final String ACTION_GTALK_SERVICE_DISCONNECTED =
             "android.intent.action.GTALK_DISCONNECTED";
-    
+
     /**
      * Broadcast Action: An input method has been changed.
      * {@hide pending API Council approval}
@@ -1450,12 +1450,12 @@
      *
      * <p>The Intent will have the following extra value:
      * <ul>
-     *   <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> - 
+     *   <li><em>{@link android.content.Intent#EXTRA_PHONE_NUMBER}</em> -
      *       the phone number originally intended to be dialed.</li>
      * </ul>
      * <p>Once the broadcast is finished, the resultData is used as the actual
      * number to call.  If  <code>null</code>, no call will be placed.</p>
-     * <p>It is perfectly acceptable for multiple receivers to process the 
+     * <p>It is perfectly acceptable for multiple receivers to process the
      * outgoing call in turn: for example, a parental control application
      * might verify that the user is authorized to place the call at that
      * time, then a number-rewriting application might add an area code if
@@ -1463,7 +1463,7 @@
      * <p>For consistency, any receiver whose purpose is to prohibit phone
      * calls should have a priority of 0, to ensure it will see the final
      * phone number to be dialed.
-     * Any receiver whose purpose is to rewrite phone numbers to be called 
+     * Any receiver whose purpose is to rewrite phone numbers to be called
      * should have a positive priority.
      * Negative priorities are reserved for the system for this broadcast;
      * using them may cause problems.</p>
@@ -1472,7 +1472,7 @@
      * <p>Emergency calls cannot be intercepted using this mechanism, and
      * other calls cannot be modified to call emergency numbers using this
      * mechanism.
-     * <p>You must hold the 
+     * <p>You must hold the
      * {@link android.Manifest.permission#PROCESS_OUTGOING_CALLS}
      * permission to receive this Intent.</p>
      */
@@ -1709,7 +1709,7 @@
      * implying that this is an update).
      */
     public static final String EXTRA_DATA_REMOVED = "android.intent.extra.DATA_REMOVED";
-    
+
     /**
      * Used as a boolean extra field in {@link android.content.Intent#ACTION_PACKAGE_REMOVED}
      * intents to indicate that this is a replacement of the package, so this
@@ -1717,7 +1717,7 @@
      * different version of the same package.
      */
     public static final String EXTRA_REPLACING = "android.intent.extra.REPLACING";
-    
+
     /**
      * Used as an int extra field in {@link android.app.AlarmManager} intents
      * to tell the application being invoked how many pending alarms are being
@@ -1728,15 +1728,6 @@
      */
     public static final String EXTRA_ALARM_COUNT = "android.intent.extra.ALARM_COUNT";
 
-    /**
-     * Used as an int extra field in {@link android.content.Intent#ACTION_VOICE_COMMAND}
-     * intents to request which audio route the voice command should prefer.
-     * The value should be a route from {@link android.media.AudioManager}, for
-     * example ROUTE_BLUETOOTH_SCO. Providing this value is optional.
-     * {@hide pending API Council approval}
-     */
-    public static final String EXTRA_AUDIO_ROUTE = "android.intent.extra.AUDIO_ROUTE";
-
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     // Intent flags (see mFlags variable).
@@ -1781,7 +1772,7 @@
      * next task activity) defines an atomic group of activities that the
      * user can move to.  Tasks can be moved to the foreground and background;
      * all of the activities inside of a particular task always remain in
-     * the same order.  See 
+     * the same order.  See
      * <a href="{@docRoot}guide/topics/fundamentals.html#acttask">Application Fundamentals:
      * Activities and Tasks</a> for more details on tasks.
      *
@@ -1812,7 +1803,7 @@
      * <p><strong>Because the default system does not include graphical task management,
      * you should not use this flag unless you provide some way for a user to
      * return back to the tasks you have launched.</strong>
-     * 
+     *
      * <p>This flag is ignored if
      * {@link #FLAG_ACTIVITY_NEW_TASK} is not set.
      *
@@ -1901,7 +1892,7 @@
      * the user re-launching it from home), this activity and all on top of
      * it will be finished so that the user does not return to them, but
      * instead returns to whatever activity preceeded it.
-     * 
+     *
      * <p>This is useful for cases where you have a logical break in your
      * application.  For example, an e-mail application may have a command
      * to view an attachment, which launches an image view activity to
@@ -1919,31 +1910,31 @@
      * If set, this flag will prevent the normal {@link android.app.Activity#onUserLeaveHint}
      * callback from occurring on the current frontmost activity before it is
      * paused as the newly-started activity is brought to the front.
-     * 
+     *
      * <p>Typically, an activity can rely on that callback to indicate that an
      * explicit user action has caused their activity to be moved out of the
      * foreground. The callback marks an appropriate point in the activity's
      * lifecycle for it to dismiss any notifications that it intends to display
      * "until the user has seen them," such as a blinking LED.
-     * 
+     *
      * <p>If an activity is ever started via any non-user-driven events such as
      * phone-call receipt or an alarm handler, this flag should be passed to {@link
      * Context#startActivity Context.startActivity}, ensuring that the pausing
-     * activity does not think the user has acknowledged its notification. 
+     * activity does not think the user has acknowledged its notification.
      */
     public static final int FLAG_ACTIVITY_NO_USER_ACTION = 0x00040000;
     /**
      * If set in an Intent passed to {@link Context#startActivity Context.startActivity()},
      * this flag will cause the launched activity to be brought to the front of its
      * task's history stack if it is already running.
-     * 
+     *
      * <p>For example, consider a task consisting of four activities: A, B, C, D.
      * If D calls startActivity() with an Intent that resolves to the component
      * of activity B, then B will be brought to the front of the history stack,
      * with this resulting order:  A, C, D, B.
-     * 
+     *
      * This flag will be ignored if {@link #FLAG_ACTIVITY_CLEAR_TOP} is also
-     * specified. 
+     * specified.
      */
     public static final int FLAG_ACTIVITY_REORDER_TO_FRONT = 0X00020000;
     /**
@@ -1957,11 +1948,11 @@
      * will be launched.  Sticky intent state will be recorded properly even
      * if no receivers wind up being called.  If {@link #FLAG_RECEIVER_REGISTERED_ONLY}
      * is specified in the broadcast intent, this flag is unnecessary.
-     * 
+     *
      * <p>This flag is only for use by system sevices as a convenience to
      * avoid having to implement a more complex mechanism around detection
      * of boot completion.
-     * 
+     *
      * @hide
      */
     public static final int FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT = 0x20000000;
@@ -2121,7 +2112,7 @@
 
             // old format Intent URI
             if (!uri.startsWith("#Intent;", i)) return getIntentOld(uri);
-            
+
             // new format
             Intent intent = new Intent(ACTION_VIEW);
 
@@ -2130,7 +2121,7 @@
                 intent.mData = Uri.parse(uri.substring(0, i));
             }
             i += "#Intent;".length();
-            
+
             // loop over contents of Intent, all name=value;
             while (!uri.startsWith("end", i)) {
                 int eq = uri.indexOf('=', i);
@@ -2161,7 +2152,7 @@
                 else if (uri.startsWith("component=", i)) {
                     intent.mComponent = ComponentName.unflattenFromString(value);
                 }
-                
+
                 // extra
                 else {
                     String key = Uri.decode(uri.substring(i + 2, eq));
@@ -2181,18 +2172,18 @@
                     else if (uri.startsWith("s.", i)) b.putShort(key, Short.parseShort(value));
                     else throw new URISyntaxException(uri, "unknown EXTRA type", i);
                 }
-                
+
                 // move to the next item
                 i = semi + 1;
             }
 
             return intent;
-            
+
         } catch (IndexOutOfBoundsException e) {
             throw new URISyntaxException(uri, "illegal Intent URI format", i);
         }
     }
-    
+
     public static Intent getIntentOld(String uri) throws URISyntaxException {
         Intent intent;
 
@@ -2257,7 +2248,7 @@
 
             if (uri.regionMatches(i, "extras(", 0, 7)) {
                 i += 7;
-                
+
                 final int closeParen = uri.indexOf(')', i);
                 if (closeParen == -1) throw new URISyntaxException(uri,
                         "EXTRA missing trailing ')'", i);
@@ -2272,7 +2263,7 @@
                     i++;
                     String key = uri.substring(i, j);
                     i = j + 1;
-                    
+
                     // get type-value
                     j = uri.indexOf('!', i);
                     if (j == -1 || j >= closeParen) j = closeParen;
@@ -2282,7 +2273,7 @@
 
                     // create Bundle if it doesn't already exist
                     if (intent.mExtras == null) intent.mExtras = new Bundle();
-                    
+
                     // add item to bundle
                     try {
                         switch (type) {
@@ -2319,7 +2310,7 @@
                     } catch (NumberFormatException e) {
                         throw new URISyntaxException(uri, "EXTRA value can't be parsed", i);
                     }
-                    
+
                     char ch = uri.charAt(i);
                     if (ch == ')') break;
                     if (ch != '!') throw new URISyntaxException(uri, "EXTRA missing '!'", i);
@@ -2522,7 +2513,7 @@
     public boolean hasFileDescriptors() {
         return mExtras != null && mExtras.hasFileDescriptors();
     }
-    
+
     /**
      * Retrieve extended data from the intent.
      *
@@ -3889,7 +3880,7 @@
     /**
      * Completely replace the extras in the Intent with the extras in the
      * given Intent.
-     * 
+     *
      * @param src The exact extras contained in this Intent are copied
      * into the target intent, replacing any that were previously there.
      */
@@ -3897,11 +3888,11 @@
         mExtras = src.mExtras != null ? new Bundle(src.mExtras) : null;
         return this;
     }
-    
+
     /**
      * Completely replace the extras in the Intent with the given Bundle of
      * extras.
-     * 
+     *
      * @param extras The new set of extras in the Intent, or null to erase
      * all extras.
      */
@@ -3909,7 +3900,7 @@
         mExtras = extras != null ? new Bundle(extras) : null;
         return this;
     }
-    
+
     /**
      * Remove extended data from the intent.
      *
@@ -4397,12 +4388,12 @@
                 }
             }
         }
-        
+
         uri.append("end");
 
         return uri.toString();
     }
-    
+
     public int describeContents() {
         return (mExtras != null) ? mExtras.describeContents() : 0;
     }
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index 7287d9c..3e94734 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -341,6 +341,14 @@
     public static final int INSTALL_FAILED_OLDER_SDK = -12;
 
     /**
+     * Installation return code: this is passed to the {@link IPackageInstallObserver} by
+     * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)} if
+     * the new package failed because it contains a content provider with the
+     * same authority as a provider already installed in the system.
+     */
+    public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;
+
+    /**
      * Installation parse return code: this is passed to the {@link IPackageInstallObserver} by
      * {@link #installPackage(android.net.Uri, IPackageInstallObserver, int)}
      * if the parser was given a path that is not a file, or does not end with the expected
diff --git a/core/java/android/emoji/EmojiFactory.java b/core/java/android/emoji/EmojiFactory.java
index 389bd07..e0b12ae 100644
--- a/core/java/android/emoji/EmojiFactory.java
+++ b/core/java/android/emoji/EmojiFactory.java
@@ -253,6 +253,22 @@
      * is returned. 
      */
     public static native EmojiFactory newAvailableInstance();
+
+    /**
+     * Returns the lowest code point corresponding to an Android
+     * emoji character.
+     */
+    public int getMinimumAndroidPua() {
+        return nativeGetMinimumAndroidPua(mNativeEmojiFactory);
+    }
+
+    /**
+     * Returns the highest code point corresponding to an Android
+     * emoji character.
+     */
+    public int getMaximumAndroidPua() {
+        return nativeGetMaximumAndroidPua(mNativeEmojiFactory);
+    }
     
     // native methods
     
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 32270c4..6ee92ce 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -22,8 +22,8 @@
 import android.app.Dialog;
 import android.content.Context;
 import android.content.res.Configuration;
+import android.content.res.TypedArray;
 import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.ResultReceiver;
@@ -44,6 +44,7 @@
 import android.view.ViewTreeObserver;
 import android.view.Window;
 import android.view.WindowManager;
+import android.view.animation.AnimationUtils;
 import android.view.inputmethod.CompletionInfo;
 import android.view.inputmethod.ExtractedText;
 import android.view.inputmethod.ExtractedTextRequest;
@@ -54,6 +55,8 @@
 import android.view.inputmethod.EditorInfo;
 import android.widget.Button;
 import android.widget.FrameLayout;
+import android.widget.LinearLayout;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
@@ -204,6 +207,10 @@
  * You can use these to reset and initialize your input state for the current
  * target.  For example, you will often want to clear any input state, and
  * update a soft keyboard to be appropriate for the new inputType.</p>
+ * 
+ * @attr ref android.R.styleable#InputMethodService_imeFullscreenBackground
+ * @attr ref android.R.styleable#InputMethodService_imeExtractEnterAnimation
+ * @attr ref android.R.styleable#InputMethodService_imeExtractExitAnimation
  */
 public class InputMethodService extends AbstractInputMethodService {
     static final String TAG = "InputMethodService";
@@ -211,13 +218,19 @@
     
     InputMethodManager mImm;
     
+    int mTheme = android.R.style.Theme_InputMethod;
+    
     LayoutInflater mInflater;
+    TypedArray mThemeAttrs;
     View mRootView;
     SoftInputWindow mWindow;
     boolean mInitialized;
     boolean mWindowCreated;
     boolean mWindowAdded;
     boolean mWindowVisible;
+    boolean mWindowWasVisible;
+    boolean mInShowWindow;
+    ViewGroup mFullscreenArea;
     FrameLayout mExtractFrame;
     FrameLayout mCandidatesFrame;
     FrameLayout mInputFrame;
@@ -243,6 +256,7 @@
     boolean mFullscreenApplied;
     boolean mIsFullscreen;
     View mExtractView;
+    boolean mExtractViewHidden;
     ExtractEditText mExtractEditText;
     ViewGroup mExtractAccessories;
     Button mExtractAction;
@@ -260,8 +274,8 @@
     final ViewTreeObserver.OnComputeInternalInsetsListener mInsetsComputer =
             new ViewTreeObserver.OnComputeInternalInsetsListener() {
         public void onComputeInternalInsets(ViewTreeObserver.InternalInsetsInfo info) {
-            if (isFullscreenMode()) {
-                // In fullscreen mode, we just say the window isn't covering
+            if (isExtractViewShown()) {
+                // In true fullscreen mode, we just say the window isn't covering
                 // any content so we don't impact whatever is behind.
                 View decor = getWindow().getWindow().getDecorView();
                 info.contentInsets.top = info.visibleInsets.top
@@ -519,12 +533,28 @@
         public int touchableInsets;
     }
     
+    /**
+     * You can call this to customize the theme used by your IME's window.
+     * This theme should typically be one that derives from
+     * {@link android.R.style#Theme_InputMethod}, which is the default theme
+     * you will get.  This must be set before {@link #onCreate}, so you
+     * will typically call it in your constructor with the resource ID
+     * of your custom theme.
+     */
+    public void setTheme(int theme) {
+        if (mWindow != null) {
+            throw new IllegalStateException("Must be called before onCreate()");
+        }
+        mTheme = theme;
+    }
+    
     @Override public void onCreate() {
+        super.setTheme(mTheme);
         super.onCreate();
         mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
         mInflater = (LayoutInflater)getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
-        mWindow = new SoftInputWindow(this);
+        mWindow = new SoftInputWindow(this, mTheme);
         initViews();
         mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT);
     }
@@ -551,6 +581,7 @@
         mShowInputRequested = false;
         mShowInputForced = false;
         
+        mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
         mRootView = mInflater.inflate(
                 com.android.internal.R.layout.input_method, null);
         mWindow.setContentView(mRootView);
@@ -560,6 +591,8 @@
             mWindow.getWindow().setWindowAnimations(
                     com.android.internal.R.style.Animation_InputMethodFancy);
         }
+        mFullscreenArea = (ViewGroup)mRootView.findViewById(com.android.internal.R.id.fullscreenArea);
+        mExtractViewHidden = false;
         mExtractFrame = (FrameLayout)mRootView.findViewById(android.R.id.extractArea);
         mExtractView = null;
         mExtractEditText = null;
@@ -731,14 +764,20 @@
             if (ic != null) ic.reportFullscreenMode(isFullscreen);
             mFullscreenApplied = true;
             initialize();
-            Drawable bg = onCreateBackgroundDrawable();
-            if (bg == null) {
-                // We need to give the window a real drawable, so that it
-                // correctly sets its mode.
-                bg = getResources().getDrawable(android.R.color.transparent);
+            LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams)
+                    mFullscreenArea.getLayoutParams();
+            if (isFullscreen) {
+                mFullscreenArea.setBackgroundDrawable(mThemeAttrs.getDrawable(
+                        com.android.internal.R.styleable.InputMethodService_imeFullscreenBackground));
+                lp.height = 0;
+                lp.weight = 1;
+            } else {
+                mFullscreenArea.setBackgroundDrawable(null);
+                lp.height = LinearLayout.LayoutParams.WRAP_CONTENT;
+                lp.weight = 0;
             }
-            mWindow.getWindow().setBackgroundDrawable(bg);
-            mExtractFrame.setVisibility(isFullscreen ? View.VISIBLE : View.GONE);
+            ((ViewGroup)mFullscreenArea.getParent()).updateViewLayout(
+                    mFullscreenArea, lp);
             if (isFullscreen) {
                 if (mExtractView == null) {
                     View v = onCreateExtractTextView();
@@ -748,6 +787,7 @@
                 }
                 startExtractingText(false);
             }
+            updateExtractFrameVisibility();
         }
         
         if (changed) {
@@ -805,12 +845,66 @@
     }
     
     /**
+     * Controls the visibility of the extracted text area.  This only applies
+     * when the input method is in fullscreen mode, and thus showing extracted
+     * text.  When false, the extracted text will not be shown, allowing some
+     * of the application to be seen behind.  This is normally set for you
+     * by {@link #onUpdateExtractingVisibility}.  This controls the visibility
+     * of both the extracted text and candidate view; the latter since it is
+     * not useful if there is no text to see.
+     */
+    public void setExtractViewShown(boolean shown) {
+        if (mExtractViewHidden == shown) {
+            mExtractViewHidden = !shown;
+            updateExtractFrameVisibility();
+        }
+    }
+    
+    /**
+     * Return whether the fullscreen extract view is shown.  This will only
+     * return true if {@link #isFullscreenMode()} returns true, and in that
+     * case its value depends on the last call to
+     * {@link #setExtractViewShown(boolean)}.  This effectively lets you
+     * determine if the application window is entirely covered (when this
+     * returns true) or if some part of it may be shown (if this returns
+     * false, though if {@link #isFullscreenMode()} returns true in that case
+     * then it is probably only a sliver of the application).
+     */
+    public boolean isExtractViewShown() {
+        return mIsFullscreen && !mExtractViewHidden;
+    }
+    
+    void updateExtractFrameVisibility() {
+        int vis;
+        if (isFullscreenMode()) {
+            vis = mExtractViewHidden ? View.INVISIBLE : View.VISIBLE;
+            mExtractFrame.setVisibility(View.VISIBLE);
+        } else {
+            vis = View.VISIBLE;
+            mExtractFrame.setVisibility(View.GONE);
+        }
+        updateCandidatesVisibility(mCandidatesVisibility == View.VISIBLE);
+        if (mWindowWasVisible && mFullscreenArea.getVisibility() != vis) {
+            int animRes = mThemeAttrs.getResourceId(vis == View.VISIBLE
+                    ? com.android.internal.R.styleable.InputMethodService_imeExtractEnterAnimation
+                    : com.android.internal.R.styleable.InputMethodService_imeExtractExitAnimation,
+                    0);
+            if (animRes != 0) {
+                mFullscreenArea.startAnimation(AnimationUtils.loadAnimation(
+                        this, animRes));
+            }
+        }
+        mFullscreenArea.setVisibility(vis);
+    }
+    
+    /**
      * Compute the interesting insets into your UI.  The default implementation
      * uses the top of the candidates frame for the visible insets, and the
      * top of the input frame for the content insets.  The default touchable
      * insets are {@link Insets#TOUCHABLE_INSETS_VISIBLE}.
      * 
-     * <p>Note that this method is not called when in fullscreen mode, since
+     * <p>Note that this method is not called when
+     * {@link #isExtractViewShown} returns true, since
      * in that case the application is left as-is behind the input method and
      * not impacted by anything in its UI.
      * 
@@ -821,9 +915,16 @@
         if (mInputFrame.getVisibility() == View.VISIBLE) {
             mInputFrame.getLocationInWindow(loc);
         } else {
-            loc[1] = 0;
+            View decor = getWindow().getWindow().getDecorView();
+            loc[1] = decor.getHeight();
         }
-        outInsets.contentTopInsets = loc[1];
+        if (isFullscreenMode()) {
+            // In fullscreen mode, we never resize the underlying window.
+            View decor = getWindow().getWindow().getDecorView();
+            outInsets.contentTopInsets = decor.getHeight();
+        } else {
+            outInsets.contentTopInsets = loc[1];
+        }
         if (mCandidatesFrame.getVisibility() == View.VISIBLE) {
             mCandidatesFrame.getLocationInWindow(loc);
         }
@@ -889,11 +990,7 @@
      * it is hidden.
      */
     public void setCandidatesViewShown(boolean shown) {
-        int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility();
-        if (mCandidatesVisibility != vis) {
-            mCandidatesFrame.setVisibility(vis);
-            mCandidatesVisibility = vis;
-        }
+        updateCandidatesVisibility(shown);
         if (!mShowInputRequested && mWindowVisible != shown) {
             // If we are being asked to show the candidates view while the app
             // has not asked for the input view to be shown, then we need
@@ -906,17 +1003,26 @@
         }
     }
     
+    void updateCandidatesVisibility(boolean shown) {
+        int vis = shown ? View.VISIBLE : getCandidatesHiddenVisibility();
+        if (mCandidatesVisibility != vis) {
+            mCandidatesFrame.setVisibility(vis);
+            mCandidatesVisibility = vis;
+        }
+    }
+    
     /**
      * Returns the visibility mode (either {@link View#INVISIBLE View.INVISIBLE}
      * or {@link View#GONE View.GONE}) of the candidates view when it is not
-     * shown.  The default implementation returns GONE when in fullscreen mode,
+     * shown.  The default implementation returns GONE when
+     * {@link #isExtractViewShown} returns true,
      * otherwise VISIBLE.  Be careful if you change this to return GONE in
      * other situations -- if showing or hiding the candidates view causes
      * your window to resize, this can cause temporary drawing artifacts as
      * the resize takes place.
      */
     public int getCandidatesHiddenVisibility() {
-        return isFullscreenMode() ? View.GONE : View.INVISIBLE;
+        return isExtractViewShown() ? View.GONE : View.INVISIBLE;
     }
     
     public void showStatusIcon(int iconResId) {
@@ -992,20 +1098,6 @@
     }
     
     /**
-     * Called by the framework to create a Drawable for the background of
-     * the input method window.  May return null for no background.  The default
-     * implementation returns a non-null standard background only when in
-     * fullscreen mode.  This is called each time the fullscreen mode changes.
-     */
-    public Drawable onCreateBackgroundDrawable() {
-        if (isFullscreenMode()) {
-            return getResources().getDrawable(
-                    com.android.internal.R.drawable.input_method_fullscreen_background);
-        }
-        return null;
-    }
-    
-    /**
      * Called by the framework to create the layout for showing extacted text.
      * Only called when in fullscreen mode.  The returned view hierarchy must
      * have an {@link ExtractEditText} whose ID is 
@@ -1174,6 +1266,23 @@
                 + " mWindowCreated=" + mWindowCreated
                 + " mWindowVisible=" + mWindowVisible
                 + " mInputStarted=" + mInputStarted);
+        
+        if (mInShowWindow) {
+            Log.w(TAG, "Re-entrance in to showWindow");
+            return;
+        }
+        
+        try {
+            mWindowWasVisible = mWindowVisible;
+            mInShowWindow = true;
+            showWindowInner(showInput);
+        } finally {
+            mWindowWasVisible = true;
+            mInShowWindow = false;
+        }
+    }
+    
+    void showWindowInner(boolean showInput) {
         boolean doShowInput = false;
         boolean wasVisible = mWindowVisible;
         mWindowVisible = true;
@@ -1241,6 +1350,7 @@
             mWindow.hide();
             mWindowVisible = false;
             onWindowHidden();
+            mWindowWasVisible = false;
         }
     }
     
@@ -1559,7 +1669,7 @@
     
     boolean doMovementKey(int keyCode, KeyEvent event, int count) {
         final ExtractEditText eet = mExtractEditText;
-        if (isFullscreenMode() && isInputViewShown() && eet != null) {
+        if (isExtractViewShown() && isInputViewShown() && eet != null) {
             // If we are in fullscreen mode, the cursor will move around
             // the extract edit text, but should NOT cause focus to move
             // to other fields.
@@ -1583,10 +1693,10 @@
                     if (movement.onKeyOther(eet, (Spannable)eet.getText(), event)) {
                         reportExtractedMovement(keyCode, count);
                     } else {
-                        KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN);
+                        KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN);
                         if (movement.onKeyDown(eet,
                                 (Spannable)eet.getText(), keyCode, down)) {
-                            KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP);
+                            KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
                             movement.onKeyUp(eet,
                                     (Spannable)eet.getText(), keyCode, up);
                             while (--count > 0) {
@@ -1800,18 +1910,52 @@
     }
     
     /**
-     * Called when it is time to update the actions available from a full-screen
-     * IME.  You do not need to deal with this if you are using the standard
-     * full screen extract UI.  If replacing it, you will need to re-implement
-     * this to put the action in your own UI and handle it.
+     * Called when the fullscreen-mode extracting editor info has changed,
+     * to determine whether the extracting (extract text and candidates) portion
+     * of the UI should be shown.  The standard implementation hides or shows
+     * the extract area depending on whether it makes sense for the
+     * current editor.  In particular, a {@link InputType#TYPE_NULL}
+     * input type or {@link EditorInfo#IME_FLAG_NO_EXTRACT_UI} flag will
+     * turn off the extract area since there is no text to be shown.
      */
-    public void onUpdateExtractingAccessories(EditorInfo ei) {
+    public void onUpdateExtractingVisibility(EditorInfo ei) {
+        if (ei.inputType == InputType.TYPE_NULL ||
+                (ei.imeOptions&EditorInfo.IME_FLAG_NO_EXTRACT_UI) != 0) {
+            // No reason to show extract UI!
+            setExtractViewShown(false);
+            return;
+        }
+        
+        setExtractViewShown(true);
+    }
+    
+    /**
+     * Called when the fullscreen-mode extracting editor info has changed,
+     * to update the state of its UI such as the action buttons shown.
+     * You do not need to deal with this if you are using the standard
+     * full screen extract UI.  If replacing it, you will need to re-implement
+     * this to put the appropriate action button in your own UI and handle it,
+     * and perform any other changes.
+     * 
+     * <p>The standard implementation turns on or off its accessory area
+     * depending on whether there is an action button, and hides or shows
+     * the entire extract area depending on whether it makes sense for the
+     * current editor.  In particular, a {@link InputType#TYPE_NULL} or 
+     * {@link InputType#TYPE_TEXT_VARIATION_FILTER} input type will turn off the
+     * extract area since there is no text to be shown.
+     */
+    public void onUpdateExtractingViews(EditorInfo ei) {
+        if (!isExtractViewShown()) {
+            return;
+        }
+        
         if (mExtractAccessories == null) {
             return;
         }
         final boolean hasAction = ei.actionLabel != null || (
                 (ei.imeOptions&EditorInfo.IME_MASK_ACTION) != EditorInfo.IME_ACTION_NONE &&
-                (ei.imeOptions&EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0);
+                (ei.imeOptions&EditorInfo.IME_FLAG_NO_ACCESSORY_ACTION) == 0 &&
+                ei.inputType != InputType.TYPE_NULL);
         if (hasAction) {
             mExtractAccessories.setVisibility(View.VISIBLE);
             if (ei.actionLabel != null) {
@@ -1855,7 +1999,8 @@
             
             try {
                 eet.startInternalChanges();
-                onUpdateExtractingAccessories(ei);
+                onUpdateExtractingVisibility(ei);
+                onUpdateExtractingViews(ei);
                 int inputType = ei.inputType;
                 if ((inputType&EditorInfo.TYPE_MASK_CLASS)
                         == EditorInfo.TYPE_CLASS_TEXT) {
@@ -1890,8 +2035,10 @@
         final Printer p = new PrintWriterPrinter(fout);
         p.println("Input method service state for " + this + ":");
         p.println("  mWindowCreated=" + mWindowCreated
-                + " mWindowAdded=" + mWindowAdded
-                + " mWindowVisible=" + mWindowVisible);
+                + " mWindowAdded=" + mWindowAdded);
+        p.println("  mWindowVisible=" + mWindowVisible
+                + " mWindowWasVisible=" + mWindowWasVisible
+                + " mInShowWindow=" + mInShowWindow);
         p.println("  Configuration=" + getResources().getConfiguration());
         p.println("  mToken=" + mToken);
         p.println("  mInputBinding=" + mInputBinding);
@@ -1914,7 +2061,8 @@
                 + " mShowInputFlags=0x" + Integer.toHexString(mShowInputFlags));
         p.println("  mCandidatesVisibility=" + mCandidatesVisibility
                 + " mFullscreenApplied=" + mFullscreenApplied
-                + " mIsFullscreen=" + mIsFullscreen);
+                + " mIsFullscreen=" + mIsFullscreen
+                + " mExtractViewHidden=" + mExtractViewHidden);
         
         if (mExtractedText != null) {
             p.println("  mExtractedText:");
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index c37845f..d91ace6 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -31,18 +31,6 @@
  */
 class SoftInputWindow extends Dialog {
 
-    /**
-     * Create a DockWindow that uses the default style.
-     * 
-     * @param context The Context the DockWindow is to run it. In particular, it
-     *        uses the window manager and theme in this context to present its
-     *        UI.
-     */
-    public SoftInputWindow(Context context) {
-        super(context, com.android.internal.R.style.Theme_InputMethod);
-        initDockWindow();
-    }
-
     public void setToken(IBinder token) {
         WindowManager.LayoutParams lp = getWindow().getAttributes();
         lp.token = token;
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index 7590bfe..76c74df 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -4,6 +4,8 @@
 import java.util.Formatter;
 import java.util.Map;
 
+import com.android.internal.os.BatteryStatsImpl.Timer;
+
 import android.util.Log;
 import android.util.Printer;
 import android.util.SparseArray;
@@ -39,6 +41,20 @@
      * {@hide}
      */
     public static final int SENSOR = 3;
+    
+    /**
+     * A constant indicating a full wifi lock timer
+     *
+     * {@hide}
+     */
+    public static final int FULL_WIFI_LOCK = 4;
+    
+    /**
+     * A constant indicating a scan wifi lock timer
+     *
+     * {@hide}
+     */
+    public static final int SCAN_WIFI_LOCK = 5;
 
     /**
      * Include all of the data in the stats, including previously saved data.
@@ -74,6 +90,7 @@
     private static final String WAKELOCK_DATA = "wakelock";
     private static final String NETWORK_DATA = "network";
     private static final String BATTERY_DATA = "battery";
+    private static final String WIFI_LOCK_DATA = "wifilock";
     private static final String MISC_DATA = "misc";
 
     private final StringBuilder mFormatBuilder = new StringBuilder(8);
@@ -162,6 +179,13 @@
          * {@hide}
          */
         public abstract long getTcpBytesSent(int which);
+        
+        public abstract void noteFullWifiLockAcquiredLocked();
+        public abstract void noteFullWifiLockReleasedLocked();
+        public abstract void noteScanWifiLockAcquiredLocked();
+        public abstract void noteScanWifiLockReleasedLocked();
+        public abstract long getFullWifiLockTime(long batteryRealtime, int which);
+        public abstract long getScanWifiLockTime(long batteryRealtime, int which);
 
         public static abstract class Sensor {
             // Magic sensor number for the GPS.
@@ -270,6 +294,22 @@
     public abstract long getPhoneOnTime(long batteryRealtime, int which);
     
     /**
+     * Returns the time in milliseconds that wifi has been on while the device was
+     * running on battery.
+     * 
+     * {@hide}
+     */
+    public abstract long getWifiOnTime(long batteryRealtime, int which);
+    
+    /**
+     * Returns the time in milliseconds that bluetooth has been on while the device was
+     * running on battery.
+     * 
+     * {@hide}
+     */
+    public abstract long getBluetoothOnTime(long batteryRealtime, int which);
+    
+    /**
      * Return whether we are currently running on battery.
      */
     public abstract boolean getIsOnBattery();
@@ -292,6 +332,17 @@
      * @param curTime the amount of elapsed realtime in microseconds.
      */
     public abstract long getBatteryRealtime(long curTime);
+    
+    /**
+     * Returns the battery percentage level at the last time the device was unplugged from power, 
+     * or the last time it was booted while unplugged.
+     */
+    public abstract int getUnpluggedStartLevel();
+    
+    /**
+     * Returns the battery percentage level at the last time the device was plugged into power.
+     */
+    public abstract int getPluggedStartLevel();
 
     /**
      * Returns the total, last, or current battery uptime in microseconds.
@@ -483,6 +534,8 @@
         final long totalUptime = computeUptime(rawUptime, which);
         final long screenOnTime = getScreenOnTime(batteryRealtime, which);
         final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
+        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
+        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
        
         StringBuilder sb = new StringBuilder(128);
         
@@ -496,7 +549,12 @@
         
         // Dump misc stats
         dumpLine(pw, 0 /* uid */, category, MISC_DATA,
-                screenOnTime / 1000, phoneOnTime / 1000);
+                screenOnTime / 1000, phoneOnTime / 1000, wifiOnTime / 1000, bluetoothOnTime / 1000);
+        
+        if (which == STATS_UNPLUGGED) {
+            dumpLine(pw, 0 /* uid */, category, BATTERY_DATA, getUnpluggedStartLevel(), 
+                    getPluggedStartLevel());
+        }
         
         SparseArray<? extends Uid> uidStats = getUidStats();
         final int NU = uidStats.size();
@@ -506,7 +564,15 @@
             // Dump Network stats per uid, if any
             long rx = u.getTcpBytesReceived(which);
             long tx = u.getTcpBytesSent(which);
+            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
+            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+            
             if (rx > 0 || tx > 0) dumpLine(pw, uid, category, NETWORK_DATA, rx, tx);
+            
+            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
+                dumpLine(pw, uid, category, WIFI_LOCK_DATA, 
+                        fullWifiLockOnTime, scanWifiLockOnTime);
+            }
 
             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
             if (wakelocks.size() > 0) {
@@ -624,13 +690,35 @@
                 + formatTimeMs(totalRealtime / 1000)
                 + "realtime");
         
-        long screenOnTime = getScreenOnTime(batteryRealtime, which);
-        long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
+        final long screenOnTime = getScreenOnTime(batteryRealtime, which);
+        final long phoneOnTime = getPhoneOnTime(batteryRealtime, which);
+        final long wifiOnTime = getWifiOnTime(batteryRealtime, which);
+        final long bluetoothOnTime = getBluetoothOnTime(batteryRealtime, which);
         pw.println(prefix
                 + "  Time with screen on: " + formatTimeMs(screenOnTime / 1000)
                 + "(" + formatRatioLocked(screenOnTime, whichBatteryRealtime)
                 + "), time with phone on: " + formatTimeMs(phoneOnTime / 1000)
-                + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime) + ")");
+                + "(" + formatRatioLocked(phoneOnTime, whichBatteryRealtime)
+                + "), time with wifi on: " + formatTimeMs(wifiOnTime / 1000)
+                + "(" + formatRatioLocked(wifiOnTime, whichBatteryRealtime)
+                + "), time with bluetooth on: " + formatTimeMs(bluetoothOnTime / 1000)
+                + "(" + formatRatioLocked(bluetoothOnTime, whichBatteryRealtime)+ ")");
+        
+        pw.println(" ");
+
+        if (which == STATS_UNPLUGGED) {
+            if (getIsOnBattery()) {
+                pw.println(prefix + "  Device is currently unplugged");
+                pw.println(prefix + "    Discharge cycle start level: " + 
+                        getUnpluggedStartLevel());
+            } else {
+                pw.println(prefix + "  Device is currently plugged into power");
+                pw.println(prefix + "    Last discharge cycle start level: " + 
+                        getUnpluggedStartLevel());
+                pw.println(prefix + "    Last discharge cycle end level: " + 
+                        getPluggedStartLevel());
+            }
+        }
         
         pw.println(" ");
 
@@ -644,10 +732,23 @@
             
             long tcpReceived = u.getTcpBytesReceived(which);
             long tcpSent = u.getTcpBytesSent(which);
+            long fullWifiLockOnTime = u.getFullWifiLockTime(batteryRealtime, which);
+            long scanWifiLockOnTime = u.getScanWifiLockTime(batteryRealtime, which);
+            
             if (tcpReceived != 0 || tcpSent != 0) {
                 pw.println(prefix + "    Network: " + tcpReceived + " bytes received, "
                         + tcpSent + " bytes sent");
             }
+            if (fullWifiLockOnTime != 0 || scanWifiLockOnTime != 0) {
+                pw.println(prefix + "    Full Wifi Lock Time: " 
+                        + formatTime(fullWifiLockOnTime / 1000) 
+                        + "(" + formatRatioLocked(fullWifiLockOnTime, 
+                                whichBatteryRealtime)+ ")");
+                pw.println(prefix + "    Scan Wifi Lock Time: " 
+                        + formatTime(scanWifiLockOnTime / 1000)
+                        + "(" + formatRatioLocked(scanWifiLockOnTime, 
+                                whichBatteryRealtime)+ ")");
+            }
 
             Map<String, ? extends BatteryStats.Uid.Wakelock> wakelocks = u.getWakelockStats();
             if (wakelocks.size() > 0) {
diff --git a/core/java/android/os/Hardware.java b/core/java/android/os/Hardware.java
index 3b6c9d7..efc5617 100644
--- a/core/java/android/os/Hardware.java
+++ b/core/java/android/os/Hardware.java
@@ -21,22 +21,29 @@
  */
 public class Hardware 
 {
-    /**
-     * Control the LED.
-     */
-    public static native int setLedState(int colorARGB, int onMS, int offMS);
-    
-    /**
-     * Control the Flashlight
-     */
+
+
+    /* ********************************************************************************
+     *
+     *
+     *
+     *
+     *
+     *
+     *
+     *
+     *   Don't add anything else to this class.  Add it to HardwareService instead.
+     *
+     *
+     *
+     *
+     *
+     *
+     *
+     * ********************************************************************************/
+
+
     public static native boolean getFlashlightEnabled();
     public static native void setFlashlightEnabled(boolean on);
     public static native void enableCameraFlash(int milliseconds);
-
-    /**
-     * Control the backlights
-     */
-    public static native void setScreenBacklight(int brightness);
-    public static native void setKeyboardBacklight(boolean on);
-    public static native void setButtonBacklight(boolean on);
 }
diff --git a/core/java/android/os/IHardwareService.aidl b/core/java/android/os/IHardwareService.aidl
index 4f6029f..fb121bb 100755
--- a/core/java/android/os/IHardwareService.aidl
+++ b/core/java/android/os/IHardwareService.aidl
@@ -29,12 +29,10 @@
     void setFlashlightEnabled(boolean on);
     void enableCameraFlash(int milliseconds);
     
-    // backlight support
-    void setScreenBacklight(int brightness);
-    void setKeyboardBacklight(boolean on);
-    void setButtonBacklight(boolean on);
-    
-    // LED support
-    void setLedState(int colorARGB, int onMS, int offMS);
+    // sets the brightness of the backlights (screen, keyboard, button) 0-255
+    void setBacklights(int brightness);
+
+    // for the phone
+    void setAttentionLight(boolean on);
 }
 
diff --git a/core/java/android/os/Power.java b/core/java/android/os/Power.java
index b53e227..47497e5 100644
--- a/core/java/android/os/Power.java
+++ b/core/java/android/os/Power.java
@@ -45,26 +45,6 @@
     public static native void releaseWakeLock(String id);
 
     /**
-     * Flag to turn on and off the keyboard light.
-     */
-    public static final int KEYBOARD_LIGHT = 0x00000001;
-
-    /**
-     * Flag to turn on and off the screen backlight.
-     */
-    public static final int SCREEN_LIGHT = 0x00000002;
-
-    /**
-     * Flag to turn on and off the button backlight.
-     */
-    public static final int BUTTON_LIGHT = 0x00000004;
-
-    /**
-     * Flags to turn on and off all the backlights.
-     */
-    public static final int ALL_LIGHTS = (KEYBOARD_LIGHT|SCREEN_LIGHT|BUTTON_LIGHT);
-
-    /**
      * Brightness value for fully off
      */
     public static final int BRIGHTNESS_OFF = 0;
@@ -91,14 +71,6 @@
     public static final int LOW_BATTERY_THRESHOLD = 10;
 
     /**
-     * Set the brightness for one or more lights
-     *
-     * @param mask flags indicating which lights to change brightness
-     * @param brightness new brightness value (0 = off, 255 = fully bright)
-     */
-    public static native int setLightBrightness(int mask, int brightness);
-
-    /**
      * Turn the screen on or off
      *
      * @param on Whether you want the screen on or off
diff --git a/core/java/android/os/RemoteCallbackList.java b/core/java/android/os/RemoteCallbackList.java
index 04e7ef0..63f6dff 100644
--- a/core/java/android/os/RemoteCallbackList.java
+++ b/core/java/android/os/RemoteCallbackList.java
@@ -211,7 +211,7 @@
             for (Callback cb : mCallbacks.values()) {
                 active[i++] = cb.mCallback;
             }
-            return N;
+            return i;
         }
     }
     
diff --git a/core/java/android/provider/Calendar.java b/core/java/android/provider/Calendar.java
index d75a25f..4a709f6 100644
--- a/core/java/android/provider/Calendar.java
+++ b/core/java/android/provider/Calendar.java
@@ -1054,6 +1054,9 @@
             if (cursor == null) {
                 return;
             }
+            if (Log.isLoggable(TAG, Log.DEBUG)) {
+                Log.d(TAG, "missed alarms found: " + cursor.getCount());
+            }
             
             try {
                 while (cursor.moveToNext()) {
@@ -1068,6 +1071,8 @@
                     intent.putExtra(android.provider.Calendar.EVENT_END_TIME, end);
                     PendingIntent sender = PendingIntent.getBroadcast(context,
                             0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+                    Log.w(TAG, "rescheduling missed alarm, id: " + id + " begin: " + begin
+                            + " end: " + end + " alarmTime: " + alarmTime);
                     manager.set(AlarmManager.RTC_WAKEUP, alarmTime, sender);
                 }
             } finally {
diff --git a/core/java/android/provider/CallLog.java b/core/java/android/provider/CallLog.java
index 10fe3f5..abd6934 100644
--- a/core/java/android/provider/CallLog.java
+++ b/core/java/android/provider/CallLog.java
@@ -22,6 +22,8 @@
 import android.net.Uri;
 import android.provider.Contacts.People;
 import com.android.internal.telephony.CallerInfo;
+import com.android.internal.telephony.Connection;
+
 import android.text.TextUtils;
 import android.util.Log;
 
@@ -137,7 +139,8 @@
          * if the contact is unknown.
          * @param context the context used to get the ContentResolver
          * @param number the phone number to be added to the calls db
-         * @param isPrivateNumber <code>true</code> if the call was marked as private by the network
+         * @param presentation the number presenting rules set by the network for 
+         *        "allowed", "payphone", "restricted" or "unknown"
          * @param callType enumerated values for "incoming", "outgoing", or "missed"
          * @param start time stamp for the call in milliseconds
          * @param duration call duration in seconds
@@ -145,12 +148,14 @@
          * {@hide}
          */
         public static Uri addCall(CallerInfo ci, Context context, String number, 
-                boolean isPrivateNumber, int callType, long start, int duration) {
+                int presentation, int callType, long start, int duration) {
             final ContentResolver resolver = context.getContentResolver();
 
             if (TextUtils.isEmpty(number)) {
-                if (isPrivateNumber) {
+                if (presentation == Connection.PRESENTATION_RESTRICTED) {
                     number = CallerInfo.PRIVATE_NUMBER;
+                } else if (presentation == Connection.PRESENTATION_PAYPHONE) {
+                    number = CallerInfo.PAYPHONE_NUMBER;
                 } else {
                     number = CallerInfo.UNKNOWN_NUMBER;
                 }
diff --git a/core/java/android/provider/Contacts.java b/core/java/android/provider/Contacts.java
index 2aa77ea..be31c0a 100644
--- a/core/java/android/provider/Contacts.java
+++ b/core/java/android/provider/Contacts.java
@@ -1459,13 +1459,24 @@
                 "com.android.contacts.action.SHOW_OR_CREATE_CONTACT";
 
         /**
-         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new contact if no matching
-         * contact found.  Otherwise, default behavior is to prompt user with dialog before creating.
-         *
-         * <P>Type: BOOLEAN</P>
+         * Used with {@link #SHOW_OR_CREATE_CONTACT} to force creating a new
+         * contact if no matching contact found. Otherwise, default behavior is
+         * to prompt user with dialog before creating.
+         * <p>
+         * Type: BOOLEAN
          */
         public static final String EXTRA_FORCE_CREATE =
                 "com.android.contacts.action.FORCE_CREATE";
+        
+        /**
+         * Used with {@link #SHOW_OR_CREATE_CONTACT} to specify an exact
+         * description to be shown when prompting user about creating a new
+         * contact.
+         * <p>
+         * Type: STRING
+         */
+        public static final String EXTRA_CREATE_DESCRIPTION =
+            "com.android.contacts.action.CREATE_DESCRIPTION";
 
         /**
          * Intents related to the Contacts app UI.
diff --git a/core/java/android/server/BluetoothA2dpService.java b/core/java/android/server/BluetoothA2dpService.java
index 3aa4078..3c50707 100644
--- a/core/java/android/server/BluetoothA2dpService.java
+++ b/core/java/android/server/BluetoothA2dpService.java
@@ -63,6 +63,7 @@
     private final IntentFilter mIntentFilter;
     private HashMap<String, SinkState> mAudioDevices;
     private final AudioManager mAudioManager;
+    private final BluetoothDevice mBluetooth;
 
     private class SinkState {
         public String address;
@@ -75,9 +76,8 @@
 
         mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
 
-        BluetoothDevice device =
-                (BluetoothDevice)mContext.getSystemService(Context.BLUETOOTH_SERVICE);
-        if (device == null) {
+        mBluetooth = (BluetoothDevice) mContext.getSystemService(Context.BLUETOOTH_SERVICE);
+        if (mBluetooth == null) {
             throw new RuntimeException("Platform does not support Bluetooth");
         }
 
@@ -85,13 +85,12 @@
             throw new RuntimeException("Could not init BluetoothA2dpService");
         }
 
-        mIntentFilter = new IntentFilter(BluetoothIntent.ENABLED_ACTION);
-        mIntentFilter.addAction(BluetoothIntent.DISABLED_ACTION);
+        mIntentFilter = new IntentFilter(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
         mIntentFilter.addAction(BluetoothIntent.BOND_STATE_CHANGED_ACTION);
         mIntentFilter.addAction(BluetoothIntent.REMOTE_DEVICE_CONNECTED_ACTION);
         mContext.registerReceiver(mReceiver, mIntentFilter);
 
-        if (device.isEnabled()) {
+        if (mBluetooth.isEnabled()) {
             onBluetoothEnable();
         }
     }
@@ -110,10 +109,17 @@
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
             String address = intent.getStringExtra(BluetoothIntent.ADDRESS);
-            if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
-                onBluetoothEnable();
-            } else if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
-                onBluetoothDisable();
+            if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) {
+                int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
+                                               BluetoothError.ERROR);
+                switch (state) {
+                case BluetoothDevice.BLUETOOTH_STATE_ON:
+                    onBluetoothEnable();
+                    break;
+                case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF:
+                    onBluetoothDisable();
+                    break;
+                }
             } else if (action.equals(BluetoothIntent.BOND_STATE_CHANGED_ACTION)) {
                 int bondState = intent.getIntExtra(BluetoothIntent.BOND_STATE,
                                                    BluetoothError.ERROR);
@@ -145,9 +151,10 @@
             switch (msg.what) {
             case MESSAGE_CONNECT_TO:
                 String address = (String)msg.obj;
-                // check device is still preferred, and nothing is currently
-                // connected
-                if (getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF &&
+                // check bluetooth is still on, device is still preferred, and
+                // nothing is currently connected
+                if (mBluetooth.isEnabled() &&
+                        getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF &&
                         lookupSinksMatchingStates(new int[] {
                             BluetoothA2dp.STATE_CONNECTING,
                             BluetoothA2dp.STATE_CONNECTED,
diff --git a/core/java/android/server/BluetoothDeviceService.java b/core/java/android/server/BluetoothDeviceService.java
index 9e9ba62..b7e3846 100644
--- a/core/java/android/server/BluetoothDeviceService.java
+++ b/core/java/android/server/BluetoothDeviceService.java
@@ -37,8 +37,10 @@
 import android.content.IntentFilter;
 import android.os.Binder;
 import android.os.Handler;
+import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.SystemService;
 import android.provider.Settings;
 import android.util.Log;
@@ -51,6 +53,8 @@
 import java.util.HashMap;
 import java.util.Map;
 
+import com.android.internal.app.IBatteryStats;
+
 public class BluetoothDeviceService extends IBluetoothDevice.Stub {
     private static final String TAG = "BluetoothDeviceService";
     private static final boolean DBG = true;
@@ -60,14 +64,18 @@
     private IntentFilter mIntentFilter;
     private boolean mIsAirplaneSensitive;
     private final BondState mBondState = new BondState();  // local cache of bondings
-    private volatile boolean mIsEnabled;  // local cache of isEnabledNative()
+    private int mBluetoothState;
     private boolean mIsDiscovering;
+    private final IBatteryStats mBatteryStats;
 
     private final Context mContext;
 
     private static final String BLUETOOTH_ADMIN_PERM = android.Manifest.permission.BLUETOOTH_ADMIN;
     private static final String BLUETOOTH_PERM = android.Manifest.permission.BLUETOOTH;
 
+    private static final int MESSAGE_REGISTER_SDP_RECORDS = 1;
+    private static final int MESSAGE_FINISH_DISABLE = 2;
+
     static {
         classInitNative();
     }
@@ -75,6 +83,12 @@
 
     public BluetoothDeviceService(Context context) {
         mContext = context;
+
+        // Need to do this in place of:
+        // mBatteryStats = BatteryStatsService.getService();
+        // Since we can not import BatteryStatsService from here. This class really needs to be
+        // moved to java/services/com/android/server/
+        mBatteryStats = IBatteryStats.Stub.asInterface(ServiceManager.getService("batteryinfo"));
     }
 
     /** Must be called after construction, and before any other method.
@@ -87,7 +101,7 @@
             disableNative();
         }
 
-        mIsEnabled = false;
+        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF);
         mIsDiscovering = false;
         mEventLoop = new BluetoothEventLoop(mContext, this);
         registerForAirplaneMode();
@@ -109,10 +123,16 @@
 
     public boolean isEnabled() {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
-        return mIsEnabled;
+        return mBluetoothState == BluetoothDevice.BLUETOOTH_STATE_ON;
     }
     private native int isEnabledNative();
 
+    public int getBluetoothState() {
+        mContext.enforceCallingOrSelfPermission(BLUETOOTH_PERM, "Need BLUETOOTH permission");
+        return mBluetoothState;
+    }
+
+
     /**
      * Bring down bluetooth and disable BT in settings. Returns true on success.
      */
@@ -124,17 +144,36 @@
      * Bring down bluetooth. Returns true on success.
      *
      * @param saveSetting If true, disable BT in settings
-     *
      */
     public synchronized boolean disable(boolean saveSetting) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                 "Need BLUETOOTH_ADMIN permission");
 
+        switch (mBluetoothState) {
+        case BluetoothDevice.BLUETOOTH_STATE_OFF:
+            return true;
+        case BluetoothDevice.BLUETOOTH_STATE_ON:
+            break;
+        default:
+            return false;
+        }
         if (mEnableThread != null && mEnableThread.isAlive()) {
             return false;
         }
-        if (!mIsEnabled) {
-            return true;
+        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF);
+
+        // Allow 3 seconds for profiles to gracefully disconnect
+        // TODO: Introduce a callback mechanism so that each profile can notify
+        // BluetoothDeviceService when it is done shutting down
+        mHandler.sendMessageDelayed(
+                mHandler.obtainMessage(MESSAGE_FINISH_DISABLE, saveSetting ? 1 : 0, 0), 3000);
+        return true;
+    }
+
+
+    private synchronized void finishDisable(boolean saveSetting) {
+        if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) {
+            return;
         }
         mEventLoop.stop();
         disableNative();
@@ -163,38 +202,37 @@
         intent.putExtra(BluetoothIntent.SCAN_MODE, BluetoothDevice.SCAN_MODE_NONE);
         mContext.sendBroadcast(intent, BLUETOOTH_PERM);
 
-        mIsEnabled = false;
+        mIsDiscovering = false;
+
         if (saveSetting) {
             persistBluetoothOnSetting(false);
         }
-        mIsDiscovering = false;
-        intent = new Intent(BluetoothIntent.DISABLED_ACTION);
-        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
-        return true;
+
+        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_OFF);
+
+        // Log bluetooth off to battery stats.
+        long ident = Binder.clearCallingIdentity();
+        try {
+            mBatteryStats.noteBluetoothOff();
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
     }
 
-    /**
-     * Bring up bluetooth, asynchronously, and enable BT in settings.
-     * This turns on/off the underlying hardware.
-     *
-     * @return True on success (so far), guaranteeing the callback with be
-     * notified when complete.
-     */
-    public boolean enable(IBluetoothDeviceCallback callback) {
-        return enable(callback, true);
+    /** Bring up BT and persist BT on in settings */
+    public boolean enable() {
+        return enable(true);
     }
 
     /**
      * Enable this Bluetooth device, asynchronously.
      * This turns on/off the underlying hardware.
      *
-     * @param saveSetting If true, enable BT in settings
-     *
-     * @return True on success (so far), guaranteeing the callback with be
-     * notified when complete.
+     * @param saveSetting If true, persist the new state of BT in settings
+     * @return True on success (so far)
      */
-    public synchronized boolean enable(IBluetoothDeviceCallback callback,
-            boolean saveSetting) {
+    public synchronized boolean enable(boolean saveSetting) {
         mContext.enforceCallingOrSelfPermission(BLUETOOTH_ADMIN_PERM,
                                                 "Need BLUETOOTH_ADMIN permission");
 
@@ -202,28 +240,49 @@
         if (mIsAirplaneSensitive && isAirplaneModeOn()) {
             return false;
         }
-        if (mIsEnabled) {
+        if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_OFF) {
             return false;
         }
         if (mEnableThread != null && mEnableThread.isAlive()) {
             return false;
         }
-        mEnableThread = new EnableThread(callback, saveSetting);
+        setBluetoothState(BluetoothDevice.BLUETOOTH_STATE_TURNING_ON);
+        mEnableThread = new EnableThread(saveSetting);
         mEnableThread.start();
         return true;
     }
 
-    private static final int REGISTER_SDP_RECORDS = 1;
+    private synchronized void setBluetoothState(int state) {
+        if (state == mBluetoothState) {
+            return;
+        }
+
+        if (DBG) log("Bluetooth state " + mBluetoothState + " -> " + state);
+
+        Intent intent = new Intent(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
+        intent.putExtra(BluetoothIntent.BLUETOOTH_PREVIOUS_STATE, mBluetoothState);
+        intent.putExtra(BluetoothIntent.BLUETOOTH_STATE, state);
+        intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+
+        mBluetoothState = state;
+
+        mContext.sendBroadcast(intent, BLUETOOTH_PERM);
+    }
+
     private final Handler mHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
             switch (msg.what) {
-            case REGISTER_SDP_RECORDS:
+            case MESSAGE_REGISTER_SDP_RECORDS:
                 //TODO: Don't assume HSP/HFP is running, don't use sdptool,
                 if (isEnabled()) {
                     SystemService.start("hsag");
                     SystemService.start("hfag");
                 }
+                break;
+            case MESSAGE_FINISH_DISABLE:
+                finishDisable(msg.arg1 != 0);
+                break;
             }
         }
     };
@@ -231,10 +290,8 @@
     private EnableThread mEnableThread;
 
     private class EnableThread extends Thread {
-        private final IBluetoothDeviceCallback mEnableCallback;
         private final boolean mSaveSetting;
-        public EnableThread(IBluetoothDeviceCallback callback, boolean saveSetting) {
-            mEnableCallback = callback;
+        public EnableThread(boolean saveSetting) {
             mSaveSetting = saveSetting;
         }
         public void run() {
@@ -244,7 +301,7 @@
                 boolean running = false;
                 while ((retryCount-- > 0) && !running) {
                     mEventLoop.start();
-                    // it may take a momement for the other thread to do its 
+                    // it may take a momement for the other thread to do its
                     // thing.  Check periodically for a while.
                     int pollCount = 5;
                     while ((pollCount-- > 0) && !running) {
@@ -264,36 +321,37 @@
                 }
             }
 
-            if (mEnableCallback != null) {
-                try {
-                    mEnableCallback.onEnableResult(res ?
-                                                   BluetoothDevice.RESULT_SUCCESS :
-                                                   BluetoothDevice.RESULT_FAILURE);
-                } catch (RemoteException e) {}
-            }
 
             if (res) {
-                mIsEnabled = true;
                 if (mSaveSetting) {
                     persistBluetoothOnSetting(true);
                 }
                 mIsDiscovering = false;
                 mBondState.loadBondState();
-                mHandler.sendMessageDelayed(mHandler.obtainMessage(REGISTER_SDP_RECORDS), 3000);
+                mHandler.sendMessageDelayed(mHandler.obtainMessage(MESSAGE_REGISTER_SDP_RECORDS),
+                                            3000);
 
+                // Log bluetooth on to battery stats.
+                long ident = Binder.clearCallingIdentity();
+                try {
+                    mBatteryStats.noteBluetoothOn();
+                } catch (RemoteException e) {
+                } finally {
+                    Binder.restoreCallingIdentity(ident);
+                }
+            }
+
+            mEnableThread = null;
+
+            setBluetoothState(res ?
+                              BluetoothDevice.BLUETOOTH_STATE_ON :
+                              BluetoothDevice.BLUETOOTH_STATE_OFF);
+
+            if (res) {
                 // Update mode
                 mEventLoop.onModeChanged(getModeNative());
             }
-            Intent intent = null;
-            if (res) {
-                intent = new Intent(BluetoothIntent.ENABLED_ACTION);
-            } else {
-                intent = new Intent(BluetoothIntent.DISABLED_ACTION);
-            }
-            intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
-            mContext.sendBroadcast(intent, BLUETOOTH_PERM);
 
-            mEnableThread = null;
         }
     }
 
@@ -320,18 +378,24 @@
         private final HashMap<String, Integer> mState = new HashMap<String, Integer>();
         private final HashMap<String, Integer> mPinAttempt = new HashMap<String, Integer>();
         private final ArrayList<String> mAutoPairingFailures = new ArrayList<String>();
-        // List of all the vendor_id prefix of Bluetooth addresses for which
-        // auto pairing is not attempted
+        // List of all the vendor_id prefix of Bluetooth addresses for
+        // which auto pairing is not attempted.
+        // The following companies are included in the list below:
+        // ALPS (lexus), Murata (Prius 2007, Nokia 616), TEMIC SDS (Porsche, Audi),
+        // Parrot, Zhongshan General K-mate Electronics, Great Well
+        // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi,
+        // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura),
         private final ArrayList<String>  mAutoPairingBlacklisted =
                 new ArrayList<String>(Arrays.asList(
-                        "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", //ALPS
-                        "00:21:4F", "00:23:06", "00:24:33", "00:A0:79", // ALPS
-                        "00:0E:6D", "00:13:E0", "00:21:E8", "00:60:57",// Murata for Prius 2007
-                        "00:0E:9F" // TEMIC SDS  for Porsche
+                        "00:02:C7", "00:16:FE", "00:19:C1", "00:1B:FB", "00:1E:3D", "00:21:4F",
+                        "00:23:06", "00:24:33", "00:A0:79", "00:0E:6D", "00:13:E0", "00:21:E8",
+                        "00:60:57", "00:0E:9F", "00:12:1C", "00:18:91", "00:18:96", "00:13:04",
+                        "00:16:FD", "00:22:A0", "00:0B:4C", "00:60:6F", "00:23:3D", "00:C0:59",
+                        "00:0A:30"
                         ));
 
         public synchronized void loadBondState() {
-            if (!mIsEnabled) {
+            if (mBluetoothState != BluetoothDevice.BLUETOOTH_STATE_TURNING_ON) {
                 return;
             }
             String[] bonds = listBondingsNative();
@@ -1051,7 +1115,7 @@
                 // If bluetooth is currently expected to be on, then enable or disable bluetooth
                 if (Settings.Secure.getInt(resolver, Settings.Secure.BLUETOOTH_ON, 0) > 0) {
                     if (enabled) {
-                        enable(null, false);
+                        enable(false);
                     } else {
                         disable(false);
                     }
@@ -1079,52 +1143,63 @@
 
     @Override
     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
-        if (mIsEnabled) {
-            pw.println("\nBluetooth ENABLED: " + getAddress() + " (" + getName() + ")");
-            pw.println("\nisDiscovering() = " + isDiscovering());
+        pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive + "\n");
 
-            BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
-
-            String[] addresses = listRemoteDevices();
-
-            pw.println("\n--Known devices--");
-            for (String address : addresses) {
-                pw.printf("%s %10s (%d) %s\n", address,
-                           toBondStateString(mBondState.getBondState(address)),
-                           mBondState.getAttempt(address),
-                           getRemoteName(address));
-            }
-
-            addresses = listAclConnections();
-            pw.println("\n--ACL connected devices--");
-            for (String address : addresses) {
-                pw.println(address);
-            }
-
-            // Rather not do this from here, but no-where else and I need this
-            // dump
-            pw.println("\n--Headset Service--");
-            switch (headset.getState()) {
-            case BluetoothHeadset.STATE_DISCONNECTED:
-                pw.println("getState() = STATE_DISCONNECTED");
-                break;
-            case BluetoothHeadset.STATE_CONNECTING:
-                pw.println("getState() = STATE_CONNECTING");
-                break;
-            case BluetoothHeadset.STATE_CONNECTED:
-                pw.println("getState() = STATE_CONNECTED");
-                break;
-            case BluetoothHeadset.STATE_ERROR:
-                pw.println("getState() = STATE_ERROR");
-                break;
-            }
-            pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress());
-            headset.close();
-
-        } else {
-            pw.println("\nBluetooth DISABLED");
+        switch(mBluetoothState) {
+        case BluetoothDevice.BLUETOOTH_STATE_OFF:
+            pw.println("\nBluetooth OFF\n");
+            return;
+        case BluetoothDevice.BLUETOOTH_STATE_TURNING_ON:
+            pw.println("\nBluetooth TURNING ON\n");
+            return;
+        case BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF:
+            pw.println("\nBluetooth TURNING OFF\n");
+            return;
+        case BluetoothDevice.BLUETOOTH_STATE_ON:
+            pw.println("\nBluetooth ON\n");
         }
-        pw.println("\nmIsAirplaneSensitive = " + mIsAirplaneSensitive);
+
+        pw.println("\nLocal address = " + getAddress());
+        pw.println("\nLocal name = " + getName());
+        pw.println("\nisDiscovering() = " + isDiscovering());
+
+        BluetoothHeadset headset = new BluetoothHeadset(mContext, null);
+
+        String[] addresses = listRemoteDevices();
+
+        pw.println("\n--Known devices--");
+        for (String address : addresses) {
+            pw.printf("%s %10s (%d) %s\n", address,
+                       toBondStateString(mBondState.getBondState(address)),
+                       mBondState.getAttempt(address),
+                       getRemoteName(address));
+        }
+
+        addresses = listAclConnections();
+        pw.println("\n--ACL connected devices--");
+        for (String address : addresses) {
+            pw.println(address);
+        }
+
+        // Rather not do this from here, but no-where else and I need this
+        // dump
+        pw.println("\n--Headset Service--");
+        switch (headset.getState()) {
+        case BluetoothHeadset.STATE_DISCONNECTED:
+            pw.println("getState() = STATE_DISCONNECTED");
+            break;
+        case BluetoothHeadset.STATE_CONNECTING:
+            pw.println("getState() = STATE_CONNECTING");
+            break;
+        case BluetoothHeadset.STATE_CONNECTED:
+            pw.println("getState() = STATE_CONNECTED");
+            break;
+        case BluetoothHeadset.STATE_ERROR:
+            pw.println("getState() = STATE_ERROR");
+            break;
+        }
+        pw.println("getHeadsetAddress() = " + headset.getHeadsetAddress());
+        headset.close();
     }
 
     /* package */ static int bluezStringToScanMode(String mode) {
@@ -1159,3 +1234,4 @@
         Log.d(TAG, msg);
     }
 }
+
diff --git a/core/java/android/server/BluetoothEventLoop.java b/core/java/android/server/BluetoothEventLoop.java
index 8e77eed..6be8eb9 100644
--- a/core/java/android/server/BluetoothEventLoop.java
+++ b/core/java/android/server/BluetoothEventLoop.java
@@ -46,10 +46,10 @@
     private Thread mThread;
     private boolean mStarted;
     private boolean mInterrupted;
-    private HashMap<String, Integer> mPasskeyAgentRequestData;
-    private HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks;
-    private BluetoothDeviceService mBluetoothService;
-    private Context mContext;
+    private final HashMap<String, Integer> mPasskeyAgentRequestData;
+    private final HashMap<String, IBluetoothDeviceCallback> mGetRemoteServiceChannelCallbacks;
+    private final BluetoothDeviceService mBluetoothService;
+    private final Context mContext;
 
     private static final int EVENT_AUTO_PAIRING_FAILURE_ATTEMPT_DELAY = 1;
     private static final int EVENT_RESTART_BLUETOOTH = 2;
@@ -77,7 +77,7 @@
                 break;
             case EVENT_RESTART_BLUETOOTH:
                 mBluetoothService.disable();
-                mBluetoothService.enable(null);
+                mBluetoothService.enable();
                 break;
             }
         }
@@ -309,6 +309,12 @@
         address = address.toUpperCase();
         mPasskeyAgentRequestData.put(address, new Integer(nativeData));
 
+        if (mBluetoothService.getBluetoothState() == BluetoothDevice.BLUETOOTH_STATE_TURNING_OFF) {
+            // shutdown path
+            mBluetoothService.cancelPin(address);
+            return;
+        }
+
         if (mBluetoothService.getBondState().getBondState(address) ==
                 BluetoothDevice.BOND_BONDING) {
             // we initiated the bonding
@@ -347,7 +353,7 @@
 
     private boolean onAuthAgentAuthorize(String address, String service, String uuid) {
         boolean authorized = false;
-        if (service.endsWith("service_audio")) {
+        if (mBluetoothService.isEnabled() && service.endsWith("service_audio")) {
             BluetoothA2dp a2dp = new BluetoothA2dp(mContext);
             authorized = a2dp.getSinkPriority(address) > BluetoothA2dp.PRIORITY_OFF;
             if (authorized) {
diff --git a/core/java/android/text/Html.java b/core/java/android/text/Html.java
index 8495714..6f0be3a 100644
--- a/core/java/android/text/Html.java
+++ b/core/java/android/text/Html.java
@@ -28,6 +28,8 @@
 import android.content.res.Resources;
 import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
+import android.text.style.AbsoluteSizeSpan;
+import android.text.style.AlignmentSpan;
 import android.text.style.CharacterStyle;
 import android.text.style.ForegroundColorSpan;
 import android.text.style.ImageSpan;
@@ -41,6 +43,7 @@
 import android.text.style.TypefaceSpan;
 import android.text.style.URLSpan;
 import android.text.style.UnderlineSpan;
+import android.util.Log;
 import com.android.internal.util.XmlUtils;
 
 import java.io.IOException;
@@ -137,11 +140,52 @@
      */
     public static String toHtml(Spanned text) {
         StringBuilder out = new StringBuilder();
+        withinHtml(out, text);
+        return out.toString();
+    }
+
+    private static void withinHtml(StringBuilder out, Spanned text) {
         int len = text.length();
 
         int next;
         for (int i = 0; i < text.length(); i = next) {
-            next = text.nextSpanTransition(i, len, QuoteSpan.class);
+            next = text.nextSpanTransition(i, len, ParagraphStyle.class);
+            ParagraphStyle[] style = text.getSpans(i, next, ParagraphStyle.class);
+            if (style.length > 0) {
+                out.append("<div ");
+            }
+            for(int j = 0; j < style.length; j++) {
+                if (style[j] instanceof AlignmentSpan) {
+                    out.append("align=\"");
+                    Layout.Alignment align = 
+                        ((AlignmentSpan) style[j]).getAlignment();
+                    if (align == Layout.Alignment.ALIGN_CENTER) {
+                        out.append("center");
+                    } else if (align == Layout.Alignment.ALIGN_OPPOSITE) {
+                        out.append("right");
+                    } else {
+                        out.append("left");
+                    }
+                    out.append("\" ");
+                }
+            }
+            if (style.length > 0) {
+                out.append(">");
+            }
+
+            withinDiv(out, text, i, next);
+
+            if (style.length > 0) {
+                out.append("</div>");
+            }
+        }
+    }
+
+    private static void withinDiv(StringBuilder out, Spanned text,
+            int start, int end) {
+        int next;
+        for (int i = start; i < end; i = next) {
+            next = text.nextSpanTransition(i, end, QuoteSpan.class);
             QuoteSpan[] quotes = text.getSpans(i, next, QuoteSpan.class);
 
             for (QuoteSpan quote: quotes) {
@@ -154,8 +198,6 @@
                 out.append("</blockquote>\n");
             }
         }
-
-        return out.toString();
     }
 
     private static void withinBlockquote(StringBuilder out, Spanned text,
@@ -234,11 +276,32 @@
                     // Don't output the dummy character underlying the image.
                     i = next;
                 }
+                if (style[j] instanceof AbsoluteSizeSpan) {
+                    out.append("<font size =\"");
+                    out.append(((AbsoluteSizeSpan) style[j]).getSize() / 6);
+                    out.append("\">");
+                }
+                if (style[j] instanceof ForegroundColorSpan) {
+                    out.append("<font color =\"#");
+                    String color = Integer.toHexString(((ForegroundColorSpan)
+                            style[j]).getForegroundColor() + 0x01000000);
+                    while (color.length() < 6) {
+                        color = "0" + color;
+                    }
+                    out.append(color);
+                    out.append("\">");
+                }
             }
 
             withinStyle(out, text, i, next);
 
             for (int j = style.length - 1; j >= 0; j--) {
+                if (style[j] instanceof ForegroundColorSpan) {
+                    out.append("</font>");
+                }
+                if (style[j] instanceof AbsoluteSizeSpan) {
+                    out.append("</font>");
+                }
                 if (style[j] instanceof URLSpan) {
                     out.append("</a>");
                 }
diff --git a/core/java/android/text/Layout.java b/core/java/android/text/Layout.java
index 95acf9d..23e740d 100644
--- a/core/java/android/text/Layout.java
+++ b/core/java/android/text/Layout.java
@@ -16,6 +16,8 @@
 
 package android.text;
 
+import android.emoji.EmojiFactory;
+import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Paint;
 import android.graphics.Rect;
@@ -36,6 +38,20 @@
  * For text that will not change, use a {@link StaticLayout}.
  */
 public abstract class Layout {
+    /* package */ static final EmojiFactory EMOJI_FACTORY =
+        EmojiFactory.newAvailableInstance();
+    /* package */ static final int MIN_EMOJI, MAX_EMOJI;
+
+    static {
+        if (EMOJI_FACTORY != null) {
+            MIN_EMOJI = EMOJI_FACTORY.getMinimumAndroidPua();
+            MAX_EMOJI = EMOJI_FACTORY.getMaximumAndroidPua();
+        } else {
+            MIN_EMOJI = -1;
+            MAX_EMOJI = -1;
+        }
+    };
+
     /**
      * Return how wide a layout would be necessary to display the
      * specified text with one line per paragraph.
@@ -445,7 +461,9 @@
     public abstract int getParagraphDirection(int line);
 
     /**
-     * Returns whether the specified line contains one or more tabs.
+     * Returns whether the specified line contains one or more
+     * characters that need to be handled specially, like tabs
+     * or emoji.
      */
     public abstract boolean getLineContainsTab(int line);
 
@@ -1352,6 +1370,26 @@
                         h = dir * nextTab(text, start, end, h * dir, parspans);
 
                     segstart = j + 1;
+                } else if (hasTabs && buf[j] >= 0xD800 && buf[j] <= 0xDFFF && j + 1 < there) {
+                    int emoji = Character.codePointAt(buf, j);
+
+                    if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) {
+                        Bitmap bm = EMOJI_FACTORY.
+                            getBitmapFromAndroidPua(emoji);
+
+                        if (bm != null) {
+                            h += Styled.drawText(canvas, text,
+                                                 start + segstart, start + j,
+                                                 dir, (i & 1) != 0, x + h,
+                                                 top, y, bottom, paint, workPaint,
+                                                 start + j != end);
+
+                            canvas.drawBitmap(bm, x + h, y - bm.getHeight(), paint);
+                            h += bm.getWidth();
+                            j++;
+                            segstart = j + 1;
+                        }
+                    }
                 }
             }
 
@@ -1394,7 +1432,22 @@
 
             int segstart = here;
             for (int j = hasTabs ? here : there; j <= there; j++) {
-                if (j == there || buf[j] == '\t') {
+                int codept = 0;
+                Bitmap bm = null;
+
+                if (hasTabs && j < there) {
+                    codept = buf[j];
+                }
+
+                if (codept >= 0xD800 && codept <= 0xDFFF && j + 1 < there) {
+                    codept = Character.codePointAt(buf, j);
+
+                    if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) {
+                        bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept);
+                    }
+                }
+
+                if (j == there || codept == '\t' || bm != null) {
                     float segw;
 
                     if (offset < start + j ||
@@ -1449,6 +1502,16 @@
                         h = dir * nextTab(text, start, end, h * dir, tabs);
                     }
 
+                    if (bm != null) {
+                        if (dir == DIR_RIGHT_TO_LEFT) {
+                            h -= bm.getWidth();
+                        } else {
+                            h += bm.getWidth();
+                        }
+
+                        j++;
+                    }
+
                     segstart = j + 1;
                 }
             }
@@ -1488,7 +1551,22 @@
         }
 
         for (int i = hasTabs ? 0 : len; i <= len; i++) {
-            if (i == len || buf[i] == '\t') {
+            int codept = 0;
+            Bitmap bm = null;
+
+            if (hasTabs && i < len) {
+                codept = buf[i];
+            }
+
+            if (codept >= 0xD800 && codept <= 0xDFFF && i < len) {
+                codept = Character.codePointAt(buf, i);
+
+                if (codept >= MIN_EMOJI && codept <= MAX_EMOJI) {
+                    bm = EMOJI_FACTORY.getBitmapFromAndroidPua(codept);
+                }
+            }
+
+            if (i == len || codept == '\t' || bm != null) {
                 workPaint.baselineShift = 0;
 
                 h += Styled.measureText(paint, workPaint, text,
@@ -1505,8 +1583,14 @@
                     }
                 }
 
-                if (i != len)
-                    h = nextTab(text, start, end, h, tabs);
+                if (i != len) {
+                    if (bm == null) {
+                        h = nextTab(text, start, end, h, tabs);
+                    } else {
+                        h += bm.getWidth();
+                        i++;
+                    }
+                }
 
                 if (fm != null) {
                     if (fm.ascent < ab) {
@@ -1522,6 +1606,17 @@
                     if (fm.bottom > bot) {
                         bot = fm.bottom;
                     }
+
+                    if (bm != null) {
+                        int ht = -bm.getHeight();
+
+                        if (ht < ab) {
+                            ab = ht;
+                        }
+                        if (ht < top) {
+                            top = ht;
+                        }
+                    }
                 }
 
                 here = i + 1;
diff --git a/core/java/android/text/StaticLayout.java b/core/java/android/text/StaticLayout.java
index 0fef40b..720d15a 100644
--- a/core/java/android/text/StaticLayout.java
+++ b/core/java/android/text/StaticLayout.java
@@ -16,6 +16,7 @@
 
 package android.text;
 
+import android.graphics.Bitmap;
 import android.graphics.Paint;
 import com.android.internal.util.ArrayUtils;
 import android.util.Log;
@@ -421,11 +422,16 @@
 
                 // dump(chdirs, n, "final");
 
-                // extra: enforce that all tabs go the primary direction
+                // extra: enforce that all tabs and surrogate characters go the
+                // primary direction
+                // TODO: actually do directions right for surrogates
 
                 for (int j = 0; j < n; j++) {
-                    if (chs[j] == '\t')
+                    char c = chs[j];
+
+                    if (c == '\t' || (c >= 0xD800 && c <= 0xDFFF)) {
                         chdirs[j] = SOR;
+                    }
                 }
 
                 // extra: enforce that object replacements go to the
@@ -548,16 +554,29 @@
                     char c = chs[j - start];
                     float before = w;
 
-                    switch (c) {
-                    case '\n':
-                        break;
-
-                    case '\t':
+                    if (c == '\n') {
+                        ;
+                    } else if (c == '\t') {
                         w = Layout.nextTab(sub, start, end, w, null);
                         tab = true;
-                        break;
+                    } else if (c >= 0xD800 && c <= 0xDFFF && j + 1 < next) {
+                        int emoji = Character.codePointAt(chs, j - start);
 
-                    default:
+                        if (emoji >= MIN_EMOJI && emoji <= MAX_EMOJI) {
+                            Bitmap bm = EMOJI_FACTORY.
+                                getBitmapFromAndroidPua(emoji);
+
+                            if (bm != null) {
+                                w += bm.getWidth();
+                                tab = true;
+                                j++;
+                            } else {
+                                w += widths[j - start + (end - start)];
+                            }
+                        } else {
+                            w += widths[j - start + (end - start)];
+                        }
+                    } else {
                         w += widths[j - start + (end - start)];
                     }
 
diff --git a/core/java/android/view/GestureDetector.java b/core/java/android/view/GestureDetector.java
index f7ac522..23f3e3c 100644
--- a/core/java/android/view/GestureDetector.java
+++ b/core/java/android/view/GestureDetector.java
@@ -201,8 +201,6 @@
 
     private static final int LONGPRESS_TIMEOUT = ViewConfiguration.getLongPressTimeout();
     private static final int TAP_TIMEOUT = ViewConfiguration.getTapTimeout();
-    // TODO make new double-tap timeout, and define its events (i.e. either time
-    // between down-down or time between up-down)
     private static final int DOUBLE_TAP_TIMEOUT = ViewConfiguration.getDoubleTapTimeout();
 
     // constants for Message.what used by GestureHandler below
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index a856b24..15e7eb2 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -62,7 +62,8 @@
     void addAppToken(int addPos, IApplicationToken token,
             int groupId, int requestedOrientation, boolean fullscreen);
     void setAppGroupId(IBinder token, int groupId);
-    Configuration updateOrientationFromAppTokens(IBinder freezeThisOneIfNeeded);
+    Configuration updateOrientationFromAppTokens(in Configuration currentConfig,
+            IBinder freezeThisOneIfNeeded);
     void setAppOrientation(IApplicationToken token, int requestedOrientation);
     int getAppOrientation(IApplicationToken token);
     void setFocusedApp(IBinder token, boolean moveFocusNow);
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index 430cc71..41779ba 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -235,6 +235,22 @@
     public static final int FLAG_KEEP_TOUCH_MODE = 0x4;
     
     /**
+     * This mask is set if an event was known to come from a trusted part
+     * of the system.  That is, the event is known to come from the user,
+     * and could not have been spoofed by a third party component.
+     */
+    public static final int FLAG_FROM_SYSTEM = 0x8;
+    
+    /**
+     * This mask is used for compatibility, to identify enter keys that are
+     * coming from an IME whose enter key has been auto-labelled "next" or
+     * "done".  This allows TextView to dispatch these as normal enter keys
+     * for old applications, but still do the appropriate action when
+     * receiving them.
+     */
+    public static final int FLAG_EDITOR_ACTION = 0x10;
+    
+    /**
      * Returns the maximum keycode.
      */
     public static int getMaxKeyCode() {
@@ -440,6 +456,22 @@
     }
 
     /**
+     * Make an exact copy of an existing key event.
+     */
+    public KeyEvent(KeyEvent origEvent) {
+        mDownTime = origEvent.mDownTime;
+        mEventTime = origEvent.mEventTime;
+        mAction = origEvent.mAction;
+        mKeyCode = origEvent.mKeyCode;
+        mRepeatCount = origEvent.mRepeatCount;
+        mMetaState = origEvent.mMetaState;
+        mDeviceId = origEvent.mDeviceId;
+        mScancode = origEvent.mScancode;
+        mFlags = origEvent.mFlags;
+        mCharacters = origEvent.mCharacters;
+    }
+
+    /**
      * Copy an existing key event, modifying its time and repeat count.
      * 
      * @param origEvent The existing event to be copied.
@@ -461,12 +493,26 @@
     }
 
     /**
+     * Create a new key event that is the same as the given one, but whose
+     * event time and repeat count are replaced with the given value.
+     * 
+     * @param event The existing event to be copied.  This is not modified.
+     * @param eventTime The new event time
+     * (in {@link android.os.SystemClock#uptimeMillis}) of the event.
+     * @param newRepeat The new repeat count of the event.
+     */
+    public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime,
+            int newRepeat) {
+        return new KeyEvent(event, eventTime, newRepeat);
+    }
+    
+    /**
      * Copy an existing key event, modifying its action.
      * 
      * @param origEvent The existing event to be copied.
      * @param action The new action code of the event.
      */
-    public KeyEvent(KeyEvent origEvent, int action) {
+    private KeyEvent(KeyEvent origEvent, int action) {
         mDownTime = origEvent.mDownTime;
         mEventTime = origEvent.mEventTime;
         mAction = action;
@@ -481,6 +527,30 @@
     }
 
     /**
+     * Create a new key event that is the same as the given one, but whose
+     * action is replaced with the given value.
+     * 
+     * @param event The existing event to be copied.  This is not modified.
+     * @param action The new action code of the event.
+     */
+    public static KeyEvent changeAction(KeyEvent event, int action) {
+        return new KeyEvent(event, action);
+    }
+    
+    /**
+     * Create a new key event that is the same as the given one, but whose
+     * flags are replaced with the given value.
+     * 
+     * @param event The existing event to be copied.  This is not modified.
+     * @param flags The new flags constant.
+     */
+    public static KeyEvent changeFlags(KeyEvent event, int flags) {
+        event = new KeyEvent(event);
+        event.mFlags = flags;
+        return event;
+    }
+    
+    /**
      * Don't use in new code, instead explicitly check
      * {@link #getAction()}.
      * 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index c3e00c4..04447ca 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -3409,6 +3409,9 @@
             if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
                 imm.focusOut(this);
             }
+            if (mPendingCheckForLongPress != null) {
+                removeCallbacks(mPendingCheckForLongPress);
+            }
         } else if (imm != null && (mPrivateFlags & FOCUSED) != 0) {
             imm.focusIn(this);
         }
@@ -7656,7 +7659,7 @@
         private int mOriginalWindowAttachCount;
 
         public void run() {
-            if (isPressed() && (mParent != null) && hasWindowFocus()
+            if (isPressed() && (mParent != null)
                     && mOriginalWindowAttachCount == mWindowAttachCount) {
                 if (performLongClick()) {
                     mHasPerformedLongPress = true;
diff --git a/core/java/android/view/ViewDebug.java b/core/java/android/view/ViewDebug.java
index 6ea7a82..f604bc5 100644
--- a/core/java/android/view/ViewDebug.java
+++ b/core/java/android/view/ViewDebug.java
@@ -19,6 +19,7 @@
 import android.util.Log;
 import android.util.DisplayMetrics;
 import android.content.res.Resources;
+import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.os.Environment;
@@ -800,7 +801,7 @@
             View view = root.getRootView();
             if (view instanceof ViewGroup) {
                 ViewGroup group = (ViewGroup) view;
-                dumpViewHierarchyWithProperties(group, out, 0);
+                dumpViewHierarchyWithProperties(group.getContext(), group, out, 0);
             }
             out.write("DONE.");
             out.newLine();
@@ -838,9 +839,9 @@
         return view.getClass().getName().equals(className) && view.hashCode() == hashCode;
     }
 
-    private static void dumpViewHierarchyWithProperties(ViewGroup group,
+    private static void dumpViewHierarchyWithProperties(Context context, ViewGroup group,
             BufferedWriter out, int level) {
-        if (!dumpViewWithProperties(group, out, level)) {
+        if (!dumpViewWithProperties(context, group, out, level)) {
             return;
         }
 
@@ -848,14 +849,16 @@
         for (int i = 0; i < count; i++) {
             final View view = group.getChildAt(i);
             if (view instanceof ViewGroup) {
-                dumpViewHierarchyWithProperties((ViewGroup) view, out, level + 1);
+                dumpViewHierarchyWithProperties(context, (ViewGroup) view, out, level + 1);
             } else {
-                dumpViewWithProperties(view, out, level + 1);
+                dumpViewWithProperties(context, view, out, level + 1);
             }
         }
     }
 
-    private static boolean dumpViewWithProperties(View view, BufferedWriter out, int level) {
+    private static boolean dumpViewWithProperties(Context context, View view,
+            BufferedWriter out, int level) {
+
         try {
             for (int i = 0; i < level; i++) {
                 out.write(' ');
@@ -864,7 +867,7 @@
             out.write('@');
             out.write(Integer.toHexString(view.hashCode()));
             out.write(' ');
-            dumpViewProperties(view, out);
+            dumpViewProperties(context, view, out);
             out.newLine();
         } catch (IOException e) {
             Log.w("View", "Error while dumping hierarchy tree");
@@ -945,23 +948,26 @@
         return methods;
     }
 
-    private static void dumpViewProperties(Object view, BufferedWriter out) throws IOException {
-        dumpViewProperties(view, out, "");
+    private static void dumpViewProperties(Context context, Object view,
+            BufferedWriter out) throws IOException {
+
+        dumpViewProperties(context, view, out, "");
     }
 
-    private static void dumpViewProperties(Object view, BufferedWriter out, String prefix)
-            throws IOException {
+    private static void dumpViewProperties(Context context, Object view,
+            BufferedWriter out, String prefix) throws IOException {
+
         Class<?> klass = view.getClass();
 
         do {
-            exportFields(view, out, klass, prefix);
-            exportMethods(view, out, klass, prefix);
+            exportFields(context, view, out, klass, prefix);
+            exportMethods(context, view, out, klass, prefix);
             klass = klass.getSuperclass();
         } while (klass != Object.class);
     }
     
-    private static void exportMethods(Object view, BufferedWriter out, Class<?> klass,
-            String prefix) throws IOException {
+    private static void exportMethods(Context context, Object view, BufferedWriter out,
+            Class<?> klass, String prefix) throws IOException {
 
         final Method[] methods = getExportedPropertyMethods(klass);
 
@@ -976,9 +982,9 @@
 
                 if (returnType == int.class) {
                     final ExportedProperty property = sAnnotations.get(method);
-                    if (property.resolveId() && view instanceof View) {
+                    if (property.resolveId() && context != null) {
                         final int id = (Integer) methodValue;
-                        methodValue = resolveId(view, id);
+                        methodValue = resolveId(context, id);
                     } else {
                         final IntToString[] mapping = property.mapping();
                         if (mapping.length > 0) {
@@ -1005,11 +1011,11 @@
                     final String valuePrefix = prefix + method.getName() + '_';
                     final String suffix = "()";
 
-                    exportUnrolledArray(view, out, property, array, valuePrefix, suffix);
+                    exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
                 } else if (!returnType.isPrimitive()) {
                     final ExportedProperty property = sAnnotations.get(method);
                     if (property.deepExport()) {
-                        dumpViewProperties(methodValue, out, prefix + property.prefix());
+                        dumpViewProperties(context, methodValue, out, prefix + property.prefix());
                         continue;
                     }
                 }
@@ -1021,8 +1027,9 @@
         }
     }
 
-    private static void exportFields(Object view, BufferedWriter out, Class<?> klass, String prefix)
-            throws IOException {
+    private static void exportFields(Context context, Object view, BufferedWriter out,
+            Class<?> klass, String prefix) throws IOException {
+
         final Field[] fields = getExportedPropertyFields(klass);
 
         int count = fields.length;
@@ -1036,9 +1043,9 @@
 
                 if (type == int.class) {
                     final ExportedProperty property = sAnnotations.get(field);
-                    if (property.resolveId() && view instanceof View) {
+                    if (property.resolveId() && context != null) {
                         final int id = field.getInt(view);
-                        fieldValue = resolveId(view, id);
+                        fieldValue = resolveId(context, id);
                     } else {
                         final IntToString[] mapping = property.mapping();
                         if (mapping.length > 0) {
@@ -1063,14 +1070,15 @@
                     final String valuePrefix = prefix + field.getName() + '_';
                     final String suffix = "";
 
-                    exportUnrolledArray(view, out, property, array, valuePrefix, suffix);
+                    exportUnrolledArray(context, out, property, array, valuePrefix, suffix);
 
                     // We exit here!
                     return;
                 } else if (!type.isPrimitive()) {
                     final ExportedProperty property = sAnnotations.get(field);
                     if (property.deepExport()) {
-                        dumpViewProperties(field.get(view), out, prefix + property.prefix());
+                        dumpViewProperties(context, field.get(view), out,
+                                prefix + property.prefix());
                         continue;
                     }
                 }
@@ -1096,7 +1104,7 @@
         out.write(' ');
     }
 
-    private static void exportUnrolledArray(Object view, BufferedWriter out,
+    private static void exportUnrolledArray(Context context, BufferedWriter out,
             ExportedProperty property, int[] array, String prefix, String suffix)
             throws IOException {
 
@@ -1106,7 +1114,7 @@
         final IntToString[] mapping = property.mapping();
         final boolean hasMapping = mapping.length > 0;
 
-        final boolean resolveId = property.resolveId() && view instanceof View;
+        final boolean resolveId = property.resolveId() && context != null;
         final int valuesCount = array.length;
 
         for (int j = 0; j < valuesCount; j++) {
@@ -1140,16 +1148,16 @@
             }
 
             if (resolveId) {
-                value = (String) resolveId(view, intValue);
+                value = (String) resolveId(context, intValue);
             }
 
             writeEntry(out, prefix, name, suffix, value);
         }
     }
 
-    private static Object resolveId(Object view, int id) {
+    private static Object resolveId(Context context, int id) {
         Object fieldValue;
-        final Resources resources = ((View) view).getContext().getResources();
+        final Resources resources = context.getResources();
         if (id >= 0) {
             try {
                 fieldValue = resources.getResourceTypeName(id) + '/' +
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index dd2b154..fbb4d42 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -470,11 +470,20 @@
 
     void setLayoutParams(WindowManager.LayoutParams attrs, boolean newView) {
         synchronized (this) {
+            int oldSoftInputMode = mWindowAttributes.softInputMode;
             mWindowAttributes.copyFrom(attrs);
             if (newView) {
                 mSoftInputMode = attrs.softInputMode;
                 requestLayout();
             }
+            // Don't lose the mode we last auto-computed.
+            if ((attrs.softInputMode&WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+                    == WindowManager.LayoutParams.SOFT_INPUT_ADJUST_UNSPECIFIED) {
+                mWindowAttributes.softInputMode = (mWindowAttributes.softInputMode
+                        & ~WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST)
+                        | (oldSoftInputMode
+                                & WindowManager.LayoutParams.SOFT_INPUT_MASK_ADJUST);
+            }
             mWindowAttributesChanged = true;
             scheduleTraversals();
         }
@@ -1485,7 +1494,7 @@
                 + msg.obj + " to " + mView);
             deliverKeyEvent((KeyEvent)msg.obj, true);
             break;
-        case DISPATCH_POINTER:
+        case DISPATCH_POINTER: {
             MotionEvent event = (MotionEvent)msg.obj;
 
             boolean didFinish;
@@ -1571,7 +1580,7 @@
                 // Let the exception fall through -- the looper will catch
                 // it and take care of the bad app for us.
             }
-            break;
+        } break;
         case DISPATCH_TRACKBALL:
             deliverTrackballEvent((MotionEvent)msg.obj);
             break;
@@ -1657,12 +1666,19 @@
         case DIE:
             dispatchDetachedFromWindow();
             break;
-        case DISPATCH_KEY_FROM_IME:
+        case DISPATCH_KEY_FROM_IME: {
             if (LOCAL_LOGV) Log.v(
                 "ViewRoot", "Dispatching key "
                 + msg.obj + " from IME to " + mView);
+            KeyEvent event = (KeyEvent)msg.obj;
+            if ((event.getFlags()&KeyEvent.FLAG_FROM_SYSTEM) != 0) {
+                // The IME is trying to say this event is from the
+                // system!  Bad bad bad!
+                event = KeyEvent.changeFlags(event,
+                        event.getFlags()&~KeyEvent.FLAG_FROM_SYSTEM);
+            }
             deliverKeyEventToViewHierarchy((KeyEvent)msg.obj, false);
-            break;
+        } break;
         case FINISH_INPUT_CONNECTION: {
             InputMethodManager imm = InputMethodManager.peekInstance();
             if (imm != null) {
diff --git a/core/java/android/view/ViewTreeObserver.java b/core/java/android/view/ViewTreeObserver.java
index 47b52e4..4230afa 100644
--- a/core/java/android/view/ViewTreeObserver.java
+++ b/core/java/android/view/ViewTreeObserver.java
@@ -18,7 +18,7 @@
 
 import android.graphics.Rect;
 
-import java.util.ArrayList;
+import java.util.concurrent.CopyOnWriteArrayList;
 
 /**
  * A view tree observer is used to register listeners that can be notified of global
@@ -30,12 +30,12 @@
  * for more information.
  */
 public final class ViewTreeObserver {
-    private ArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
-    private ArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
-    private ArrayList<OnPreDrawListener> mOnPreDrawListeners;
-    private ArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
-    private ArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
-    private ArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
+    private CopyOnWriteArrayList<OnGlobalFocusChangeListener> mOnGlobalFocusListeners;
+    private CopyOnWriteArrayList<OnGlobalLayoutListener> mOnGlobalLayoutListeners;
+    private CopyOnWriteArrayList<OnPreDrawListener> mOnPreDrawListeners;
+    private CopyOnWriteArrayList<OnTouchModeChangeListener> mOnTouchModeChangeListeners;
+    private CopyOnWriteArrayList<OnComputeInternalInsetsListener> mOnComputeInternalInsetsListeners;
+    private CopyOnWriteArrayList<OnScrollChangedListener> mOnScrollChangedListeners;
 
     private boolean mAlive = true;
 
@@ -283,7 +283,7 @@
         checkIsAlive();
 
         if (mOnGlobalFocusListeners == null) {
-            mOnGlobalFocusListeners = new ArrayList<OnGlobalFocusChangeListener>();
+            mOnGlobalFocusListeners = new CopyOnWriteArrayList<OnGlobalFocusChangeListener>();
         }
 
         mOnGlobalFocusListeners.add(listener);
@@ -318,7 +318,7 @@
         checkIsAlive();
 
         if (mOnGlobalLayoutListeners == null) {
-            mOnGlobalLayoutListeners = new ArrayList<OnGlobalLayoutListener>();
+            mOnGlobalLayoutListeners = new CopyOnWriteArrayList<OnGlobalLayoutListener>();
         }
 
         mOnGlobalLayoutListeners.add(listener);
@@ -352,7 +352,7 @@
         checkIsAlive();
 
         if (mOnPreDrawListeners == null) {
-            mOnPreDrawListeners = new ArrayList<OnPreDrawListener>();
+            mOnPreDrawListeners = new CopyOnWriteArrayList<OnPreDrawListener>();
         }
 
         mOnPreDrawListeners.add(listener);
@@ -388,7 +388,7 @@
         checkIsAlive();
 
         if (mOnScrollChangedListeners == null) {
-            mOnScrollChangedListeners = new ArrayList<OnScrollChangedListener>();
+            mOnScrollChangedListeners = new CopyOnWriteArrayList<OnScrollChangedListener>();
         }
 
         mOnScrollChangedListeners.add(listener);
@@ -424,7 +424,7 @@
         checkIsAlive();
 
         if (mOnTouchModeChangeListeners == null) {
-            mOnTouchModeChangeListeners = new ArrayList<OnTouchModeChangeListener>();
+            mOnTouchModeChangeListeners = new CopyOnWriteArrayList<OnTouchModeChangeListener>();
         }
 
         mOnTouchModeChangeListeners.add(listener);
@@ -460,7 +460,8 @@
         checkIsAlive();
 
         if (mOnComputeInternalInsetsListeners == null) {
-            mOnComputeInternalInsetsListeners = new ArrayList<OnComputeInternalInsetsListener>();
+            mOnComputeInternalInsetsListeners =
+                    new CopyOnWriteArrayList<OnComputeInternalInsetsListener>();
         }
 
         mOnComputeInternalInsetsListeners.add(listener);
@@ -518,11 +519,14 @@
      * Notifies registered listeners that focus has changed.
      */
     final void dispatchOnGlobalFocusChange(View oldFocus, View newFocus) {
-        final ArrayList<OnGlobalFocusChangeListener> globaFocusListeners = mOnGlobalFocusListeners;
-        if (globaFocusListeners != null) {
-            final int count = globaFocusListeners.size();
-            for (int i = count - 1; i >= 0; i--) {
-                globaFocusListeners.get(i).onGlobalFocusChanged(oldFocus, newFocus);
+        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
+        // perform the dispatching. The iterator is a safe guard against listeners that
+        // could mutate the list by calling the various add/remove methods. This prevents
+        // the array from being modified while we iterate it.
+        final CopyOnWriteArrayList<OnGlobalFocusChangeListener> listeners = mOnGlobalFocusListeners;
+        if (listeners != null) {
+            for (OnGlobalFocusChangeListener listener : listeners) {
+                listener.onGlobalFocusChanged(oldFocus, newFocus);
             }
         }
     }
@@ -533,11 +537,14 @@
      * not attached to a Window or in the GONE state.
      */
     public final void dispatchOnGlobalLayout() {
-        final ArrayList<OnGlobalLayoutListener> globaLayoutListeners = mOnGlobalLayoutListeners;
-        if (globaLayoutListeners != null) {
-            final int count = globaLayoutListeners.size();
-            for (int i = count - 1; i >= 0; i--) {
-                globaLayoutListeners.get(i).onGlobalLayout();
+        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
+        // perform the dispatching. The iterator is a safe guard against listeners that
+        // could mutate the list by calling the various add/remove methods. This prevents
+        // the array from being modified while we iterate it.
+        final CopyOnWriteArrayList<OnGlobalLayoutListener> listeners = mOnGlobalLayoutListeners;
+        if (listeners != null) {
+            for (OnGlobalLayoutListener listener : listeners) {
+                listener.onGlobalLayout();
             }
         }
     }
@@ -551,12 +558,15 @@
      * @return True if the current draw should be canceled and resceduled, false otherwise.
      */
     public final boolean dispatchOnPreDraw() {
+        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
+        // perform the dispatching. The iterator is a safe guard against listeners that
+        // could mutate the list by calling the various add/remove methods. This prevents
+        // the array from being modified while we iterate it.
         boolean cancelDraw = false;
-        final ArrayList<OnPreDrawListener> preDrawListeners = mOnPreDrawListeners;
-        if (preDrawListeners != null) {
-            final int count = preDrawListeners.size();
-            for (int i = count - 1; i >= 0; i--) {
-                cancelDraw |= !preDrawListeners.get(i).onPreDraw();
+        final CopyOnWriteArrayList<OnPreDrawListener> listeners = mOnPreDrawListeners;
+        if (listeners != null) {
+            for (OnPreDrawListener listener : listeners) {
+                cancelDraw |= !listener.onPreDraw();
             }
         }
         return cancelDraw;
@@ -568,11 +578,15 @@
      * @param inTouchMode True if the touch mode is now enabled, false otherwise.
      */
     final void dispatchOnTouchModeChanged(boolean inTouchMode) {
-        final ArrayList<OnTouchModeChangeListener> touchModeListeners = mOnTouchModeChangeListeners;
-        if (touchModeListeners != null) {
-            final int count = touchModeListeners.size();
-            for (int i = count - 1; i >= 0; i--) {
-                touchModeListeners.get(i).onTouchModeChanged(inTouchMode);
+        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
+        // perform the dispatching. The iterator is a safe guard against listeners that
+        // could mutate the list by calling the various add/remove methods. This prevents
+        // the array from being modified while we iterate it.
+        final CopyOnWriteArrayList<OnTouchModeChangeListener> listeners =
+                mOnTouchModeChangeListeners;
+        if (listeners != null) {
+            for (OnTouchModeChangeListener listener : listeners) {
+                listener.onTouchModeChanged(inTouchMode);
             }
         }
     }
@@ -581,11 +595,14 @@
      * Notifies registered listeners that something has scrolled.
      */
     final void dispatchOnScrollChanged() {
-        final ArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
-
+        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
+        // perform the dispatching. The iterator is a safe guard against listeners that
+        // could mutate the list by calling the various add/remove methods. This prevents
+        // the array from being modified while we iterate it.
+        final CopyOnWriteArrayList<OnScrollChangedListener> listeners = mOnScrollChangedListeners;
         if (listeners != null) {
-            for (OnScrollChangedListener scl : mOnScrollChangedListeners) {
-                scl.onScrollChanged();
+            for (OnScrollChangedListener listener : listeners) {
+                listener.onScrollChanged();
             }
         }
     }
@@ -594,7 +611,8 @@
      * Returns whether there are listeners for computing internal insets.
      */
     final boolean hasComputeInternalInsetsListeners() {
-        final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners;
+        final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+                mOnComputeInternalInsetsListeners;
         return (listeners != null && listeners.size() > 0);
     }
     
@@ -602,11 +620,15 @@
      * Calls all listeners to compute the current insets.
      */
     final void dispatchOnComputeInternalInsets(InternalInsetsInfo inoutInfo) {
-        final ArrayList<OnComputeInternalInsetsListener> listeners = mOnComputeInternalInsetsListeners;
+        // NOTE: because of the use of CopyOnWriteArrayList, we *must* use an iterator to
+        // perform the dispatching. The iterator is a safe guard against listeners that
+        // could mutate the list by calling the various add/remove methods. This prevents
+        // the array from being modified while we iterate it.
+        final CopyOnWriteArrayList<OnComputeInternalInsetsListener> listeners =
+                mOnComputeInternalInsetsListeners;
         if (listeners != null) {
-            final int count = listeners.size();
-            for (int i = count - 1; i >= 0; i--) {
-                listeners.get(i).onComputeInternalInsets(inoutInfo);
+            for (OnComputeInternalInsetsListener listener : listeners) {
+                listener.onComputeInternalInsets(inoutInfo);
             }
         }
     }
diff --git a/core/java/android/view/inputmethod/EditorInfo.java b/core/java/android/view/inputmethod/EditorInfo.java
index b00e565..c718bac 100644
--- a/core/java/android/view/inputmethod/EditorInfo.java
+++ b/core/java/android/view/inputmethod/EditorInfo.java
@@ -78,12 +78,37 @@
     public static final int IME_ACTION_DONE = 0x00000006;
     
     /**
+     * Flag of {@link #imeOptions}: used to specify that the IME does not need
+     * to show its extracted text UI.  For input methods that may be fullscreen,
+     * often when in landscape mode, this allows them to be smaller and let part
+     * of the application be shown behind.  Though there will likely be limited
+     * access to the application available from the user, it can make the
+     * experience of a (mostly) fullscreen IME less jarring.  Note that when
+     * this flag is specified the IME may <em>not</em> be set up to be able
+     * to display text, so it should only be used in situations where this is
+     * not needed.
+     */
+    public static final int IME_FLAG_NO_EXTRACT_UI = 0x10000000;
+    
+    /**
      * Flag of {@link #imeOptions}: used in conjunction with
      * {@link #IME_MASK_ACTION}, this indicates that the action should not
-     * be available in-line as the same as a "enter" key.  Typically this is
+     * be available as an accessory button when the input method is full-screen.
+     * Note that by setting this flag, there can be cases where the action
+     * is simply never available to the user.  Setting this generally means
+     * that you think showing text being edited is more important than the
+     * action you have supplied. 
+     */
+    public static final int IME_FLAG_NO_ACCESSORY_ACTION = 0x20000000;
+    
+    /**
+     * Flag of {@link #imeOptions}: used in conjunction with
+     * {@link #IME_MASK_ACTION}, this indicates that the action should not
+     * be available in-line as a replacement for "enter" key.  Typically this is
      * because the action has such a significant impact or is not recoverable
      * enough that accidentally hitting it should be avoided, such as sending
-     * a message.
+     * a message.  Note that {@link android.widget.TextView} will automatically set this
+     * flag for you on multi-line text views.
      */
     public static final int IME_FLAG_NO_ENTER_ACTION = 0x40000000;
     
diff --git a/core/java/android/webkit/CacheManager.java b/core/java/android/webkit/CacheManager.java
index dcf68cd..4528b73 100644
--- a/core/java/android/webkit/CacheManager.java
+++ b/core/java/android/webkit/CacheManager.java
@@ -282,9 +282,7 @@
         CacheResult result = mDataBase.getCache(url);
         if (result != null) {
             if (result.contentLength == 0) {
-                if (result.httpStatusCode != 301
-                        && result.httpStatusCode != 302
-                        && result.httpStatusCode != 307) {
+                if (!checkCacheRedirect(result.httpStatusCode)) {
                     // this should not happen. If it does, remove it.
                     mDataBase.removeCache(url);
                     return null;
@@ -350,6 +348,17 @@
             return null;
         }
 
+        // according to the rfc 2616, the 303 response MUST NOT be cached.
+        if (statusCode == 303) {
+            return null;
+        }
+
+        // like the other browsers, do not cache redirects containing a cookie
+        // header.
+        if (checkCacheRedirect(statusCode) && !headers.getSetCookie().isEmpty()) {
+            return null;
+        }
+
         CacheResult ret = parseHeaders(statusCode, headers, mimeType);
         if (ret != null) {
             setupFiles(url, ret);
@@ -395,9 +404,7 @@
         }
 
         cacheRet.contentLength = cacheRet.outFile.length();
-        if (cacheRet.httpStatusCode == 301
-                || cacheRet.httpStatusCode == 302
-                || cacheRet.httpStatusCode == 307) {
+        if (checkCacheRedirect(cacheRet.httpStatusCode)) {
             // location is in database, no need to keep the file
             cacheRet.contentLength = 0;
             cacheRet.localPath = new String();
@@ -471,6 +478,15 @@
         }
     }
 
+    private static boolean checkCacheRedirect(int statusCode) {
+        if (statusCode == 301 || statusCode == 302 || statusCode == 307) {
+            // as 303 can't be cached, we do not return true
+            return true;
+        } else {
+            return false;
+        }
+    }
+
     @SuppressWarnings("deprecation")
     private static void setupFiles(String url, CacheResult cacheRet) {
         if (true) {
diff --git a/core/java/android/webkit/HttpAuthHandler.java b/core/java/android/webkit/HttpAuthHandler.java
index 48b9eec..84dc9f0 100644
--- a/core/java/android/webkit/HttpAuthHandler.java
+++ b/core/java/android/webkit/HttpAuthHandler.java
@@ -80,8 +80,7 @@
                 break;
 
             case AUTH_CANCEL:
-
-                mNetwork.resetHandlersAndStopLoading(loader.getFrame());
+                loader.handleAuthResponse(null, null);
                 break;
         }
 
@@ -126,24 +125,6 @@
     }
 
     /**
-     * Resets the HTTP-authentication request handler, removes
-     * all loaders that share the same BrowserFrame
-     *
-     * @param frame The browser frame
-     */
-    /* package */ void reset(BrowserFrame frame) {
-        synchronized (mLoaderQueue) {
-            ListIterator<LoadListener> i = mLoaderQueue.listIterator(0);
-            while (i.hasNext()) {
-                LoadListener loader = i.next();
-                if (frame == loader.getFrame()) {
-                    i.remove();
-                }
-            }
-        }
-    }
-
-    /**
      * Enqueues the loader, if the loader is the only element
      * in the queue, starts processing the loader
      *
diff --git a/core/java/android/webkit/LoadListener.java b/core/java/android/webkit/LoadListener.java
index f9fb0b0..c64200c 100644
--- a/core/java/android/webkit/LoadListener.java
+++ b/core/java/android/webkit/LoadListener.java
@@ -377,10 +377,6 @@
             }
         }
 
-        // if there is buffered data, commit them in the end
-        boolean needToCommit = mAuthHeader != null && !mustAuthenticate
-                && mNativeLoader != 0 && !mDataBuilder.isEmpty();
-
         // it is only here that we can reset the last mAuthHeader object
         // (if existed) and start a new one!!!
         mAuthHeader = null;
@@ -415,10 +411,6 @@
             }
         }
         commitHeadersCheckRedirect();
-
-        if (needToCommit) {
-            commitLoad();
-        }
     }
 
     /**
@@ -452,6 +444,8 @@
         status.put("minor", minorVersion);
         status.put("code", code);
         status.put("reason", reasonPhrase);
+        // New status means new data. Clear the old.
+        mDataBuilder.clear();
         sendMessageInternal(obtainMessage(MSG_STATUS, status));
     }
 
@@ -613,7 +607,6 @@
                 // ask for it, so make sure we have a valid CacheLoader
                 // before calling it.
                 if (mCacheLoader != null) {
-                    detachRequestHandle();
                     mCacheLoader.load();
                     if (Config.LOGV) {
                         Log.v(LOGTAG, "LoadListener cache load url=" + url());
@@ -738,10 +731,16 @@
         if (mRequestHandle != null) {
             mRequestHandle.handleSslErrorResponse(proceed);
         }
+        if (!proceed) {
+            // Commit whatever data we have and tear down the loader.
+            commitLoad();
+            tearDown();
+        }
     }
 
     /**
-     * Uses user-supplied credentials to restar a request.
+     * Uses user-supplied credentials to restart a request. If the credentials
+     * are null, cancel the request.
      */
     void handleAuthResponse(String username, String password) {
         if (Config.LOGV) {
@@ -780,6 +779,10 @@
                     }
                 }
             }
+        } else {
+            // Commit whatever data we have and tear down the loader.
+            commitLoad();
+            tearDown();
         }
     }
 
@@ -944,13 +947,12 @@
      * @return native response pointer
      */
     private int createNativeResponse() {
-        // The reason we change HTTP_NOT_MODIFIED to HTTP_OK is because we know
-        // that WebCore never sends the if-modified-since header. Our
-        // CacheManager does it for us. If the server responds with a 304, then
-        // we treat it like it was a 200 code and proceed with loading the file
-        // from the cache.
-        int statusCode = mStatusCode == HTTP_NOT_MODIFIED
-                ? HTTP_OK : mStatusCode;
+        // If WebCore sends if-modified-since, mCacheLoader is null. If 
+        // CacheManager sends it, mCacheLoader is not null. In this case, if the
+        // server responds with a 304, then we treat it like it was a 200 code 
+        // and proceed with loading the file from the cache.
+        int statusCode = (mStatusCode == HTTP_NOT_MODIFIED &&
+                mCacheLoader != null) ? HTTP_OK : mStatusCode;
         // pass content-type content-length and content-encoding
         final int nativeResponse = nativeCreateResponse(
                 mUrl, statusCode, mStatusText,
@@ -1181,8 +1183,6 @@
                 // sync. Add 1 to account for the current redirect.
                 mCacheRedirectCount = mRequestHandle.getRedirectCount() + 1;
             }
-            // Clear the buffered data since the redirect is valid.
-            mDataBuilder.clear();
         } else {
             commitHeaders();
             commitLoad();
@@ -1197,9 +1197,10 @@
 
     /**
      * Parses the content-type header.
+     * The first part only allows '-' if it follows x or X.
      */
     private static final Pattern CONTENT_TYPE_PATTERN =
-            Pattern.compile("^([a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$");
+            Pattern.compile("^((?:[xX]-)?[a-zA-Z\\*]+/[\\w\\+\\*-]+[\\.[\\w\\+-]+]*)$");
 
     private void parseContentTypeHeader(String contentType) {
         if (Config.LOGV) {
diff --git a/core/java/android/webkit/MimeTypeMap.java b/core/java/android/webkit/MimeTypeMap.java
index c9cc208..85c2275 100644
--- a/core/java/android/webkit/MimeTypeMap.java
+++ b/core/java/android/webkit/MimeTypeMap.java
@@ -496,6 +496,7 @@
             sMimeTypeMap.loadEntry("video/x-msvideo", "avi", false);
             sMimeTypeMap.loadEntry("video/x-sgi-movie", "movie", false);
             sMimeTypeMap.loadEntry("x-conference/x-cooltalk", "ice", false);
+            sMimeTypeMap.loadEntry("x-epoc/x-sisx-app", "sisx", false);
         }
 
         return sMimeTypeMap;
diff --git a/core/java/android/webkit/Network.java b/core/java/android/webkit/Network.java
index 74622b3..6fa0775 100644
--- a/core/java/android/webkit/Network.java
+++ b/core/java/android/webkit/Network.java
@@ -261,24 +261,6 @@
     }
 
     /**
-     * If we need to stop loading done in a handler (here, browser frame), we
-     * send a message to the handler to stop loading, and remove all loaders
-     * that share the same CallbackProxy in question from all local
-     * handlers (such as ssl-error and http-authentication handler).
-     * @param proxy The CallbackProxy responsible for cancelling the current
-     *              load.
-     */
-    public void resetHandlersAndStopLoading(BrowserFrame frame) {
-        if (Config.LOGV) {
-            Log.v(LOGTAG, "Network.resetHandlersAndStopLoading()");
-        }
-
-        frame.stopLoading();
-        mSslErrorHandler.reset(frame);
-        mHttpAuthHandler.reset(frame);
-    }
-
-    /**
      * Saves the state of network handlers (user SSL and HTTP-authentication
      * preferences).
      * @param outState The out-state to save (write) to.
diff --git a/core/java/android/webkit/SslErrorHandler.java b/core/java/android/webkit/SslErrorHandler.java
index 115434a..2e2fa12 100644
--- a/core/java/android/webkit/SslErrorHandler.java
+++ b/core/java/android/webkit/SslErrorHandler.java
@@ -118,20 +118,6 @@
     }
 
     /**
-     * Resets the SSL error handler, removes all loaders that
-     * share the same BrowserFrame.
-     */
-    /* package */ synchronized void reset(BrowserFrame frame) {
-        ListIterator<LoadListener> i = mLoaderQueue.listIterator(0);
-        while (i.hasNext()) {
-            LoadListener loader = i.next();
-            if (frame == loader.getFrame()) {
-                i.remove();
-            }
-        }
-    }
-
-    /**
      * Handles SSL error(s) on the way up to the user.
      */
     /* package */ synchronized void handleSslErrorRequest(LoadListener loader) {
@@ -244,12 +230,8 @@
                     primary > mSslPrefTable.getInt(host)) {
                     mSslPrefTable.putInt(host, new Integer(primary));
                 }
-
-                loader.handleSslErrorResponse(proceed);
-            } else {
-                loader.handleSslErrorResponse(proceed);
-                mNetwork.resetHandlersAndStopLoading(loader.getFrame());
             }
+            loader.handleSslErrorResponse(proceed);
         }
     }
 }
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 65544d4..025e6bb 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -153,6 +153,7 @@
     private boolean         mNeedInitialFocus = true;
     private boolean         mNavDump = false;
     private boolean         mSupportZoom = true;
+    private boolean         mBuiltInZoomControls = false;
     private boolean         mAllowFileAccess = true;
 
     // Class to handle messages before WebCore is ready.
@@ -364,6 +365,20 @@
     }
 
     /**
+     * Sets whether the zoom mechanism built into WebView is used.
+     */
+    public void setBuiltInZoomControls(boolean enabled) {
+        mBuiltInZoomControls = enabled;
+    }
+    
+    /**
+     * Returns true if the zoom mechanism built into WebView is being used.
+     */
+    public boolean getBuiltInZoomControls() {
+        return mBuiltInZoomControls;
+    }
+    
+    /**
      * Enable or disable file access within WebView. File access is enabled by
      * default.
      */
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 753267f..3205820 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -56,17 +56,20 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewTreeObserver;
+import android.view.animation.AlphaAnimation;
 import android.view.inputmethod.InputMethodManager;
 import android.webkit.TextDialog.AutoCompleteAdapter;
 import android.webkit.WebViewCore.EventHub;
 import android.widget.AbsoluteLayout;
 import android.widget.AdapterView;
 import android.widget.ArrayAdapter;
+import android.widget.FrameLayout;
 import android.widget.ImageView;
 import android.widget.ListView;
 import android.widget.Scroller;
 import android.widget.Toast;
 import android.widget.ZoomButtonsController;
+import android.widget.ZoomControls;
 import android.widget.AdapterView.OnItemClickListener;
 
 import java.io.File;
@@ -85,6 +88,9 @@
  * It uses the WebKit rendering engine to display
  * web pages and includes methods to navigate forward and backward
  * through a history, zoom in and out, perform text searches and more.</p>
+ * <p>To enable the built-in zoom, set
+ * {@link #getSettings() WebSettings}.{@link WebSettings#setBuiltInZoomControls(boolean)}
+ * (introduced in API version 3).
  * <p>Note that, in order for your Activity to access the Internet and load web pages
  * in a WebView, you must add the <var>INTERNET</var> permissions to your 
  * Android Manifest file:</p>
@@ -106,6 +112,57 @@
     static final boolean DEBUG = false;
     static final boolean LOGV_ENABLED = DEBUG ? Config.LOGD : Config.LOGV;
 
+    private class ExtendedZoomControls extends FrameLayout {
+        public ExtendedZoomControls(Context context, AttributeSet attrs) {
+            super(context, attrs);
+            LayoutInflater inflater = (LayoutInflater)
+                    context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
+            inflater.inflate(com.android.internal.R.layout.zoom_magnify, this, true);
+            mZoomControls = (ZoomControls) findViewById(com.android.internal.R.id.zoomControls);
+            mZoomMagnify = (ImageView) findViewById(com.android.internal.R.id.zoomMagnify);
+        }
+        
+        public void show(boolean showZoom, boolean canZoomOut) {
+            mZoomControls.setVisibility(showZoom ? View.VISIBLE : View.GONE);
+            mZoomMagnify.setVisibility(canZoomOut ? View.VISIBLE : View.GONE);
+            fade(View.VISIBLE, 0.0f, 1.0f);
+        }
+        
+        public void hide() {
+            fade(View.GONE, 1.0f, 0.0f);
+        }
+        
+        private void fade(int visibility, float startAlpha, float endAlpha) {
+            AlphaAnimation anim = new AlphaAnimation(startAlpha, endAlpha);
+            anim.setDuration(500);
+            startAnimation(anim);
+            setVisibility(visibility);
+        }
+        
+        public void setIsZoomMagnifyEnabled(boolean isEnabled) {
+            mZoomMagnify.setEnabled(isEnabled);
+        }
+        
+        public boolean hasFocus() {
+            return mZoomControls.hasFocus() || mZoomMagnify.hasFocus();
+        }
+        
+        public void setOnZoomInClickListener(OnClickListener listener) {
+            mZoomControls.setOnZoomInClickListener(listener);
+        }
+            
+        public void setOnZoomOutClickListener(OnClickListener listener) {
+            mZoomControls.setOnZoomOutClickListener(listener);
+        }
+            
+        public void setOnZoomMagnifyClickListener(OnClickListener listener) {
+            mZoomMagnify.setOnClickListener(listener);
+        }
+
+        ZoomControls mZoomControls;
+        ImageView mZoomMagnify;
+    }
+    
     /**
      *  Transportation object for returning WebView across thread boundaries.
      */
@@ -232,6 +289,9 @@
     private static final int LONG_PRESS_TIMEOUT = 1000;
     // needed to avoid flinging after a pause of no movement
     private static final int MIN_FLING_TIME = 250;
+    // The time that the Zoom Controls are visible before fading away
+    private static final long ZOOM_CONTROLS_TIMEOUT = 
+            ViewConfiguration.getZoomControlsTimeout();
     // The amount of content to overlap between two screens when going through
     // pages with the space bar, in pixels.
     private static final int PAGE_SCROLL_OVERLAP = 24;
@@ -472,6 +532,10 @@
         }
     }
 
+    // The View containing the zoom controls
+    private ExtendedZoomControls mZoomControls;
+    private Runnable mZoomControlRunnable;
+
     private ZoomButtonsController mZoomButtonsController; 
     private ImageView mZoomOverviewButton;
     private ImageView mZoomFitPageButton;
@@ -484,11 +548,6 @@
     private ZoomButtonsController.OnZoomListener mZoomListener =
             new ZoomButtonsController.OnZoomListener() {
 
-        public void onCenter(int x, int y) {
-            // Don't translate when the control is invoked, hence we do nothing
-            // in this callback
-        }
-
         public void onVisibilityChanged(boolean visible) {
             if (visible) {
                 switchOutDrawHistory();
@@ -582,10 +641,26 @@
     }
 
     private void updateZoomButtonsEnabled() {
-        mZoomButtonsController.setZoomInEnabled(mActualScale < mMaxZoomScale);
-        mZoomButtonsController.setZoomOutEnabled(mActualScale > mMinZoomScale);
-        mZoomFitPageButton.setEnabled(mActualScale != 1);
-        mZoomOverviewButton.setEnabled(canZoomScrollOut());
+        boolean canZoomIn = mActualScale < mMaxZoomScale;
+        boolean canZoomOut = mActualScale > mMinZoomScale;
+        if (!canZoomIn && !canZoomOut) {
+            // Hide the zoom in and out buttons, as well as the fit to page
+            // button, if the page cannot zoom
+            mZoomButtonsController.getZoomControls().setVisibility(View.GONE);
+            mZoomFitPageButton.setVisibility(View.GONE);
+        } else {
+            // Bring back the hidden zoom controls.
+            mZoomButtonsController.getZoomControls()
+                    .setVisibility(View.VISIBLE);
+            mZoomFitPageButton.setVisibility(View.VISIBLE);
+            // Set each one individually, as a page may be able to zoom in
+            // or out.
+            mZoomButtonsController.setZoomInEnabled(canZoomIn);
+            mZoomButtonsController.setZoomOutEnabled(canZoomOut);
+            mZoomFitPageButton.setEnabled(mActualScale != 1);
+        }
+        mZoomOverviewButton.setVisibility(canZoomScrollOut() ? View.VISIBLE:
+                View.GONE);
     }
 
     private void init() {
@@ -1332,7 +1407,13 @@
             return;
         }
         clearTextEntry();
-        mZoomButtonsController.setVisible(true);
+        if (getSettings().getBuiltInZoomControls()) {
+            mZoomButtonsController.setVisible(true);
+        } else {
+            mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+            mPrivateHandler.postDelayed(mZoomControlRunnable,
+                    ZOOM_CONTROLS_TIMEOUT);
+        }
     }
 
     /**
@@ -2535,8 +2616,17 @@
     private void startZoomScrollOut() {
         setHorizontalScrollBarEnabled(false);
         setVerticalScrollBarEnabled(false);
-        if (mZoomButtonsController.isVisible()) {
-            mZoomButtonsController.setVisible(false);
+        if (getSettings().getBuiltInZoomControls()) {
+            if (mZoomButtonsController.isVisible()) {
+                mZoomButtonsController.setVisible(false);
+            }
+        } else {
+            if (mZoomControlRunnable != null) {
+                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+            }
+            if (mZoomControls != null) {
+                mZoomControls.hide();
+            }
         }
         int width = getViewWidth();
         int height = getViewHeight();
@@ -3206,7 +3296,6 @@
 
         // Clean up the zoom controller
         mZoomButtonsController.setVisible(false);
-        ZoomButtonsController.finishZoomTutorial(mContext, false);
     }
     
     // Implementation for OnHierarchyChangeListener
@@ -3255,7 +3344,7 @@
                 // false for the first parameter
             }
         } else {
-            if (!mZoomButtonsController.isVisible()) {
+            if (getSettings().getBuiltInZoomControls() && !mZoomButtonsController.isVisible()) {
                 /*
                  * The zoom controls come in their own window, so our window
                  * loses focus. Our policy is to not draw the focus ring if
@@ -3527,7 +3616,9 @@
                         mWebViewCore
                                 .sendMessage(EventHub.SET_SNAP_ANCHOR, 0, 0);
                     }
-                    if (getSettings().supportZoom()
+                    WebSettings settings = getSettings();
+                    if (settings.supportZoom()
+                            && settings.getBuiltInZoomControls()
                             && !mZoomButtonsController.isVisible()
                             && (canZoomScrollOut() || 
                                     mMinZoomScale < mMaxZoomScale)) {
@@ -3594,6 +3685,21 @@
                     mLastTouchTime = eventTime;
                     mUserScroll = true;
                 }
+
+                if (!getSettings().getBuiltInZoomControls()) {
+                    boolean showPlusMinus = mMinZoomScale < mMaxZoomScale;
+                    boolean showMagnify = canZoomScrollOut();
+                    if (mZoomControls != null && (showPlusMinus || showMagnify)) {
+                        if (mZoomControls.getVisibility() == View.VISIBLE) {
+                            mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+                        } else {
+                            mZoomControls.show(showPlusMinus, showMagnify);
+                        }
+                        mPrivateHandler.postDelayed(mZoomControlRunnable,
+                                ZOOM_CONTROLS_TIMEOUT);
+                    }
+                }
+
                 if (done) {
                     // return false to indicate that we can't pan out of the
                     // view space
@@ -4050,18 +4156,83 @@
         }
     }
 
-    // TODO: deprecate
     /**
      * Returns a view containing zoom controls i.e. +/- buttons. The caller is
      * in charge of installing this view to the view hierarchy. This view will
      * become visible when the user starts scrolling via touch and fade away if
      * the user does not interact with it.
      * <p/>
-     * From 1.5, WebView change to use ZoomButtonsController. This will return
-     * an invisible dummy view for backwards compatibility.
+     * API version 3 introduces a built-in zoom mechanism that is shown
+     * automatically by the MapView. This is the preferred approach for
+     * showing the zoom UI.
+     *
+     * @deprecated The built-in zoom mechanism is preferred, see
+     *             {@link WebSettings#setBuiltInZoomControls(boolean)}.
      */
+    @Deprecated
     public View getZoomControls() {
-        return mZoomButtonsController.getDummyZoomControls();
+        if (!getSettings().supportZoom()) {
+            Log.w(LOGTAG, "This WebView doesn't support zoom.");
+            return null;
+        }
+        if (mZoomControls == null) {
+            mZoomControls = createZoomControls();
+            
+            /*
+             * need to be set to VISIBLE first so that getMeasuredHeight() in
+             * {@link #onSizeChanged()} can return the measured value for proper
+             * layout.
+             */
+            mZoomControls.setVisibility(View.VISIBLE);
+            mZoomControlRunnable = new Runnable() {
+                public void run() {
+                    
+                    /* Don't dismiss the controls if the user has
+                     * focus on them. Wait and check again later.
+                     */
+                    if (!mZoomControls.hasFocus()) {
+                        mZoomControls.hide();
+                    } else {
+                        mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+                        mPrivateHandler.postDelayed(mZoomControlRunnable,
+                                ZOOM_CONTROLS_TIMEOUT);
+                    }
+                }
+            };
+        }
+        return mZoomControls;
+    }
+
+    private ExtendedZoomControls createZoomControls() {
+        ExtendedZoomControls zoomControls = new ExtendedZoomControls(mContext
+            , null);
+        zoomControls.setOnZoomInClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                // reset time out
+                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+                mPrivateHandler.postDelayed(mZoomControlRunnable,
+                        ZOOM_CONTROLS_TIMEOUT);
+                zoomIn();
+            }
+        });
+        zoomControls.setOnZoomOutClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                // reset time out
+                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+                mPrivateHandler.postDelayed(mZoomControlRunnable,
+                        ZOOM_CONTROLS_TIMEOUT);
+                zoomOut();
+            }
+        });
+        zoomControls.setOnZoomMagnifyClickListener(new OnClickListener() {
+            public void onClick(View v) {
+                mPrivateHandler.removeCallbacks(mZoomControlRunnable);
+                mPrivateHandler.postDelayed(mZoomControlRunnable,
+                        ZOOM_CONTROLS_TIMEOUT);
+                zoomScrollOut();
+            }
+        });
+        return zoomControls;
     }
 
     /**
@@ -4070,7 +4241,7 @@
      * 
      * @return The instance of {@link ZoomButtonsController} used by this class,
      *         or null if it is unavailable.
-     * @hide pending API council
+     * @hide
      */
     public ZoomButtonsController getZoomButtonsController() {
         return mZoomButtonsController;
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index bd4bba8..965d900 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -905,10 +905,7 @@
                 ((Filterable) getAdapter()).getFilter() == null) {
             return false;
         }
-        final Context context = mContext;
-        final InputMethodManager inputManager = (InputMethodManager)
-                context.getSystemService(Context.INPUT_METHOD_SERVICE);
-        return !inputManager.isFullscreenMode();
+        return true;
     }
 
     /**
@@ -2904,7 +2901,7 @@
 
             KeyEvent forwardEvent = event;
             if (forwardEvent.getRepeatCount() > 0) {
-                forwardEvent = new KeyEvent(event, event.getEventTime(), 0);
+                forwardEvent = KeyEvent.changeTimeRepeat(event, event.getEventTime(), 0);
             }
 
             int action = event.getAction();
@@ -2967,6 +2964,7 @@
             // want to figure out why this is.
             mTextFilter.setRawInputType(EditorInfo.TYPE_CLASS_TEXT
                     | EditorInfo.TYPE_TEXT_VARIATION_FILTER);
+            mTextFilter.setImeOptions(EditorInfo.IME_FLAG_NO_EXTRACT_UI);
             mTextFilter.addTextChangedListener(this);
             p.setFocusable(false);
             p.setTouchable(false);
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index 1d553f1..04cb8a0 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -164,7 +164,7 @@
     void onProgressRefresh(float scale, boolean fromUser) { 
         Drawable thumb = mThumb;
         if (thumb != null) {
-            setThumbPos(getWidth(), getHeight(), thumb, scale, Integer.MIN_VALUE);
+            setThumbPos(getWidth(), thumb, scale, Integer.MIN_VALUE);
             /*
              * Since we draw translated, the drawable's bounds that it signals
              * for invalidation won't be the actual bounds we want invalidated,
@@ -189,7 +189,7 @@
         
         if (thumbHeight > trackHeight) {
             if (thumb != null) {
-                setThumbPos(w, h, thumb, scale, 0);
+                setThumbPos(w, thumb, scale, 0);
             }
             int gapForCenteringTrack = (thumbHeight - trackHeight) / 2;
             if (d != null) {
@@ -206,16 +206,15 @@
             }
             int gap = (trackHeight - thumbHeight) / 2;
             if (thumb != null) {
-                setThumbPos(w, h, thumb, scale, gap);
+                setThumbPos(w, thumb, scale, gap);
             }
         }
     }
 
     /**
      * @param gap If set to {@link Integer#MIN_VALUE}, this will be ignored and
-     *            the old vertical bounds will be used.
      */
-    private void setThumbPos(int w, int h, Drawable thumb, float scale, int gap) {
+    private void setThumbPos(int w, Drawable thumb, float scale, int gap) {
         int available = w - mPaddingLeft - mPaddingRight;
         int thumbWidth = thumb.getIntrinsicWidth();
         int thumbHeight = thumb.getIntrinsicHeight();
@@ -353,6 +352,12 @@
     void onStopTrackingTouch() {
     }
 
+    /**
+     * Called when the user changes the seekbar's progress by using a key event.
+     */
+    void onKeyChange() {
+    }
+
     @Override
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         int progress = getProgress();
@@ -361,11 +366,13 @@
             case KeyEvent.KEYCODE_DPAD_LEFT:
                 if (progress <= 0) break;
                 setProgress(progress - mKeyProgressIncrement, true);
+                onKeyChange();
                 return true;
         
             case KeyEvent.KEYCODE_DPAD_RIGHT:
                 if (progress >= getMax()) break;
                 setProgress(progress + mKeyProgressIncrement, true);
+                onKeyChange();
                 return true;
         }
 
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index 8aafee2..2bb716c 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -56,6 +56,7 @@
     private final Rect mSelfBounds = new Rect();
     private final Rect mOverlayBounds = new Rect();
     private int mForegroundGravity = Gravity.FILL;
+    private boolean mForegroundInPadding = true;
 
     public FrameLayout(Context context) {
         super(context);
@@ -71,6 +72,9 @@
         TypedArray a = context.obtainStyledAttributes(attrs, com.android.internal.R.styleable.FrameLayout,
                     defStyle, 0);
 
+        mForegroundGravity = a.getInt(
+                com.android.internal.R.styleable.FrameLayout_foregroundGravity, mForegroundGravity);
+
         final Drawable d = a.getDrawable(com.android.internal.R.styleable.FrameLayout_foreground);
         if (d != null) {
             setForeground(d);
@@ -80,8 +84,8 @@
             setMeasureAllChildren(true);
         }
 
-        mForegroundGravity = a.getInt(com.android.internal.R.styleable.FrameLayout_foregroundGravity,
-                mForegroundGravity);
+        mForegroundInPadding = a.getBoolean(
+                com.android.internal.R.styleable.FrameLayout_foregroundInsidePadding, true);
 
         a.recycle();
     }
@@ -105,6 +109,23 @@
             }
 
             mForegroundGravity = foregroundGravity;
+
+
+            if (mForegroundGravity == Gravity.FILL && mForeground != null) {
+                Rect padding = new Rect();
+                if (mForeground.getPadding(padding)) {
+                    mForegroundPaddingLeft = padding.left;
+                    mForegroundPaddingTop = padding.top;
+                    mForegroundPaddingRight = padding.right;
+                    mForegroundPaddingBottom = padding.bottom;
+                }
+            } else {
+                mForegroundPaddingLeft = 0;
+                mForegroundPaddingTop = 0;
+                mForegroundPaddingRight = 0;
+                mForegroundPaddingBottom = 0;
+            }
+
             requestLayout();
         }
     }
@@ -167,12 +188,14 @@
                 if (drawable.isStateful()) {
                     drawable.setState(getDrawableState());
                 }
-                Rect padding = new Rect();
-                if (drawable.getPadding(padding)) {
-                    mForegroundPaddingLeft = padding.left;
-                    mForegroundPaddingTop = padding.top;
-                    mForegroundPaddingRight = padding.right;
-                    mForegroundPaddingBottom = padding.bottom;
+                if (mForegroundGravity == Gravity.FILL) {
+                    Rect padding = new Rect();
+                    if (drawable.getPadding(padding)) {
+                        mForegroundPaddingLeft = padding.left;
+                        mForegroundPaddingTop = padding.top;
+                        mForegroundPaddingRight = padding.right;
+                        mForegroundPaddingBottom = padding.bottom;
+                    }
                 }
             }  else {
                 setWillNotDraw(true);
@@ -309,10 +332,14 @@
             final Rect selfBounds = mSelfBounds;
             final Rect overlayBounds = mOverlayBounds;
 
-            selfBounds.set(0, 0, w, h);
+            if (mForegroundInPadding) {
+                selfBounds.set(0, 0, w, h);
+            } else {
+                selfBounds.set(mPaddingLeft, mPaddingTop, w - mPaddingRight, h - mPaddingBottom);
+            }
+
             Gravity.apply(mForegroundGravity, foreground.getIntrinsicWidth(),
                     foreground.getIntrinsicHeight(), selfBounds, overlayBounds);
-
             foreground.setBounds(overlayBounds);
         }
     }
diff --git a/core/java/android/widget/MediaController.java b/core/java/android/widget/MediaController.java
index 227fb95..a2ec83f 100644
--- a/core/java/android/widget/MediaController.java
+++ b/core/java/android/widget/MediaController.java
@@ -405,6 +405,8 @@
             return super.dispatchKeyEvent(event);
         } else if (keyCode == KeyEvent.KEYCODE_BACK || keyCode == KeyEvent.KEYCODE_MENU) {
             hide();
+
+            return true;
         } else {
             show(sDefaultTimeout);
         }
diff --git a/core/java/android/widget/PopupWindow.java b/core/java/android/widget/PopupWindow.java
index a4f729f..f864690 100644
--- a/core/java/android/widget/PopupWindow.java
+++ b/core/java/android/widget/PopupWindow.java
@@ -1125,17 +1125,16 @@
     }
 
     /**
-     * <p>Updates the position and the dimension of the popup window. Width and
-     * height can be set to -1 to update location only.  Calling this function
-     * also updates the window with the current popup state as
-     * described for {@link #update()}.</p>
+     * <p>Updates the position and the dimension of the popup window. Calling this
+     * function also updates the window with the current popup state as described
+     * for {@link #update()}.</p>
      *
      * @param anchor the popup's anchor view
      * @param width the new width, can be -1 to ignore
      * @param height the new height, can be -1 to ignore
      */
     public void update(View anchor, int width, int height) {
-        update(anchor, 0, 0, width, height);
+        update(anchor, false, 0, 0, true, width, height);
     }
 
     /**
@@ -1153,31 +1152,44 @@
      * @param height the new height, can be -1 to ignore
      */
     public void update(View anchor, int xoff, int yoff, int width, int height) {
+        update(anchor, true, xoff, yoff, true, width, height);
+    }
+
+    private void update(View anchor, boolean updateLocation, int xoff, int yoff,
+            boolean updateDimension, int width, int height) {
+
         if (!isShowing() || mContentView == null) {
             return;
         }
 
         WeakReference<View> oldAnchor = mAnchor;
         if (oldAnchor == null || oldAnchor.get() != anchor ||
-            mAnchorXoff != xoff || mAnchorYoff != yoff) {
+                (updateLocation && (mAnchorXoff != xoff || mAnchorYoff != yoff))) {
             registerForScrollChanged(anchor, xoff, yoff);
         }
 
         WindowManager.LayoutParams p = (WindowManager.LayoutParams)
                 mPopupView.getLayoutParams();
 
-        if (width == -1) {
-            width = mPopupWidth;
-        } else {
-            mPopupWidth = width;
+        if (updateDimension) {
+            if (width == -1) {
+                width = mPopupWidth;
+            } else {
+                mPopupWidth = width;
+            }
+            if (height == -1) {
+                height = mPopupHeight;
+            } else {
+                mPopupHeight = height;
+            }
         }
-        if (height == -1) {
-            height = mPopupHeight;
+
+        if (updateLocation) {
+            mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff);
         } else {
-            mPopupHeight = height;
+            mAboveAnchor = findDropDownPosition(anchor, p, mAnchorXoff, mAnchorYoff);            
         }
-        
-        mAboveAnchor = findDropDownPosition(anchor, p, xoff, yoff);
+
         update(p.x, p.y, width, height);
     }
 
diff --git a/core/java/android/widget/RatingBar.java b/core/java/android/widget/RatingBar.java
index ad5ca07..1800c5a 100644
--- a/core/java/android/widget/RatingBar.java
+++ b/core/java/android/widget/RatingBar.java
@@ -296,7 +296,13 @@
             dispatchRatingChange(true);
         }
     }
-    
+
+    @Override
+    void onKeyChange() {
+        super.onKeyChange();
+        dispatchRatingChange(true);
+    }
+
     void dispatchRatingChange(boolean fromUser) {
         if (mOnRatingBarChangeListener != null) {
             mOnRatingBarChangeListener.onRatingChanged(this, getRating(),
diff --git a/core/java/android/widget/RelativeLayout.java b/core/java/android/widget/RelativeLayout.java
index 52c421c..c4f0abd 100644
--- a/core/java/android/widget/RelativeLayout.java
+++ b/core/java/android/widget/RelativeLayout.java
@@ -821,7 +821,10 @@
             @ViewDebug.IntToString(from = CENTER_VERTICAL,     to = "centerVertical"),
             @ViewDebug.IntToString(from = LEFT_OF,             to = "leftOf"),
             @ViewDebug.IntToString(from = RIGHT_OF,            to = "rightOf")
-        }, mapping = { @ViewDebug.IntToString(from = TRUE, to = "true") })
+        }, mapping = {
+            @ViewDebug.IntToString(from = TRUE, to = "true"),
+            @ViewDebug.IntToString(from = 0,    to = "NO_ID")
+        })
         private int[] mRules = new int[VERB_COUNT];
 
         private int mLeft, mTop, mRight, mBottom;
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 7b62b50..136752b 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -224,7 +224,7 @@
 
     private CharSequence mError;
     private boolean mErrorWasChanged;
-    private PopupWindow mPopup;
+    private ErrorPopup mPopup;
     /**
      * This flag is set if the TextView tries to display an error before it
      * is attached to the window (so its position is still unknown).
@@ -3039,12 +3039,11 @@
                     return;
                 }
             }
-        }
-        if (ict != null || !shouldAdvanceFocusOnEnter()) {
+            
             // This is the handling for some default action.
             // Note that for backwards compatibility we don't do this
             // default handling if explicit ime options have not been given,
-            // to instead turn this into the normal enter key codes that an
+            // instead turning this into the normal enter key codes that an
             // app may be expecting.
             if (actionCode == EditorInfo.IME_ACTION_NEXT) {
                 View v = focusSearch(FOCUS_DOWN);
@@ -3066,15 +3065,19 @@
         }
         
         Handler h = getHandler();
-        long eventTime = SystemClock.uptimeMillis();
-        h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
-                new KeyEvent(eventTime, eventTime,
-                KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0,
-                KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
-        h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
-                new KeyEvent(SystemClock.uptimeMillis(), eventTime,
-                KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0,
-                KeyEvent.FLAG_SOFT_KEYBOARD|KeyEvent.FLAG_KEEP_TOUCH_MODE)));
+        if (h != null) {
+            long eventTime = SystemClock.uptimeMillis();
+            h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
+                    new KeyEvent(eventTime, eventTime,
+                    KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0,
+                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
+                    | KeyEvent.FLAG_EDITOR_ACTION)));
+            h.sendMessage(h.obtainMessage(ViewRoot.DISPATCH_KEY_FROM_IME,
+                    new KeyEvent(SystemClock.uptimeMillis(), eventTime,
+                    KeyEvent.ACTION_UP, KeyEvent.KEYCODE_ENTER, 0, 0, 0, 0,
+                    KeyEvent.FLAG_SOFT_KEYBOARD | KeyEvent.FLAG_KEEP_TOUCH_MODE
+                    | KeyEvent.FLAG_EDITOR_ACTION)));
+        }
     }
     
     /**
@@ -3222,25 +3225,7 @@
             final TextView err = (TextView) inflater.inflate(com.android.internal.R.layout.textview_hint,
                     null);
 
-            mPopup = new PopupWindow(err, 200, 50) {
-                private boolean mAbove = false;
-
-                @Override
-                public void update(int x, int y, int w, int h, boolean force) {
-                    super.update(x, y, w, h, force);
-
-                    boolean above = isAboveAnchor();
-                    if (above != mAbove) {
-                        mAbove = above;
-
-                        if (above) {
-                            err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above);
-                        } else {
-                            err.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error);
-                        }
-                    }
-                }
-            };
+            mPopup = new ErrorPopup(err, 200, 50);
             mPopup.setFocusable(false);
             // The user is entering text, so the input method is needed.  We
             // don't want the popup to be displayed on top of it.
@@ -3252,6 +3237,37 @@
         tv.setText(mError);
 
         mPopup.showAsDropDown(this, getErrorX(), getErrorY());
+        mPopup.fixDirection(mPopup.isAboveAnchor());
+    }
+
+    private static class ErrorPopup extends PopupWindow {
+        private boolean mAbove = false;
+        private TextView mView;
+
+        ErrorPopup(TextView v, int width, int height) {
+            super(v, width, height);
+            mView = v;
+        }
+
+        void fixDirection(boolean above) {
+            mAbove = above;
+
+            if (above) {
+                mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error_above);
+            } else {
+                mView.setBackgroundResource(com.android.internal.R.drawable.popup_inline_error);
+            }
+        }
+
+        @Override
+        public void update(int x, int y, int w, int h, boolean force) {
+            super.update(x, y, w, h, force);
+
+            boolean above = isAboveAnchor();
+            if (above != mAbove) {
+                fixDirection(above);
+            }
+        }
     }
 
     /**
@@ -4001,7 +4017,7 @@
 
     @Override
     public boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) {
-        KeyEvent down = new KeyEvent(event, KeyEvent.ACTION_DOWN);
+        KeyEvent down = KeyEvent.changeAction(event, KeyEvent.ACTION_DOWN);
 
         int which = doKeyDown(keyCode, down, event);
         if (which == 0) {
@@ -4020,7 +4036,7 @@
         // of down and up events until we have done the complete repeatCount.
         // It would be nice if those interfaces had an onKeyMultiple() method,
         // but adding that is a more complicated change.
-        KeyEvent up = new KeyEvent(event, KeyEvent.ACTION_UP);
+        KeyEvent up = KeyEvent.changeAction(event, KeyEvent.ACTION_UP);
         if (which == 1) {
             mInput.onKeyUp(this, (Editable)mText, keyCode, up);
             while (--repeatCount > 0) {
@@ -4069,19 +4085,6 @@
         return false;
     }
 
-    private boolean isInterestingEnter(KeyEvent event) {
-        if ((event.getFlags() & KeyEvent.FLAG_SOFT_KEYBOARD) != 0 &&
-                mInputContentType != null &&
-                (mInputContentType.imeOptions &
-                        EditorInfo.IME_FLAG_NO_ENTER_ACTION) != 0) {
-            // If this enter key came from a soft keyboard, and the
-            // text editor has been configured to not do a default
-            // action for software enter keys, then we aren't interested.
-            return false;
-        }
-        return true;
-    }
-    
     private int doKeyDown(int keyCode, KeyEvent event, KeyEvent otherEvent) {
         if (!isEnabled()) {
             return 0;
@@ -4089,18 +4092,37 @@
 
         switch (keyCode) {
             case KeyEvent.KEYCODE_ENTER:
-                if (!isInterestingEnter(event)) {
-                    // Ignore enter key we aren't interested in.
-                    return -1;
+                // If ALT modifier is held, then we always insert a
+                // newline character.
+                if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0) {
+                    
+                    // When mInputContentType is set, we know that we are
+                    // running in a "modern" cupcake environment, so don't need
+                    // to worry about the application trying to capture
+                    // enter key events.
+                    if (mInputContentType != null) {
+                        
+                        // If there is an action listener, given them a
+                        // chance to consume the event.
+                        if (mInputContentType.onEditorActionListener != null &&
+                                mInputContentType.onEditorActionListener.onEditorAction(
+                                this, EditorInfo.IME_NULL, event)) {
+                            mInputContentType.enterDown = true;
+                            // We are consuming the enter key for them.
+                            return -1;
+                        }
+                    }
+                    
+                    // If our editor should move focus when enter is pressed, or
+                    // this is a generated event from an IME action button, then
+                    // don't let it be inserted into the text.
+                    if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0
+                            || shouldAdvanceFocusOnEnter()) {
+                        return -1;
+                    }
                 }
-                if ((event.getMetaState()&KeyEvent.META_ALT_ON) == 0
-                        && mInputContentType != null
-                        && mInputContentType.onEditorActionListener != null) {
-                    mInputContentType.enterDown = true;
-                    // We are consuming the enter key for them.
-                    return -1;
-                }
-                // fall through...
+                break;
+                
             case KeyEvent.KEYCODE_DPAD_CENTER:
                 if (shouldAdvanceFocusOnEnter()) {
                     return 0;
@@ -4215,7 +4237,8 @@
                     }
                 }
                 
-                if (shouldAdvanceFocusOnEnter()) {
+                if ((event.getFlags()&KeyEvent.FLAG_EDITOR_ACTION) != 0
+                        || shouldAdvanceFocusOnEnter()) {
                     /*
                      * If there is a click listener, just call through to
                      * super, which will invoke it.
@@ -4243,7 +4266,7 @@
                             super.onKeyUp(keyCode, event);
                             return true;
                         } else if ((event.getFlags()
-                                & KeyEvent.FLAG_SOFT_KEYBOARD) != 0) {
+                                & KeyEvent.FLAG_EDITOR_ACTION) != 0) {
                             // No target for next focus, but make sure the IME
                             // if this came from it.
                             InputMethodManager imm = InputMethodManager.peekInstance();
@@ -4302,6 +4325,13 @@
                     outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
                 }
             }
+            if ((outAttrs.inputType & (InputType.TYPE_MASK_CLASS
+                    | InputType.TYPE_TEXT_FLAG_MULTI_LINE))
+                    == (InputType.TYPE_CLASS_TEXT
+                            | InputType.TYPE_TEXT_FLAG_MULTI_LINE)) {
+                // Multi-line text editors should always show an enter key.
+                outAttrs.imeOptions |= EditorInfo.IME_FLAG_NO_ENTER_ACTION;
+            }
             outAttrs.hintText = mHint;
             if (mText instanceof Editable) {
                 InputConnection ic = new EditableInputConnection(this);
diff --git a/core/java/android/widget/ZoomButton.java b/core/java/android/widget/ZoomButton.java
index 0df919d..c5fa18c 100644
--- a/core/java/android/widget/ZoomButton.java
+++ b/core/java/android/widget/ZoomButton.java
@@ -19,15 +19,11 @@
 import android.content.Context;
 import android.os.Handler;
 import android.util.AttributeSet;
-import android.view.GestureDetector;
-import android.view.HapticFeedbackConstants;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.View;
-import android.view.GestureDetector.SimpleOnGestureListener;
 import android.view.View.OnLongClickListener;
 
-
 public class ZoomButton extends ImageButton implements OnLongClickListener {
 
     private final Handler mHandler;
@@ -39,7 +35,6 @@
             }
         }
     };
-    private final GestureDetector mGestureDetector;
     
     private long mZoomSpeed = 1000;
     private boolean mIsInLongpress;
@@ -55,19 +50,11 @@
     public ZoomButton(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
         mHandler = new Handler();
-        mGestureDetector = new GestureDetector(context, new SimpleOnGestureListener() {
-            @Override
-            public void onLongPress(MotionEvent e) {
-                performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
-                onLongClick(ZoomButton.this);
-            }
-        });
         setOnLongClickListener(this);
     }
 
     @Override
     public boolean onTouchEvent(MotionEvent event) {
-        mGestureDetector.onTouchEvent(event);
         if ((event.getAction() == MotionEvent.ACTION_CANCEL)
                 || (event.getAction() == MotionEvent.ACTION_UP)) {
             mIsInLongpress = false;
diff --git a/core/java/android/widget/ZoomButtonsController.java b/core/java/android/widget/ZoomButtonsController.java
index 4daa419..d9fb78b 100644
--- a/core/java/android/widget/ZoomButtonsController.java
+++ b/core/java/android/widget/ZoomButtonsController.java
@@ -16,23 +16,15 @@
 
 package android.widget;
 
-import android.app.AlertDialog;
-import android.app.Dialog;
 import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.graphics.Canvas;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.os.Handler;
 import android.os.Message;
-import android.os.SystemClock;
-import android.provider.Settings;
 import android.util.Log;
-import android.view.GestureDetector;
 import android.view.Gravity;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -42,7 +34,6 @@
 import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewRoot;
-import android.view.Window;
 import android.view.WindowManager;
 import android.view.View.OnClickListener;
 import android.view.WindowManager.LayoutParams;
@@ -51,29 +42,33 @@
  * Implementation notes:
  * - The zoom controls are displayed in their own window.
  *   (Easier for the client and better performance)
- * - This window is not touchable, and by default is not focusable.
- * - To make the buttons clickable, it attaches a OnTouchListener to the owner
- *   view and does the hit detection locally.
+ * - This window is never touchable, and by default is not focusable.
+ *   Its rect is quite big (fills horizontally) but has empty space between the
+ *   edges and center.  Touches there should be given to the owner.  Instead of
+ *   having the window touchable and dispatching these empty touch events to the
+ *   owner, we set the window to not touchable and steal events from owner
+ *   via onTouchListener.
+ * - To make the buttons clickable, it attaches an OnTouchListener to the owner
+ *   view and does the hit detection locally (attaches when visible, detaches when invisible).
  * - When it is focusable, it forwards uninteresting events to the owner view's
  *   view hierarchy.
  */
 /**
  * The {@link ZoomButtonsController} handles showing and hiding the zoom
- * controls relative to an owner view. It also gives the client access to the
- * zoom controls container, allowing for additional accessory buttons to be
- * shown in the zoom controls window.
+ * controls and positioning it relative to an owner view. It also gives the
+ * client access to the zoom controls container, allowing for additional
+ * accessory buttons to be shown in the zoom controls window.
  * <p>
- * Typical usage involves the client using the {@link GestureDetector} to
- * forward events from
- * {@link GestureDetector.OnDoubleTapListener#onDoubleTapEvent(MotionEvent)} to
- * {@link #handleDoubleTapEvent(MotionEvent)}. Also, whenever the owner cannot
- * be zoomed further, the client should update
+ * Typically, clients should call {@link #setVisible(boolean) setVisible(true)}
+ * on a touch down or move (no need to call {@link #setVisible(boolean)
+ * setVisible(false)} since it will time out on its own). Also, whenever the
+ * owner cannot be zoomed further, the client should update
  * {@link #setZoomInEnabled(boolean)} and {@link #setZoomOutEnabled(boolean)}.
  * <p>
  * If you are using this with a custom View, please call
  * {@link #setVisible(boolean) setVisible(false)} from the
  * {@link View#onDetachedFromWindow}.
- * 
+ *
  * @hide
  */
 public class ZoomButtonsController implements View.OnTouchListener {
@@ -88,6 +83,7 @@
 
     private Context mContext;
     private WindowManager mWindowManager;
+    private boolean mAutoDismissControls = true;
 
     /**
      * The view that is being zoomed by this zoom controller.
@@ -118,35 +114,26 @@
      * The {@link #mTouchTargetView}'s location in window, set on touch down.
      */
     private int[] mTouchTargetWindowLocation = new int[2];
+
     /**
      * If the zoom controller is dismissed but the user is still in a touch
      * interaction, we set this to true. This will ignore all touch events until
      * up/cancel, and then set the owner's touch listener to null.
+     * <p>
+     * Otherwise, the owner view would get mismatched events (i.e., touch move
+     * even though it never got the touch down.)
      */
     private boolean mReleaseTouchListenerOnUp;
 
-    /**
-     * Whether we are currently in the double-tap gesture, with the second tap
-     * still being performed (i.e., we're waiting for the second tap's touch up).
-     */
-    private boolean mIsSecondTapDown;
-
     /** Whether the container has been added to the window manager. */
     private boolean mIsVisible;
 
     private Rect mTempRect = new Rect();
     private int[] mTempIntArray = new int[2];
-    
+
     private OnZoomListener mCallback;
 
     /**
-     * In 1.0, the ZoomControls were to be added to the UI by the client of
-     * WebView, MapView, etc. We didn't want apps to break, so we return a dummy
-     * view in place now.
-     */
-    private InvisibleView mDummyZoomControls;
-    
-    /**
      * When showing the zoom, we add the view as a new window. However, there is
      * logic that needs to know the size of the zoom which is determined after
      * it's laid out. Therefore, we must post this logic onto the UI thread so
@@ -170,12 +157,6 @@
         }
     };
 
-    /**
-     * The setting name that tracks whether we've shown the zoom tutorial.
-     */
-    private static final String SETTING_NAME_SHOWN_TUTORIAL = "shown_zoom_tutorial";
-    private static Dialog sTutorialDialog;
-
     /** When configuration changes, this is called after the UI thread is idle. */
     private static final int MSG_POST_CONFIGURATION_CHANGED = 2;
     /** Used to delay the zoom controller dismissal. */
@@ -215,7 +196,7 @@
 
     /**
      * Constructor for the {@link ZoomButtonsController}.
-     * 
+     *
      * @param ownerView The view that is being zoomed by the zoom controls. The
      *            zoom controls will be displayed aligned with this view.
      */
@@ -227,13 +208,13 @@
         mTouchPaddingScaledSq = (int)
                 (ZOOM_CONTROLS_TOUCH_PADDING * mContext.getResources().getDisplayMetrics().density);
         mTouchPaddingScaledSq *= mTouchPaddingScaledSq;
-        
+
         mContainer = createContainer();
     }
 
     /**
      * Whether to enable the zoom in control.
-     * 
+     *
      * @param enabled Whether to enable the zoom in control.
      */
     public void setZoomInEnabled(boolean enabled) {
@@ -242,7 +223,7 @@
 
     /**
      * Whether to enable the zoom out control.
-     * 
+     *
      * @param enabled Whether to enable the zoom out control.
      */
     public void setZoomOutEnabled(boolean enabled) {
@@ -251,7 +232,7 @@
 
     /**
      * Sets the delay between zoom callbacks as the user holds a zoom button.
-     * 
+     *
      * @param speed The delay in milliseconds between zoom callbacks.
      */
     public void setZoomSpeed(long speed) {
@@ -264,7 +245,8 @@
         lp.gravity = Gravity.TOP | Gravity.LEFT;
         lp.flags = LayoutParams.FLAG_NOT_TOUCHABLE |
                 LayoutParams.FLAG_NOT_FOCUSABLE |
-                LayoutParams.FLAG_LAYOUT_NO_LIMITS;
+                LayoutParams.FLAG_LAYOUT_NO_LIMITS |
+                LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         lp.height = LayoutParams.WRAP_CONTENT;
         lp.width = LayoutParams.FILL_PARENT;
         lp.type = LayoutParams.TYPE_APPLICATION_PANEL;
@@ -299,7 +281,7 @@
 
     /**
      * Sets the {@link OnZoomListener} listener that receives callbacks to zoom.
-     * 
+     *
      * @param listener The listener that will be told to zoom.
      */
     public void setOnZoomListener(OnZoomListener listener) {
@@ -310,7 +292,7 @@
      * Sets whether the zoom controls should be focusable. If the controls are
      * focusable, then trackball and arrow key interactions are possible.
      * Otherwise, only touch interactions are possible.
-     * 
+     *
      * @param focusable Whether the zoom controls should be focusable.
      */
     public void setFocusable(boolean focusable) {
@@ -327,8 +309,26 @@
     }
 
     /**
+     * Whether the zoom controls will be automatically dismissed after showing.
+     *
+     * @return Whether the zoom controls will be auto dismissed after showing.
+     */
+    public boolean isAutoDismissed() {
+        return mAutoDismissControls;
+    }
+
+    /**
+     * Sets whether the zoom controls will be automatically dismissed after
+     * showing.
+     */
+    public void setAutoDismissed(boolean autoDismiss) {
+        if (mAutoDismissControls == autoDismiss) return;
+        mAutoDismissControls = autoDismiss;
+    }
+
+    /**
      * Whether the zoom controls are visible to the user.
-     * 
+     *
      * @return Whether the zoom controls are visible to the user.
      */
     public boolean isVisible() {
@@ -337,7 +337,7 @@
 
     /**
      * Sets whether the zoom controls should be visible to the user.
-     * 
+     *
      * @param visible Whether the zoom controls should be visible to the user.
      */
     public void setVisible(boolean visible) {
@@ -419,7 +419,7 @@
      * <p>
      * The client can add other views to this container to link them with the
      * zoom controls.
-     * 
+     *
      * @return The container of the zoom controls. It will be a layout that
      *         respects the gravity of a child's layout parameters.
      */
@@ -427,43 +427,20 @@
         return mContainer;
     }
 
-    private void dismissControlsDelayed(int delay) {
-        mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS);
-        mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay);
+    /**
+     * Gets the view for the zoom controls.
+     *
+     * @return The zoom controls view.
+     */
+    public View getZoomControls() {
+        return mControls;
     }
 
-    /**
-     * Should be called by the client for each event belonging to the second tap
-     * (the down, move, up, and/or cancel events).
-     *
-     * @param event The event belonging to the second tap.
-     * @return Whether the event was consumed.
-     */
-    public boolean handleDoubleTapEvent(MotionEvent event) {
-        int action = event.getAction();
-
-        if (action == MotionEvent.ACTION_DOWN) {
-            int x = (int) event.getX();
-            int y = (int) event.getY();
-
-            /*
-             * This class will consume all events in the second tap (down,
-             * move(s), up). But, the owner already got the second tap's down,
-             * so cancel that. Do this before setVisible, since that call
-             * will set us as a touch listener.
-             */
-            MotionEvent cancelEvent = MotionEvent.obtain(event.getDownTime(),
-                    SystemClock.elapsedRealtime(),
-                    MotionEvent.ACTION_CANCEL, 0, 0, 0);
-            mOwnerView.dispatchTouchEvent(cancelEvent);
-            cancelEvent.recycle();
-
-            setVisible(true);
-            centerPoint(x, y);
-            mIsSecondTapDown = true;
+    private void dismissControlsDelayed(int delay) {
+        if (mAutoDismissControls) {
+            mHandler.removeMessages(MSG_DISMISS_ZOOM_CONTROLS);
+            mHandler.sendEmptyMessageDelayed(MSG_DISMISS_ZOOM_CONTROLS, delay);
         }
-
-        return true;
     }
 
     private void refreshPositioningVariables() {
@@ -477,7 +454,7 @@
         mOwnerView.getLocationOnScreen(mOwnerViewRawLocation);
         mContainerRawLocation[0] = mOwnerViewRawLocation[0];
         mContainerRawLocation[1] = mOwnerViewRawLocation[1] + containerOwnerYOffset;
-        
+
         int[] ownerViewWindowLoc = mTempIntArray;
         mOwnerView.getLocationInWindow(ownerViewWindowLoc);
 
@@ -488,39 +465,30 @@
         if (mIsVisible) {
             mWindowManager.updateViewLayout(mContainer, mContainerLayoutParams);
         }
-        
-    }
 
-    /**
-     * Centers the point (in owner view's coordinates).
-     */
-    private void centerPoint(int x, int y) {
-        if (mCallback != null) {
-            mCallback.onCenter(x, y);
-        }
     }
 
     /* This will only be called when the container has focus. */
     private boolean onContainerKey(KeyEvent event) {
         int keyCode = event.getKeyCode();
         if (isInterestingKey(keyCode)) {
-            
+
             if (keyCode == KeyEvent.KEYCODE_BACK) {
                 setVisible(false);
             } else {
                 dismissControlsDelayed(ZOOM_CONTROLS_TIMEOUT);
             }
-            
+
             // Let the container handle the key
             return false;
-            
+
         } else {
-            
+
             ViewRoot viewRoot = getOwnerViewRoot();
             if (viewRoot != null) {
                 viewRoot.dispatchKey(event);
             }
-            
+
             // We gave the key to the owner, don't let the container handle this key
             return true;
         }
@@ -540,13 +508,13 @@
                 return false;
         }
     }
-    
+
     private ViewRoot getOwnerViewRoot() {
         View rootViewOfOwner = mOwnerView.getRootView();
         if (rootViewOfOwner == null) {
             return null;
         }
-        
+
         ViewParent parentOfRootView = rootViewOfOwner.getParent();
         if (parentOfRootView instanceof ViewRoot) {
             return (ViewRoot) parentOfRootView;
@@ -562,13 +530,6 @@
     public boolean onTouch(View v, MotionEvent event) {
         int action = event.getAction();
 
-        // Consume all events during the second-tap interaction (down, move, up/cancel)
-        boolean consumeEvent = mIsSecondTapDown;
-        if ((action == MotionEvent.ACTION_UP) || (action == MotionEvent.ACTION_CANCEL)) {
-            // The second tap can no longer be down
-            mIsSecondTapDown = false;
-        }
-
         if (mReleaseTouchListenerOnUp) {
             // The controls were dismissed but we need to throw away all events until the up
             if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
@@ -609,18 +570,21 @@
                     mOwnerViewRawLocation[1] - targetViewRawY);
             /* Disallow negative coordinates (which can occur due to
              * ZOOM_CONTROLS_TOUCH_PADDING) */
-            if (containerEvent.getX() < 0) {
-                containerEvent.offsetLocation(-containerEvent.getX(), 0);
+            // These are floats because we need to potentially offset away this exact amount
+            float containerX = containerEvent.getX();
+            float containerY = containerEvent.getY();
+            if (containerX < 0 && containerX > -ZOOM_CONTROLS_TOUCH_PADDING) {
+                containerEvent.offsetLocation(-containerX, 0);
             }
-            if (containerEvent.getY() < 0) {
-                containerEvent.offsetLocation(0, -containerEvent.getY());
+            if (containerY < 0 && containerY > -ZOOM_CONTROLS_TOUCH_PADDING) {
+                containerEvent.offsetLocation(0, -containerY);
             }
             boolean retValue = targetView.dispatchTouchEvent(containerEvent);
             containerEvent.recycle();
-            return retValue || consumeEvent;
+            return retValue;
 
         } else {
-            return consumeEvent;
+            return false;
         }
     }
 
@@ -646,7 +610,7 @@
 
         View closestChild = null;
         int closestChildDistanceSq = Integer.MAX_VALUE;
-        
+
         for (int i = mContainer.getChildCount() - 1; i >= 0; i--) {
             View child = mContainer.getChildAt(i);
             if (child.getVisibility() != View.VISIBLE) {
@@ -657,13 +621,23 @@
             if (frame.contains(containerCoordsX, containerCoordsY)) {
                 return child;
             }
-            
-            int distanceX = Math.min(Math.abs(frame.left - containerCoordsX),
+
+            int distanceX;
+            if (containerCoordsX >= frame.left && containerCoordsX <= frame.right) {
+                distanceX = 0;
+            } else {
+                distanceX = Math.min(Math.abs(frame.left - containerCoordsX),
                     Math.abs(containerCoordsX - frame.right));
-            int distanceY = Math.min(Math.abs(frame.top - containerCoordsY),
-                    Math.abs(containerCoordsY - frame.bottom));
+            }
+            int distanceY;
+            if (containerCoordsY >= frame.top && containerCoordsY <= frame.bottom) {
+                distanceY = 0;
+            } else {
+                distanceY = Math.min(Math.abs(frame.top - containerCoordsY),
+                        Math.abs(containerCoordsY - frame.bottom));
+            }
             int distanceSq = distanceX * distanceX + distanceY * distanceY;
-                        
+
             if ((distanceSq < mTouchPaddingScaledSq) &&
                     (distanceSq < closestChildDistanceSq)) {
                 closestChild = child;
@@ -679,130 +653,27 @@
         refreshPositioningVariables();
     }
 
-    /*
-     * This is static so Activities can call this instead of the Views
-     * (Activities usually do not have a reference to the ZoomButtonsController
-     * instance.)
-     */
-    /**
-     * Shows a "tutorial" (some text) to the user teaching her the new zoom
-     * invocation method. Must call from the main thread.
-     * <p>
-     * It checks the global system setting to ensure this has not been seen
-     * before. Furthermore, if the application does not have privilege to write
-     * to the system settings, it will store this bit locally in a shared
-     * preference.
-     *
-     * @hide This should only be used by our main apps--browser, maps, and
-     *       gallery
-     */
-    public static void showZoomTutorialOnce(Context context) {
-        
-        // TODO: remove this code, but to hit the weekend build, just never show
-        if (true) return;
-        
-        ContentResolver cr = context.getContentResolver();
-        if (Settings.System.getInt(cr, SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) {
-            return;
-        }
-
-        SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE);
-        if (sp.getInt(SETTING_NAME_SHOWN_TUTORIAL, 0) == 1) {
-            return;
-        }
-
-        if (sTutorialDialog != null && sTutorialDialog.isShowing()) {
-            sTutorialDialog.dismiss();
-        }
-
-        LayoutInflater layoutInflater =
-                (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        TextView textView = (TextView) layoutInflater.inflate(
-                com.android.internal.R.layout.alert_dialog_simple_text, null)
-                .findViewById(android.R.id.text1);
-        textView.setText(com.android.internal.R.string.tutorial_double_tap_to_zoom_message_short);
-
-        sTutorialDialog = new AlertDialog.Builder(context)
-                .setView(textView)
-                .setIcon(0)
-                .create();
-
-        Window window = sTutorialDialog.getWindow();
-        window.setGravity(Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM);
-        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND |
-                WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
-        window.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |
-                WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
-
-        sTutorialDialog.show();
-    }
-
-    /** @hide Should only be used by Android platform apps */
-    public static void finishZoomTutorial(Context context, boolean userNotified) {
-        if (sTutorialDialog == null) return;
-
-        sTutorialDialog.dismiss();
-        sTutorialDialog = null;
-
-        // Record that they have seen the tutorial
-        if (userNotified) {
-            try {
-                Settings.System.putInt(context.getContentResolver(), SETTING_NAME_SHOWN_TUTORIAL,
-                        1);
-            } catch (SecurityException e) {
-                /*
-                 * The app does not have permission to clear this global flag, make
-                 * sure the user does not see the message when he comes back to this
-                 * same app at least.
-                 */
-                SharedPreferences sp = context.getSharedPreferences("_zoom", Context.MODE_PRIVATE);
-                sp.edit().putInt(SETTING_NAME_SHOWN_TUTORIAL, 1).commit();
-            }
-        }
-    }
-
-    /** @hide Should only be used by Android platform apps */
-    public void finishZoomTutorial() {
-        finishZoomTutorial(mContext, true);
-    }
-
-    /** @hide Should only be used only be WebView and MapView */
-    public View getDummyZoomControls() {
-        if (mDummyZoomControls == null) {
-            mDummyZoomControls = new InvisibleView(mContext);
-        }
-        return mDummyZoomControls;
-    }
-    
     /**
      * Interface that will be called when the user performs an interaction that
      * triggers some action, for example zooming.
      */
     public interface OnZoomListener {
-        /**
-         * Called when the given point should be centered. The point will be in
-         * owner view coordinates.
-         * 
-         * @param x The x of the point.
-         * @param y The y of the point.
-         */
-        void onCenter(int x, int y);
-        
+
         /**
          * Called when the zoom controls' visibility changes.
-         * 
+         *
          * @param visible Whether the zoom controls are visible.
          */
         void onVisibilityChanged(boolean visible);
-        
+
         /**
          * Called when the owner view needs to be zoomed.
-         * 
+         *
          * @param zoomIn The direction of the zoom: true to zoom in, false to zoom out.
          */
         void onZoom(boolean zoomIn);
     }
-    
+
     private class Container extends FrameLayout {
         public Container(Context context) {
             super(context);
@@ -820,29 +691,4 @@
         }
     }
 
-    /**
-     * An InvisibleView is an invisible, zero-sized View for backwards
-     * compatibility
-     */
-    private final class InvisibleView extends View {
-
-        private InvisibleView(Context context) {
-            super(context);
-            setVisibility(GONE);
-        }
-
-        @Override
-        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-            setMeasuredDimension(0, 0);
-        }
-
-        @Override
-        public void draw(Canvas canvas) {
-        }
-
-        @Override
-        protected void dispatchDraw(Canvas canvas) {
-        }
-    }
-
 }
diff --git a/core/java/android/widget/ZoomControls.java b/core/java/android/widget/ZoomControls.java
index 84d8f0e..a12aee5 100644
--- a/core/java/android/widget/ZoomControls.java
+++ b/core/java/android/widget/ZoomControls.java
@@ -30,11 +30,6 @@
 /**
  * The {@code ZoomControls} class displays a simple set of controls used for zooming and
  * provides callbacks to register for events. */
-// TODO: pending API council
-// * <p>
-// * Instead of using this directly, consider using the {@link ZoomButtonsController} which
-// * handles displaying the zoom controls.
-// */
 @Widget
 public class ZoomControls extends LinearLayout {
 
diff --git a/core/java/com/android/internal/app/AlertController.java b/core/java/com/android/internal/app/AlertController.java
index 5c44b2d..b330a18 100644
--- a/core/java/com/android/internal/app/AlertController.java
+++ b/core/java/com/android/internal/app/AlertController.java
@@ -361,11 +361,14 @@
         if (mView != null) {
             customPanel = (FrameLayout) mWindow.findViewById(R.id.customPanel);
             FrameLayout custom = (FrameLayout) mWindow.findViewById(R.id.custom);
-            custom.addView(mView, new LayoutParams(FILL_PARENT, WRAP_CONTENT));
+            custom.addView(mView, new LayoutParams(FILL_PARENT, FILL_PARENT));
             if (mViewSpacingSpecified) {
                 custom.setPadding(mViewSpacingLeft, mViewSpacingTop, mViewSpacingRight,
                         mViewSpacingBottom);
             }
+            if (mListView != null) {
+                ((LinearLayout.LayoutParams) customPanel.getLayoutParams()).weight = 0;
+            }
         } else {
             mWindow.findViewById(R.id.customPanel).setVisibility(View.GONE);
         }
@@ -456,7 +459,9 @@
             
             if (mListView != null) {
                 contentPanel.removeView(mWindow.findViewById(R.id.scrollView));
-                contentPanel.addView(mListView, new LinearLayout.LayoutParams(FILL_PARENT, WRAP_CONTENT));
+                contentPanel.addView(mListView,
+                        new LinearLayout.LayoutParams(FILL_PARENT, FILL_PARENT));
+                contentPanel.setLayoutParams(new LinearLayout.LayoutParams(FILL_PARENT, 0, 1.0f));
             } else {
                 contentPanel.setVisibility(View.GONE);
             }
diff --git a/core/java/com/android/internal/app/IBatteryStats.aidl b/core/java/com/android/internal/app/IBatteryStats.aidl
index edda1d9..d259756 100644
--- a/core/java/com/android/internal/app/IBatteryStats.aidl
+++ b/core/java/com/android/internal/app/IBatteryStats.aidl
@@ -30,7 +30,15 @@
     void noteScreenOff();
     void notePhoneOn();
     void notePhoneOff();
-    void setOnBattery(boolean onBattery);
+    void noteWifiOn();
+    void noteWifiOff();
+    void noteBluetoothOn();
+    void noteBluetoothOff();
+    void noteFullWifiLockAcquired(int uid);
+    void noteFullWifiLockReleased(int uid);
+    void noteScanWifiLockAcquired(int uid);
+    void noteScanWifiLockReleased(int uid);
+    void setOnBattery(boolean onBattery, int level);
     long getAwakeTimeBattery();
     long getAwakeTimePlugged();
 }
diff --git a/core/java/com/android/internal/app/RingtonePickerActivity.java b/core/java/com/android/internal/app/RingtonePickerActivity.java
index 1f8e6f0..5a0fea3 100644
--- a/core/java/com/android/internal/app/RingtonePickerActivity.java
+++ b/core/java/com/android/internal/app/RingtonePickerActivity.java
@@ -247,9 +247,13 @@
         } else {
             setResult(RESULT_CANCELED);
         }
-        
-        mCursor.deactivate();
-        
+
+        getWindow().getDecorView().post(new Runnable() {
+            public void run() {
+                mCursor.deactivate();
+            }
+        });
+
         finish();
     }
     
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 7eea8b7..b3ae0d6 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -47,7 +47,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS' 
 
     // Current on-disk Parcel version
-    private static final int VERSION = 25;
+    private static final int VERSION = 27;
 
     private final File mFile;
     private final File mBackupFile;
@@ -92,6 +92,12 @@
     boolean mPhoneOn;
     Timer mPhoneOnTimer;
     
+    boolean mWifiOn;
+    Timer mWifiOnTimer;
+    
+    boolean mBluetoothOn;
+    Timer mBluetoothOnTimer;
+    
     /**
      * These provide time bases that discount the time the device is plugged
      * in to power.
@@ -106,6 +112,12 @@
     long mUnpluggedBatteryUptime;
     long mUnpluggedBatteryRealtime;
     
+    /*
+     * These keep track of battery levels (1-100) at the last plug event and the last unplug event.
+     */
+    int mUnpluggedStartLevel;
+    int mPluggedStartLevel;
+    
     long mLastWriteTime = 0; // Milliseconds
 
     // For debugging
@@ -471,6 +483,62 @@
         }
     }
     
+    public void noteWifiOnLocked() {
+        if (!mWifiOn) {
+            mWifiOn = true;
+            mWifiOnTimer.startRunningLocked(this);
+        }
+    }
+    
+    public void noteWifiOffLocked() {
+        if (mWifiOn) {
+            mWifiOn = false;
+            mWifiOnTimer.stopRunningLocked(this);
+        }
+    }
+    
+    public void noteBluetoothOnLocked() {
+        if (!mBluetoothOn) {
+            mBluetoothOn = true;
+            mBluetoothOnTimer.startRunningLocked(this);
+        }
+    }
+    
+    public void noteBluetoothOffLocked() {
+        if (mBluetoothOn) {
+            mBluetoothOn = false;
+            mBluetoothOnTimer.stopRunningLocked(this);
+        }
+    }
+    
+    public void noteFullWifiLockAcquiredLocked(int uid) {
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteFullWifiLockAcquiredLocked();
+        }
+    }
+
+    public void noteFullWifiLockReleasedLocked(int uid) {
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteFullWifiLockReleasedLocked();
+        }
+    }
+
+    public void noteScanWifiLockAcquiredLocked(int uid) {
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteScanWifiLockAcquiredLocked();
+        }
+    }
+
+    public void noteScanWifiLockReleasedLocked(int uid) {
+        Uid u = mUidStats.get(uid);
+        if (u != null) {
+            u.noteScanWifiLockReleasedLocked();
+        }
+    }
+    
     @Override public long getScreenOnTime(long batteryRealtime, int which) {
         return mScreenOnTimer.getTotalTime(batteryRealtime, which);
     }
@@ -479,6 +547,14 @@
         return mPhoneOnTimer.getTotalTime(batteryRealtime, which);
     }
     
+    @Override public long getWifiOnTime(long batteryRealtime, int which) {
+        return mWifiOnTimer.getTotalTime(batteryRealtime, which);
+    }
+    
+    @Override public long getBluetoothOnTime(long batteryRealtime, int which) {
+        return mBluetoothOnTimer.getTotalTime(batteryRealtime, which);
+    }
+    
     @Override public boolean getIsOnBattery() {
         return mOnBattery;
     }
@@ -505,6 +581,12 @@
         long mStartedTcpBytesReceived = -1;
         long mStartedTcpBytesSent = -1;
         
+        boolean mFullWifiLockOut;
+        Timer mFullWifiLockTimer;
+        
+        boolean mScanWifiLockOut;
+        Timer mScanWifiLockTimer;
+        
         /**
          * The statistics we have collected for this uid's wake locks.
          */
@@ -527,6 +609,8 @@
         
         public Uid(int uid) {
             mUid = uid;
+            mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables);
+            mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables);
         }
 
         @Override
@@ -586,6 +670,47 @@
             }
         }
         
+        @Override
+        public void noteFullWifiLockAcquiredLocked() {
+            if (!mFullWifiLockOut) {
+                mFullWifiLockOut = true;
+                mFullWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+        
+        @Override
+        public void noteFullWifiLockReleasedLocked() {
+            if (mFullWifiLockOut) {
+                mFullWifiLockOut = false;
+                mFullWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+        
+        @Override
+        public void noteScanWifiLockAcquiredLocked() {
+            if (!mScanWifiLockOut) {
+                mScanWifiLockOut = true;
+                mScanWifiLockTimer.startRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+        
+        @Override
+        public void noteScanWifiLockReleasedLocked() {
+            if (mScanWifiLockOut) {
+                mScanWifiLockOut = false;
+                mScanWifiLockTimer.stopRunningLocked(BatteryStatsImpl.this);
+            }
+        }
+        @Override 
+        public long getFullWifiLockTime(long batteryRealtime, int which) {
+            return mFullWifiLockTimer.getTotalTime(batteryRealtime, which);
+        }
+        
+        @Override 
+        public long getScanWifiLockTime(long batteryRealtime, int which) {
+            return mScanWifiLockTimer.getTotalTime(batteryRealtime, which);
+        }
+        
         public long computeCurrentTcpBytesSent() {
             return mCurrentTcpBytesSent + (mStartedTcpBytesSent >= 0
                     ? (NetStat.getUidTxBytes(mUid) - mStartedTcpBytesSent) : 0);
@@ -626,6 +751,8 @@
             out.writeLong(computeCurrentTcpBytesSent());
             out.writeLong(mTcpBytesReceivedAtLastUnplug);
             out.writeLong(mTcpBytesSentAtLastUnplug);
+            mFullWifiLockTimer.writeToParcel(out, batteryRealtime);
+            mScanWifiLockTimer.writeToParcel(out, batteryRealtime);
         }
 
         void readFromParcelLocked(ArrayList<Unpluggable> unpluggables, Parcel in) {
@@ -671,6 +798,10 @@
             mCurrentTcpBytesSent = in.readLong();
             mTcpBytesReceivedAtLastUnplug = in.readLong();
             mTcpBytesSentAtLastUnplug = in.readLong();
+            mFullWifiLockOut = false;
+            mFullWifiLockTimer = new Timer(FULL_WIFI_LOCK, null, mUnpluggables, in);
+            mScanWifiLockOut = false;
+            mScanWifiLockTimer = new Timer(SCAN_WIFI_LOCK, null, mUnpluggables, in);
         }
 
         /**
@@ -852,6 +983,9 @@
             }
             
             void writeToParcelLocked(Parcel out) {
+                final long uSecRealtime = SystemClock.elapsedRealtime() * 1000;
+                final long batteryRealtime = getBatteryRealtimeLocked(uSecRealtime);
+                
                 out.writeLong(mUserTime);
                 out.writeLong(mSystemTime);
                 out.writeInt(mStarts);
@@ -1462,6 +1596,8 @@
         mStartCount++;
         mScreenOnTimer = new Timer(-1, null, mUnpluggables);
         mPhoneOnTimer = new Timer(-2, null, mUnpluggables);
+        mWifiOnTimer = new Timer(-3, null, mUnpluggables);
+        mBluetoothOnTimer = new Timer(-4, null, mUnpluggables);
         mOnBattery = mOnBatteryInternal = false;
         mTrackBatteryPastUptime = 0;
         mTrackBatteryPastRealtime = 0;
@@ -1469,6 +1605,8 @@
         mRealtimeStart = mTrackBatteryRealtimeStart = SystemClock.elapsedRealtime() * 1000;
         mUnpluggedBatteryUptime = getBatteryUptimeLocked(mUptimeStart);
         mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(mRealtimeStart);
+        mUnpluggedStartLevel = 0;
+        mPluggedStartLevel = 0;
     }
 
     public BatteryStatsImpl(Parcel p) {
@@ -1485,7 +1623,7 @@
         return mOnBattery;
     }
 
-    public void setOnBattery(boolean onBattery) {
+    public void setOnBattery(boolean onBattery, int level) {
         synchronized(this) {
             if (mOnBattery != onBattery) {
                 mOnBattery = mOnBatteryInternal = onBattery;
@@ -1498,10 +1636,12 @@
                     mTrackBatteryRealtimeStart = realtime;
                     mUnpluggedBatteryUptime = getBatteryUptimeLocked(uptime);
                     mUnpluggedBatteryRealtime = getBatteryRealtimeLocked(realtime);
+                    mUnpluggedStartLevel = level;
                     doUnplug(mUnpluggedBatteryUptime, mUnpluggedBatteryRealtime);
                 } else {
                     mTrackBatteryPastUptime += uptime - mTrackBatteryUptimeStart;
                     mTrackBatteryPastRealtime += realtime - mTrackBatteryRealtimeStart;
+                    mPluggedStartLevel = level;
                     doPlug(getBatteryUptimeLocked(uptime), getBatteryRealtimeLocked(realtime));
                 }
                 if ((mLastWriteTime + (60 * 1000)) < mSecRealtime) {
@@ -1602,6 +1742,28 @@
     public long getBatteryRealtime(long curTime) {
         return getBatteryRealtimeLocked(curTime);
     }
+    
+    @Override
+    public int getUnpluggedStartLevel() {
+        synchronized(this) {
+            return getUnluggedStartLevelLocked();
+        }
+    }
+    
+    public int getUnluggedStartLevelLocked() {
+            return mUnpluggedStartLevel;
+    }
+    
+    @Override
+    public int getPluggedStartLevel() {
+        synchronized(this) {
+            return getPluggedStartLevelLocked();
+        }
+    }
+    
+    public int getPluggedStartLevelLocked() {
+            return mPluggedStartLevel;
+    }
 
     /**
      * Retrieve the statistics object for a particular uid, creating if needed.
@@ -1762,12 +1924,19 @@
         mLastUptime = in.readLong();
         mRealtime = in.readLong();
         mLastRealtime = in.readLong();
+        mUnpluggedStartLevel = in.readInt();
+        mPluggedStartLevel = in.readInt();
+        
         mStartCount++;
         
         mScreenOn = false;
         mScreenOnTimer.readSummaryFromParcelLocked(in);
         mPhoneOn = false;
         mPhoneOnTimer.readSummaryFromParcelLocked(in);
+        mWifiOn = false;
+        mWifiOnTimer.readSummaryFromParcelLocked(in);
+        mBluetoothOn = false;
+        mBluetoothOnTimer.readSummaryFromParcelLocked(in);
 
         final int NU = in.readInt();
         for (int iu = 0; iu < NU; iu++) {
@@ -1775,6 +1944,11 @@
             Uid u = new Uid(uid);
             mUidStats.put(uid, u);
 
+            u.mFullWifiLockOut = false;
+            u.mFullWifiLockTimer.readSummaryFromParcelLocked(in);
+            u.mScanWifiLockOut = false;
+            u.mScanWifiLockTimer.readSummaryFromParcelLocked(in);
+            
             int NW = in.readInt();
             for (int iw = 0; iw < NW; iw++) {
                 String wlName = in.readString();
@@ -1857,15 +2031,23 @@
         out.writeLong(computeUptime(NOW_SYS, STATS_CURRENT));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_TOTAL));
         out.writeLong(computeRealtime(NOWREAL_SYS, STATS_CURRENT));
+        out.writeInt(mUnpluggedStartLevel);
+        out.writeInt(mPluggedStartLevel);
+        
         
         mScreenOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
         mPhoneOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+        mWifiOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+        mBluetoothOnTimer.writeSummaryFromParcelLocked(out, NOWREAL);
 
         final int NU = mUidStats.size();
         out.writeInt(NU);
         for (int iu = 0; iu < NU; iu++) {
             out.writeInt(mUidStats.keyAt(iu));
             Uid u = mUidStats.valueAt(iu);
+            
+            u.mFullWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
+            u.mScanWifiLockTimer.writeSummaryFromParcelLocked(out, NOWREAL);
 
             int NW = u.mWakelockStats.size();
             out.writeInt(NW);
@@ -1979,6 +2161,10 @@
         mScreenOnTimer = new Timer(-1, null, mUnpluggables, in);
         mPhoneOn = false;
         mPhoneOnTimer = new Timer(-2, null, mUnpluggables, in);
+        mWifiOn = false;
+        mWifiOnTimer = new Timer(-2, null, mUnpluggables, in);
+        mBluetoothOn = false;
+        mBluetoothOnTimer = new Timer(-2, null, mUnpluggables, in);
         mUptime = in.readLong();
         mUptimeStart = in.readLong();
         mLastUptime = in.readLong();
@@ -1993,6 +2179,8 @@
         mTrackBatteryRealtimeStart = in.readLong();
         mUnpluggedBatteryUptime = in.readLong();
         mUnpluggedBatteryRealtime = in.readLong();
+        mUnpluggedStartLevel = in.readInt();
+        mPluggedStartLevel = in.readInt();
         mLastWriteTime = in.readLong();
 
         mPartialTimers.clear();
@@ -2028,6 +2216,8 @@
         out.writeLong(mBatteryLastRealtime);
         mScreenOnTimer.writeToParcel(out, batteryRealtime);
         mPhoneOnTimer.writeToParcel(out, batteryRealtime);
+        mWifiOnTimer.writeToParcel(out, batteryRealtime);
+        mBluetoothOnTimer.writeToParcel(out, batteryRealtime);
         out.writeLong(mUptime);
         out.writeLong(mUptimeStart);
         out.writeLong(mLastUptime);
@@ -2041,6 +2231,8 @@
         out.writeLong(mTrackBatteryRealtimeStart);
         out.writeLong(mUnpluggedBatteryUptime);
         out.writeLong(mUnpluggedBatteryRealtime);
+        out.writeInt(mUnpluggedStartLevel);
+        out.writeInt(mPluggedStartLevel);
         out.writeLong(mLastWriteTime);
 
         int size = mUidStats.size();
@@ -2070,6 +2262,10 @@
             mScreenOnTimer.logState();
             Log.i(TAG, "*** Phone timer:");
             mPhoneOnTimer.logState();
+            Log.i(TAG, "*** Wifi timer:");
+            mWifiOnTimer.logState();
+            Log.i(TAG, "*** Bluetooth timer:");
+            mBluetoothOnTimer.logState();
         }
         super.dumpLocked(pw);
     }
diff --git a/core/java/com/android/internal/view/menu/IconMenuItemView.java b/core/java/com/android/internal/view/menu/IconMenuItemView.java
index 9e1f2ae..66e15c1 100644
--- a/core/java/com/android/internal/view/menu/IconMenuItemView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuItemView.java
@@ -28,6 +28,7 @@
 import android.view.View;
 import android.view.ViewDebug;
 import android.widget.TextView;
+import android.text.Layout;
 
 /**
  * The item view for each item in the {@link IconMenuView}.  
@@ -236,6 +237,32 @@
         positionIcon();
     }
 
+    @Override
+    protected void onTextChanged(CharSequence text, int start, int before, int after) {
+        super.onTextChanged(text, start, before, after);
+
+        // our layout params depend on the length of the text
+        setLayoutParams(getTextAppropriateLayoutParams());
+    }
+
+    /**
+     * @return layout params appropriate for this view.  If layout params already exist, it will
+     *         augment them to be appropriate to the current text size.
+     */
+    IconMenuView.LayoutParams getTextAppropriateLayoutParams() {
+        IconMenuView.LayoutParams lp = (IconMenuView.LayoutParams) getLayoutParams();
+        if (lp == null) {
+            // Default layout parameters
+            lp = new IconMenuView.LayoutParams(
+                    IconMenuView.LayoutParams.FILL_PARENT, IconMenuView.LayoutParams.FILL_PARENT);
+        }
+
+        // Set the desired width of item
+        lp.desiredWidth = (int) Layout.getDesiredWidth(getText(), getPaint());
+
+        return lp;
+    }
+
     /**
      * Positions the icon vertically (horizontal centering is taken care of by
      * the TextView's gravity).
@@ -280,5 +307,5 @@
     public boolean showsIcon() {
         return true;
     }
-    
+
 }
diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java
index 781c608..6034a1e 100644
--- a/core/java/com/android/internal/view/menu/IconMenuView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuView.java
@@ -26,7 +26,6 @@
 import android.graphics.drawable.Drawable;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.text.Layout;
 import android.util.AttributeSet;
 import android.view.KeyEvent;
 import android.view.View;
@@ -278,14 +277,7 @@
      * Adds an IconMenuItemView to this icon menu view.
      * @param itemView The item's view to add
      */
-    private void addItemView(IconMenuItemView itemView) {
-        LayoutParams lp = (LayoutParams) itemView.getLayoutParams();
-        
-        if (lp == null) {
-            // Default layout parameters
-            lp = new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
-        }
-        
+    private void addItemView(IconMenuItemView itemView) {   
         // Set ourselves on the item view
         itemView.setIconMenuView(this);
         
@@ -295,10 +287,7 @@
         // This class is the invoker for all its item views 
         itemView.setItemInvoker(this);
         
-        // Set the desired width of item
-        lp.desiredWidth = (int) Layout.getDesiredWidth(itemView.getText(), itemView.getPaint());
-        
-        addView(itemView, lp);
+        addView(itemView, itemView.getTextAppropriateLayoutParams());
     }
 
     /**
diff --git a/core/jni/android_location_GpsLocationProvider.cpp b/core/jni/android_location_GpsLocationProvider.cpp
index dee3fdd..f0b35e9 100644
--- a/core/jni/android_location_GpsLocationProvider.cpp
+++ b/core/jni/android_location_GpsLocationProvider.cpp
@@ -35,6 +35,7 @@
 
 static const GpsInterface* sGpsInterface = NULL;
 static const GpsXtraInterface* sGpsXtraInterface = NULL;
+static const GpsSuplInterface* sGpsSuplInterface = NULL;
 
 // data written to by GPS callbacks
 static GpsLocation  sGpsLocation;
@@ -144,9 +145,10 @@
     sGpsInterface->cleanup();
 }
 
-static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jboolean singleFix, jint fixFrequency)
+static jboolean android_location_GpsLocationProvider_start(JNIEnv* env, jobject obj, jint positionMode, 
+        jboolean singleFix, jint fixFrequency)
 {
-    int result = sGpsInterface->set_position_mode(GPS_POSITION_MODE_STANDALONE, (singleFix ? 0 : fixFrequency));
+    int result = sGpsInterface->set_position_mode(positionMode, (singleFix ? 0 : fixFrequency));
     if (result) {
         return result;
     }
@@ -267,6 +269,33 @@
     env->ReleaseByteArrayElements(data, bytes, 0);
 }
 
+static void android_location_GpsLocationProvider_set_supl_server(JNIEnv* env, jobject obj,
+        jint addr, jint port)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        sGpsSuplInterface->set_server(addr, port);
+    }
+}
+
+static void android_location_GpsLocationProvider_set_supl_apn(JNIEnv* env, jobject obj, jstring apn)
+{
+    if (!sGpsSuplInterface) {
+        sGpsSuplInterface = (const GpsSuplInterface*)sGpsInterface->get_extension(GPS_SUPL_INTERFACE);
+    }
+    if (sGpsSuplInterface) {
+        if (apn == NULL) {
+            jniThrowException(env, "java/lang/IllegalArgumentException", NULL);
+            return;
+        }
+        const char *apnStr = env->GetStringUTFChars(apn, NULL);
+        sGpsSuplInterface->set_apn(apnStr);
+        env->ReleaseStringUTFChars(apn, apnStr);
+    }
+}
+
 static JNINativeMethod sMethods[] = {
      /* name, signature, funcPtr */
     {"class_init_native", "()V", (void *)android_location_GpsLocationProvider_class_init_native},
@@ -274,7 +303,7 @@
 	{"native_init", "()Z", (void*)android_location_GpsLocationProvider_init},
 	{"native_disable", "()V", (void*)android_location_GpsLocationProvider_disable},
 	{"native_cleanup", "()V", (void*)android_location_GpsLocationProvider_cleanup},
-	{"native_start", "(ZI)Z", (void*)android_location_GpsLocationProvider_start},
+	{"native_start", "(IZI)Z", (void*)android_location_GpsLocationProvider_start},
 	{"native_stop", "()Z", (void*)android_location_GpsLocationProvider_stop},
 	{"native_set_fix_frequency", "(I)V", (void*)android_location_GpsLocationProvider_set_fix_frequency},
 	{"native_delete_aiding_data", "(I)V", (void*)android_location_GpsLocationProvider_delete_aiding_data},
@@ -283,6 +312,8 @@
 	{"native_inject_time", "(JJI)V", (void*)android_location_GpsLocationProvider_inject_time},
 	{"native_supports_xtra", "()Z", (void*)android_location_GpsLocationProvider_supports_xtra},
 	{"native_inject_xtra_data", "([BI)V", (void*)android_location_GpsLocationProvider_inject_xtra_data},
+ 	{"native_set_supl_server", "(II)V", (void*)android_location_GpsLocationProvider_set_supl_server},
+ 	{"native_set_supl_apn", "(Ljava/lang/String;)V", (void*)android_location_GpsLocationProvider_set_supl_apn},
 };
 
 int register_android_location_GpsLocationProvider(JNIEnv* env)
diff --git a/core/jni/android_os_Hardware.cpp b/core/jni/android_os_Hardware.cpp
index bc8af78..8007662 100644
--- a/core/jni/android_os_Hardware.cpp
+++ b/core/jni/android_os_Hardware.cpp
@@ -15,7 +15,6 @@
 */
 
 #include <hardware_legacy/flashlight.h>
-#include <hardware_legacy/led.h>
 #include <hardware_legacy/power.h>
 
 #include <nativehelper/jni.h>
@@ -24,12 +23,6 @@
 
 namespace android {
 
-static jboolean
-setLedState(JNIEnv *env, jobject clazz, jint colorARGB, jint onMS, jint offMS)
-{
-    return set_led_state(colorARGB, onMS, offMS);
-}
-
 static jint
 getFlashlightEnabled(JNIEnv *env, jobject clazz)
 {
@@ -48,24 +41,6 @@
     enable_camera_flash(milliseconds);
 }
 
-static void
-setScreenBacklight(JNIEnv *env, jobject clazz, jint brightness)
-{
-    set_light_brightness(SCREEN_LIGHT, brightness);
-}
-
-static void
-setKeyboardBacklight(JNIEnv *env, jobject clazz, jboolean on)
-{
-    set_light_brightness(KEYBOARD_LIGHT, (on ? 255 : 0));
-}
-
-static void
-setButtonBacklight(JNIEnv *env, jobject clazz, jboolean on)
-{
-    set_light_brightness(BUTTON_LIGHT, (on ? 255 : 0));
-}
-
 // ============================================================================
 /*
  * JNI registration.
@@ -73,13 +48,9 @@
 
 static JNINativeMethod g_methods[] = {
     /* name, signature, funcPtr */
-    { "setLedState",       "(III)I", (void*)setLedState },
     { "getFlashlightEnabled", "()Z", (void*)getFlashlightEnabled },
     { "setFlashlightEnabled", "(Z)V", (void*)setFlashlightEnabled },
     { "enableCameraFlash", "(I)V", (void*)enableCameraFlash },
-    { "setScreenBacklight", "(I)V", (void*)setScreenBacklight },
-    { "setKeyboardBacklight", "(Z)V", (void*)setKeyboardBacklight },
-    { "setButtonBacklight", "(Z)V", (void*)setButtonBacklight },
 };
 
 int register_android_os_Hardware(JNIEnv* env)
diff --git a/core/jni/android_os_Power.cpp b/core/jni/android_os_Power.cpp
index c2d75b1..df5edba 100644
--- a/core/jni/android_os_Power.cpp
+++ b/core/jni/android_os_Power.cpp
@@ -70,12 +70,6 @@
 }
 
 static int
-setLightBrightness(JNIEnv *env, jobject clazz, jint mask, jint brightness)
-{
-    return set_light_brightness(mask, brightness);
-}
-
-static int
 setScreenState(JNIEnv *env, jobject clazz, jboolean on)
 {
     return set_screen_state(on);
@@ -109,7 +103,6 @@
     { "acquireWakeLock", "(ILjava/lang/String;)V", (void*)acquireWakeLock },
     { "releaseWakeLock", "(Ljava/lang/String;)V", (void*)releaseWakeLock },
     { "setLastUserActivityTimeout", "(J)I", (void*)setLastUserActivityTimeout },
-    { "setLightBrightness", "(II)I", (void*)setLightBrightness },
     { "setScreenState", "(Z)I", (void*)setScreenState },
     { "shutdown", "()V", (void*)android_os_Power_shutdown },
     { "reboot", "(Ljava/lang/String;)V", (void*)android_os_Power_reboot },
diff --git a/core/res/assets/webkit/youtube.html b/core/res/assets/webkit/youtube.html
index 5a40c1e..2aaaa15 100644
--- a/core/res/assets/webkit/youtube.html
+++ b/core/res/assets/webkit/youtube.html
@@ -43,7 +43,7 @@
       <table height="100%" width="100%">
         <tr>
           <td align="center" valign="middle" height="100%">
-            <a id="url" href="youtube:VIDEO_ID" target="_top">
+            <a id="url" href="vnd.youtube:VIDEO_ID" target="_top">
               <img src="play.png" style="border:0px"/>
             </a>
           </td>
diff --git a/core/res/res/anim/input_method_extract_enter.xml b/core/res/res/anim/input_method_extract_enter.xml
new file mode 100644
index 0000000..96b049f
--- /dev/null
+++ b/core/res/res/anim/input_method_extract_enter.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/fade_in.xml
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android"
+        android:interpolator="@anim/decelerate_interpolator"
+        android:fromAlpha="0.0" android:toAlpha="1.0"
+        android:duration="@android:integer/config_shortAnimTime" />
diff --git a/core/res/res/anim/input_method_extract_exit.xml b/core/res/res/anim/input_method_extract_exit.xml
new file mode 100644
index 0000000..26db13f
--- /dev/null
+++ b/core/res/res/anim/input_method_extract_exit.xml
@@ -0,0 +1,25 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/res/anim/fade_out.xml
+**
+** Copyright 2007, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License"); 
+** you may not use this file except in compliance with the License. 
+** You may obtain a copy of the License at 
+**
+**     http://www.apache.org/licenses/LICENSE-2.0 
+**
+** Unless required by applicable law or agreed to in writing, software 
+** distributed under the License is distributed on an "AS IS" BASIS, 
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
+** See the License for the specific language governing permissions and 
+** limitations under the License.
+*/
+-->
+
+<alpha xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@anim/accelerate_interpolator" 
+    android:fromAlpha="1.0"
+    android:toAlpha="0.0"
+    android:duration="@android:integer/config_shortAnimTime" 
+/>
diff --git a/core/res/res/drawable-land/statusbar_background.png b/core/res/res/drawable-land/statusbar_background.png
index 2a351a5..ef61e52 100644
--- a/core/res/res/drawable-land/statusbar_background.png
+++ b/core/res/res/drawable-land/statusbar_background.png
Binary files differ
diff --git a/core/res/res/drawable/code_lock_left.9.png b/core/res/res/drawable/code_lock_left.9.png
index a53264a..215dcc8 100644
--- a/core/res/res/drawable/code_lock_left.9.png
+++ b/core/res/res/drawable/code_lock_left.9.png
Binary files differ
diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml
new file mode 100644
index 0000000..2db3203
--- /dev/null
+++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2008 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.
+-->
+
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_enabled="false" android:drawable="@drawable/ic_btn_square_browser_zoom_page_overview_disabled" />
+    <item android:drawable="@drawable/ic_btn_square_browser_zoom_page_overview_normal" />
+</selector>
\ No newline at end of file
diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png
new file mode 100644
index 0000000..859900a
--- /dev/null
+++ b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_disabled.png
Binary files differ
diff --git a/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png b/core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_normal.png
similarity index 100%
rename from core/res/res/drawable/ic_btn_square_browser_zoom_page_overview.png
rename to core/res/res/drawable/ic_btn_square_browser_zoom_page_overview_normal.png
Binary files differ
diff --git a/core/res/res/drawable/status_bar_background.9.png b/core/res/res/drawable/status_bar_background.9.png
deleted file mode 100644
index fd754a8..0000000
--- a/core/res/res/drawable/status_bar_background.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable/status_bar_divider_shadow.9.png b/core/res/res/drawable/status_bar_background.png
similarity index 86%
copy from core/res/res/drawable/status_bar_divider_shadow.9.png
copy to core/res/res/drawable/status_bar_background.png
index ad58dbe..cd11166 100644
--- a/core/res/res/drawable/status_bar_divider_shadow.9.png
+++ b/core/res/res/drawable/status_bar_background.png
Binary files differ
diff --git a/core/res/res/drawable/status_bar_close_on.9.png b/core/res/res/drawable/status_bar_close_on.9.png
index e91e4fa..9cbd9fe 100644
--- a/core/res/res/drawable/status_bar_close_on.9.png
+++ b/core/res/res/drawable/status_bar_close_on.9.png
Binary files differ
diff --git a/core/res/res/drawable/status_bar_divider_shadow.9.png b/core/res/res/drawable/status_bar_header_background.9.png
similarity index 93%
rename from core/res/res/drawable/status_bar_divider_shadow.9.png
rename to core/res/res/drawable/status_bar_header_background.9.png
index ad58dbe..fa9a90c 100644
--- a/core/res/res/drawable/status_bar_divider_shadow.9.png
+++ b/core/res/res/drawable/status_bar_header_background.9.png
Binary files differ
diff --git a/core/res/res/drawable/status_bar_item_background_normal.9.png b/core/res/res/drawable/status_bar_item_background_normal.9.png
index 6b76740..b8e399d 100644
--- a/core/res/res/drawable/status_bar_item_background_normal.9.png
+++ b/core/res/res/drawable/status_bar_item_background_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable/statusbar_background.png b/core/res/res/drawable/statusbar_background.png
index 2d8aa7a..204d76a 100644
--- a/core/res/res/drawable/statusbar_background.png
+++ b/core/res/res/drawable/statusbar_background.png
Binary files differ
diff --git a/core/res/res/drawable/title_bar_portrait.9.png b/core/res/res/drawable/title_bar_portrait.9.png
new file mode 100644
index 0000000..482d82e
--- /dev/null
+++ b/core/res/res/drawable/title_bar_portrait.9.png
Binary files differ
diff --git a/core/res/res/layout/always_use_checkbox.xml b/core/res/res/layout/always_use_checkbox.xml
index 20fc403..5e6e388 100644
--- a/core/res/res/layout/always_use_checkbox.xml
+++ b/core/res/res/layout/always_use_checkbox.xml
@@ -16,7 +16,7 @@
 
 <!-- Check box that is displayed in the activity resolver UI for the user
      to make their selection the preferred activity. -->
-<RelativeLayout
+<LinearLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="fill_parent"
     android:layout_height="wrap_content"
@@ -27,7 +27,6 @@
         android:id="@+id/alwaysUse"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
         android:focusable="true"
         android:clickable="true" />
     
@@ -38,6 +37,5 @@
         android:textAppearance="?android:attr/textAppearanceSmall"
         android:paddingLeft="36dip"
         android:visibility="gone"
-        android:layout_below="@id/alwaysUse"
         android:text="@string/clearDefaultHintMsg" />
-</RelativeLayout>
+</LinearLayout>
diff --git a/core/res/res/layout/input_method.xml b/core/res/res/layout/input_method.xml
index a21bbe8..1a701e9 100644
--- a/core/res/res/layout/input_method.xml
+++ b/core/res/res/layout/input_method.xml
@@ -25,19 +25,28 @@
     android:orientation="vertical"
     >
 
-    <FrameLayout android:id="@android:id/extractArea"
-        android:layout_width="fill_parent"
-        android:layout_height="0px"
-        android:layout_weight="1"
-        android:visibility="gone">
-    </FrameLayout>
-    
-    <FrameLayout android:id="@android:id/candidatesArea"
+    <LinearLayout
+        android:id="@+id/fullscreenArea"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
-        android:visibility="invisible">
-    </FrameLayout>
-    
+        android:orientation="vertical"
+        >
+
+        <FrameLayout android:id="@android:id/extractArea"
+            android:layout_width="fill_parent"
+            android:layout_height="0px"
+            android:layout_weight="1"
+            android:visibility="gone">
+        </FrameLayout>
+        
+        <FrameLayout android:id="@android:id/candidatesArea"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:visibility="invisible">
+        </FrameLayout>
+
+    </LinearLayout>
+            
     <FrameLayout android:id="@android:id/inputArea"
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
diff --git a/core/res/res/layout/keyguard_screen_unlock_landscape.xml b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
index ba1640a..d0388a6 100644
--- a/core/res/res/layout/keyguard_screen_unlock_landscape.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_landscape.xml
@@ -114,10 +114,10 @@
         </FrameLayout>
     </LinearLayout>
 
-    <!--View
+    <View
          android:background="@android:drawable/code_lock_left"
          android:layout_width="2dip"
-         android:layout_height="fill_parent" /-->
+         android:layout_height="fill_parent" />
 
     <!-- right side: lock pattern -->
     <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
diff --git a/core/res/res/layout/keyguard_screen_unlock_portrait.xml b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
index f09c422..59cd7a3 100644
--- a/core/res/res/layout/keyguard_screen_unlock_portrait.xml
+++ b/core/res/res/layout/keyguard_screen_unlock_portrait.xml
@@ -53,18 +53,18 @@
             android:textSize="18sp"/>
     </LinearLayout>
 
-    <!--View
+    <View
          android:background="@android:drawable/code_lock_top"
          android:layout_width="fill_parent"
-         android:layout_height="2dip" /-->
+         android:layout_height="2dip" />
     <com.android.internal.widget.LockPatternView android:id="@+id/lockPattern"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          />
-    <!--View
+    <View
          android:background="@android:drawable/code_lock_bottom"
          android:layout_width="fill_parent"
-         android:layout_height="8dip" /-->
+         android:layout_height="8dip" />
 
     <!-- footer -->
     <FrameLayout
diff --git a/core/res/res/layout/screen_simple.xml b/core/res/res/layout/screen_simple.xml
index 62e737a..df511c6 100644
--- a/core/res/res/layout/screen_simple.xml
+++ b/core/res/res/layout/screen_simple.xml
@@ -22,7 +22,8 @@
 -->
 
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
-     android:id="@android:id/content"
-     android:fitsSystemWindows="true">
-</FrameLayout>
-
+    android:id="@android:id/content"
+    android:fitsSystemWindows="true"
+    android:foregroundInsidePadding="false"
+    android:foregroundGravity="fill_horizontal|top"
+    android:foreground="?android:attr/windowContentOverlay" />
\ No newline at end of file
diff --git a/core/res/res/layout/status_bar.xml b/core/res/res/layout/status_bar.xml
index 9a6b7e8..0bc0dac 100644
--- a/core/res/res/layout/status_bar.xml
+++ b/core/res/res/layout/status_bar.xml
@@ -97,7 +97,7 @@
         android:gravity="center_vertical|left"
         android:paddingLeft="6px"
         android:paddingRight="6px"
-        android:textColor="#ff000000"
+        android:textColor="?android:attr/textColorPrimaryInverse"
         android:background="@drawable/statusbar_background"
         />
 </com.android.server.status.StatusBarView>
diff --git a/core/res/res/layout/status_bar_expanded.xml b/core/res/res/layout/status_bar_expanded.xml
index a6a188e..fd9d26e 100644
--- a/core/res/res/layout/status_bar_expanded.xml
+++ b/core/res/res/layout/status_bar_expanded.xml
@@ -31,12 +31,13 @@
         android:paddingTop="3dp"
         android:paddingBottom="5dp"
         android:paddingRight="3dp"
-        android:background="@drawable/status_bar_divider_shadow"
+        android:background="@drawable/status_bar_header_background"
         >
         <LinearLayout
             android:layout_width="0dp"
             android:layout_height="wrap_content"
             android:layout_weight="1"
+            android:layout_marginTop="1dp"
             android:layout_marginLeft="5dp"
             android:layout_gravity="center_vertical"
             android:paddingBottom="1dp"
@@ -46,86 +47,99 @@
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
                     android:layout_gravity="center_vertical"
-                    android:textSize="18sp"
-                    android:textStyle="bold"
-                    android:textColor="#ff000000"
+                    android:textAppearance="?android:attr/textAppearanceLarge"
+                    android:textColor="?android:attr/textColorSecondaryInverse"
+                    android:paddingLeft="4dp"
                     />
                 <TextView android:id="@+id/spnLabel"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
-                    android:textSize="18sp"
-                    android:textStyle="bold"
-                    android:textColor="#ff000000"
-                    android:paddingBottom="1dp"
+                    android:layout_gravity="center_vertical"
+                    android:textAppearance="?android:attr/textAppearanceLarge"
+                    android:textColor="?android:attr/textColorSecondaryInverse"
+                    android:paddingLeft="4dp"
                     />
         </LinearLayout>
         <TextView android:id="@+id/clear_all_button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_gravity="center_vertical"
+            android:layout_marginTop="4dp"
+            android:layout_marginBottom="1dp"
             android:textSize="14sp"
             android:textColor="#ff000000"
             android:text="@string/status_bar_clear_all_button"
             style="?android:attr/buttonStyle"
+            android:paddingLeft="15dp"
+            android:paddingRight="15dp"
+            android:background="@drawable/btn_default_small"
             />
     </LinearLayout>
 
-
-    <!-- This view has the same background as the tracking view.  Normally it isn't shown,
-         except in the case where our copy of the close button is visible.  That button is
-         translucent.  Even though it moves up and down, it's only visible when it's aligned
-         at the bottom.
-    -->
-    <ScrollView
-        android:id="@+id/scroll"
-        android:layout_width="fill_parent"
+    <FrameLayout
+        android:layout_width="fill_parent" 
         android:layout_height="wrap_content"
-        android:layout_weight="1"
         >
-        <com.android.server.status.NotificationLinearLayout
-            android:id="@+id/notificationLinearLayout"
+        <ScrollView
+            android:id="@+id/scroll"
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
             android:layout_weight="1"
-            android:orientation="vertical"
+            android:fadingEdge="none"
             >
-            
-            <TextView android:id="@+id/noNotificationsTitle"
+            <com.android.server.status.NotificationLinearLayout
+                android:id="@+id/notificationLinearLayout"
                 android:layout_width="fill_parent"
                 android:layout_height="wrap_content"
-                android:background="#ff888888"
-                android:paddingLeft="5dp"
-                android:textAppearance="@style/TextAppearance.StatusBarTitle"
-                android:text="@string/status_bar_no_notifications_title"
-                />
-
-            <TextView android:id="@+id/ongoingTitle"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:background="#ff888888"
-                android:paddingLeft="5dp"
-                android:textAppearance="@style/TextAppearance.StatusBarTitle"
-                android:text="@string/status_bar_ongoing_events_title"
-                />
-            <LinearLayout android:id="@+id/ongoingItems"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
+                android:layout_weight="1"
                 android:orientation="vertical"
-                />
+                >
+                
+                <TextView android:id="@+id/noNotificationsTitle"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/title_bar_portrait"
+                    android:paddingLeft="5dp"
+                    android:textAppearance="@style/TextAppearance.StatusBarTitle"
+                    android:text="@string/status_bar_no_notifications_title"
+                    />
 
-            <TextView android:id="@+id/latestTitle"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:background="#ff888888"
-                android:paddingLeft="5dp"
-                android:textAppearance="@style/TextAppearance.StatusBarTitle"
-                android:text="@string/status_bar_latest_events_title"
-                />
-            <LinearLayout android:id="@+id/latestItems"
-                android:layout_width="fill_parent"
-                android:layout_height="wrap_content"
-                android:orientation="vertical"
-                />
-        </com.android.server.status.NotificationLinearLayout>
-    </ScrollView>
+                <TextView android:id="@+id/ongoingTitle"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/title_bar_portrait"
+                    android:paddingLeft="5dp"
+                    android:textAppearance="@style/TextAppearance.StatusBarTitle"
+                    android:text="@string/status_bar_ongoing_events_title"
+                    />
+                <LinearLayout android:id="@+id/ongoingItems"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical"
+                    />
+
+                <TextView android:id="@+id/latestTitle"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:background="@drawable/title_bar_portrait"
+                    android:paddingLeft="5dp"
+                    android:textAppearance="@style/TextAppearance.StatusBarTitle"
+                    android:text="@string/status_bar_latest_events_title"
+                    />
+                <LinearLayout android:id="@+id/latestItems"
+                    android:layout_width="fill_parent"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical"
+                    />
+            </com.android.server.status.NotificationLinearLayout>
+        </ScrollView>
+
+        <ImageView
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:src="@drawable/title_bar_shadow"
+            android:scaleType="fitXY"
+        />
+
+    </FrameLayout>
 </com.android.server.status.ExpandedView>
diff --git a/core/res/res/layout/status_bar_tracking.xml b/core/res/res/layout/status_bar_tracking.xml
index 661ce86..aa3b733 100644
--- a/core/res/res/layout/status_bar_tracking.xml
+++ b/core/res/res/layout/status_bar_tracking.xml
@@ -20,13 +20,12 @@
     android:visibility="gone"
     android:focusable="true"
     android:descendantFocusability="afterDescendants"
-    android:background="@drawable/status_bar_background"
     android:paddingBottom="0px"
     android:paddingLeft="0px"
     android:paddingRight="0px"
     >
 
-    <View
+    <com.android.server.status.TrackingPatternView
         android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_weight="1"
@@ -37,11 +36,6 @@
         android:layout_height="wrap_content"
         android:orientation="vertical"
         >
-
-        <View
-            android:layout_width="fill_parent"
-            android:layout_height="5dp"
-            />
         <ImageView
             android:layout_width="fill_parent"
             android:layout_height="wrap_content"
diff --git a/core/res/res/values-cs/strings.xml b/core/res/res/values-cs/strings.xml
index 13aca371..27cefb0 100644
--- a/core/res/res/values-cs/strings.xml
+++ b/core/res/res/values-cs/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Ve výchozím nastavení není identifikace volajícího omezena. Příští hovor: Neomezeno"</string>
     <string name="serviceNotProvisioned">"Služba není zřízena."</string>
     <string name="CLIRPermanent">"Nelze změnit nastavení identifikace volajícího."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Hlas"</string>
     <string name="serviceClassData">"Data"</string>
     <string name="serviceClassFAX">"FAX"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Umožňuje povolit či zakázat aktualizace polohy prostřednictvím bezdrátového připojení. Aplikace toto nastavení obvykle nepoužívají."</string>
     <string name="permlab_checkinProperties">"přístup k vlastnostem Checkin"</string>
     <string name="permdesc_checkinProperties">"Umožňuje čtení i zápis vlastností nahraných službou Checkin. Běžné aplikace toto nastavení obvykle nevyužívají."</string>
-    <string name="permlab_bindGadget">"zvolit gadgety"</string>
-    <string name="permdesc_bindGadget">"Umožňuje aplikaci sdělit systému, které aplikace mohou použít které gadgety. Aplikace s tímto oprávněním mohou zpřístupnit osobní údaje jiným aplikacím. Není určeno pro normální aplikace."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"změny stavu telefonu"</string>
     <string name="permdesc_modifyPhoneState">"Umožňuje aplikaci ovládat telefonní funkce zařízení. Aplikace s tímto oprávněním může přepínat sítě nebo zapnout či vypnout bezdrátové připojení telefonu bez vašeho svolení."</string>
     <string name="permlab_readPhoneState">"zjistit stav telefonu"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Prosím vložte kartu SIM."</string>
     <string name="lockscreen_network_locked_message">"Síť je blokována"</string>
     <string name="lockscreen_sim_puk_locked_message">"Karta SIM je zablokována pomocí kódu PUK."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Prosím kontaktujte podporu zákazníků."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"Karta SIM je zablokována."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Odblokování karty SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"<xliff:g id="NUMBER_0">%d</xliff:g>krát jste nakreslili nesprávné bezpečnostní gesto. "\n\n"Opakujte prosím akci za <xliff:g id="NUMBER_1">%d</xliff:g> s."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Sekundy zbývající do dalšího pokusu: <xliff:g id="NUMBER">%d</xliff:g>."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Zapomněli jste gesto?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Gesta: Příliš mnoho pokusů"</string>
-    <string name="lockscreen_glogin_instructions">"Chcete-li telefon odemknout,"\n"přihlaste se pomocí svého účtu Google"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Uživatelské jméno (e-mail)"</string>
     <string name="lockscreen_glogin_password_hint">"Heslo"</string>
     <string name="lockscreen_glogin_submit_button">"Přihlásit se"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Měsíčně"</string>
     <string name="yearly">"Ročně"</string>
     <string name="VideoView_error_title">"Video nelze přehrát"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Toto video bohužel nelze přehrát."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"dop."</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"poledne"</string>
     <string name="Noon">"Poledne"</string>
     <string name="midnight">"půlnoc"</string>
     <string name="Midnight">"Půlnoc"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"neděle"</string>
     <string name="day_of_week_long_monday">"pondělí"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index cda8cbc..8619084 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Anrufer-ID ist standardmäßig nicht beschränkt. Nächster Anruf: Nicht beschränkt"</string>
     <string name="serviceNotProvisioned">"Dienst nicht eingerichtet."</string>
     <string name="CLIRPermanent">"Die Einstellung für die Anrufer-ID kann nicht geändert werden."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Sprachnotiz"</string>
     <string name="serviceClassData">"Daten"</string>
     <string name="serviceClassFAX">"FAX"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Ermöglicht die Aktivierung/Deaktivierung der Radio-Benachrichtigungen über Standort-Updates. Nicht für normale Anwendungen vorgesehen."</string>
     <string name="permlab_checkinProperties">"Auf Check-In-Eigenschaften zugreifen"</string>
     <string name="permdesc_checkinProperties">"Ermöglicht den Schreib-/Lesezugriff auf vom Check-In-Service hochgeladene Elemente. Nicht für normale Anwendungen vorgesehen."</string>
-    <string name="permlab_bindGadget">"Gadgets auswählen"</string>
-    <string name="permdesc_bindGadget">"Bei dieser Option meldet die Anwendung dem System, welche Gadgets von welcher Anwendung verwendet werden können. Mit dieser Genehmigung können Anwendungen anderen Anwendungen Zugriff auf persönliche Daten geben. Nicht für normale Anwendungen vorgesehen."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"Telefonstatus ändern"</string>
     <string name="permdesc_modifyPhoneState">"Ermöglicht einer Anwendung, die Telefonfunktionen des Gerätes zu steuern. Eine Anwendung mit dieser Berechtigung kann unter anderem das Netzwerk wechseln oder das Radio des Telefons ein- und ausschalten, ohne Sie darüber zu informieren."</string>
     <string name="permlab_readPhoneState">"Telefonstatus lesen"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Bitte legen Sie eine SIM-Karte ein."</string>
     <string name="lockscreen_network_locked_message">"Netzwerk gesperrt"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM-Karte ist gesperrt. PUK-Eingabe erforderlich."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Wenden Sie sich an den Kunden-Support."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM-Karte ist gesperrt."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-Karte wird entsperrt..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Sie haben Ihr Entsperrungsmuster <xliff:g id="NUMBER_0">%d</xliff:g>-mal falsch gezeichnet. "\n\n"Versuchen Sie es in <xliff:g id="NUMBER_1">%d</xliff:g> Sekunden erneut."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Versuchen Sie es in <xliff:g id="NUMBER">%d</xliff:g> Sekunden erneut."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Muster vergessen?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Zu viele Versuche!"</string>
-    <string name="lockscreen_glogin_instructions">"Melden Sie sich zum Entsperren"\n"mit Ihrem Google-Konto an."</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Nutzername (E-Mail)"</string>
     <string name="lockscreen_glogin_password_hint">"Passwort"</string>
     <string name="lockscreen_glogin_submit_button">"Anmelden"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Monatlich"</string>
     <string name="yearly">"Jährlich"</string>
     <string name="VideoView_error_title">"Video kann nicht wiedergegeben werden."</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Dieses Video kann leider nicht abgespielt werden."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"AM"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"Mittag"</string>
     <string name="Noon">"Mittag"</string>
     <string name="midnight">"Mitternacht"</string>
     <string name="Midnight">"Mitternacht"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"Sonntag"</string>
     <string name="day_of_week_long_monday">"Montag"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-es/strings.xml b/core/res/res/values-es/strings.xml
index 495f8aa..30061e2 100644
--- a/core/res/res/values-es/strings.xml
+++ b/core/res/res/values-es/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"El ID de emisor presenta el valor predeterminado de no restringido. Siguiente llamada: No restringido"</string>
     <string name="serviceNotProvisioned">"El servicio no se suministra."</string>
     <string name="CLIRPermanent">"El ID del emisor no se puede modificar."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Voz"</string>
     <string name="serviceClassData">"Datos"</string>
     <string name="serviceClassFAX">"FAX"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Permite habilitar/inhabilitar las notificaciones de actualización de la señal móvil. No está destinado al uso por parte de aplicaciones normales."</string>
     <string name="permlab_checkinProperties">"acceder a propiedades de registro"</string>
     <string name="permdesc_checkinProperties">"Permite el acceso de lectura/escritura a las propiedades cargadas por el servicio de registro. No está destinado al uso por parte de aplicaciones normales."</string>
-    <string name="permlab_bindGadget">"seleccionar gadgets"</string>
-    <string name="permdesc_bindGadget">"Permite a la aplicación indicar al sistema qué gadgets puede utilizar cada aplicación. Con este permiso, las aplicaciones pueden permitir a otras aplicaciones acceder a datos personales. No está destinado al uso por parte de aplicaciones normales."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"modificar estado del teléfono"</string>
     <string name="permdesc_modifyPhoneState">"Permite que la aplicación controle las funciones de teléfono del dispositivo. Una aplicación con este permiso puede cambiar redes, activar y desactivar la señal móvil, etc., sin necesidad de notificar al usuario."</string>
     <string name="permlab_readPhoneState">"leer el estado del teléfono"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Inserta una tarjeta SIM."</string>
     <string name="lockscreen_network_locked_message">"Bloqueada para la red"</string>
     <string name="lockscreen_sim_puk_locked_message">"La tarjeta SIM está bloqueada con el código PUK."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Ponte en contacto con el servicio de atención al cliente."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"La tarjeta SIM está bloqueada."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Desbloqueando tarjeta SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Has realizado <xliff:g id="NUMBER_0">%d</xliff:g> intentos fallidos de creación de un patrón de desbloqueo. "\n\n"Inténtalo de nuevo dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Espera <xliff:g id="NUMBER">%d</xliff:g> segundos y vuelve a intentarlo."</string>
     <string name="lockscreen_forgot_pattern_button_text">"¿Has olvidado el patrón?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Se han realizado demasiados intentos incorrectos de creación del patrón."</string>
-    <string name="lockscreen_glogin_instructions">"Para desbloquear el teléfono,"\n"accede a tu cuenta de Google"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Nombre de usuario (correo electrónico)"</string>
     <string name="lockscreen_glogin_password_hint">"Contraseña"</string>
     <string name="lockscreen_glogin_submit_button">"Acceder"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Mensualmente"</string>
     <string name="yearly">"Anualmente"</string>
     <string name="VideoView_error_title">"No se puede reproducir el vídeo."</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Este vídeo no se puede reproducir."</string>
     <string name="VideoView_error_button">"Aceptar"</string>
     <string name="am">"a.m."</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' de '<xliff:g id="MONTH">MMM</xliff:g>' de '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"mediodía"</string>
     <string name="Noon">"Mediodía"</string>
     <string name="midnight">"medianoche"</string>
     <string name="Midnight">"Medianoche"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"Domingo"</string>
     <string name="day_of_week_long_monday">"Lunes"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-fr/strings.xml b/core/res/res/values-fr/strings.xml
index 8bd064d..b4b9318 100644
--- a/core/res/res/values-fr/strings.xml
+++ b/core/res/res/values-fr/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Par défaut, les identifiants d\'appelant ne sont pas restreints. Appel suivant : non restreint"</string>
     <string name="serviceNotProvisioned">"Ce service n\'est pas pris en charge."</string>
     <string name="CLIRPermanent">"Le paramètre Identifiant d\'appelant ne peut pas être modifié."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Voix"</string>
     <string name="serviceClassData">"Données"</string>
     <string name="serviceClassFAX">"Télécopie"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Permet l\'activation/la désactivation des notifications de mises à jour de la position géographique provenant de la radio. Les applications normales n\'utilisent pas cette fonctionnalité."</string>
     <string name="permlab_checkinProperties">"Accès aux propriétés d\'enregistrement"</string>
     <string name="permdesc_checkinProperties">"Permet un accès en lecture/écriture à des propriétés envoyées par le service d\'inscription. Les applications normales n\'utilisent pas cette fonctionnalité."</string>
-    <string name="permlab_bindGadget">"choisir les gadgets"</string>
-    <string name="permdesc_bindGadget">"Permet à l\'application de signaler au système quels gadgets peuvent être utilisés pour quelle application. Cette autorisation permet aux applications de fournir l\'accès à des données personnelles à d\'autres applications. Cette option n\'est pas utilisée par les applications standard."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"Modification de l\'état du téléphone"</string>
     <string name="permdesc_modifyPhoneState">"Permet à une application de contrôler les fonctionnalités téléphoniques de l\'appareil. Une application bénéficiant de cette autorisation peut changer de réseau, éteindre et allumer la radio du téléphone, etc., sans vous en avertir."</string>
     <string name="permlab_readPhoneState">"Lecture de l\'état du téléphone"</string>
@@ -403,17 +415,19 @@
     <string name="lockscreen_missing_sim_message_short">"Aucune carte SIM n\'a été trouvée."</string>
     <string name="lockscreen_missing_sim_message">"Aucune carte SIM n\'est insérée dans le téléphone."</string>
     <string name="lockscreen_missing_sim_instructions">"Insérez une carte SIM."</string>
-    <string name="lockscreen_network_locked_message">"Réseau bloqué"</string>
+    <string name="lockscreen_network_locked_message">"Réseau verrouillé"</string>
     <string name="lockscreen_sim_puk_locked_message">"La carte SIM est verrouillée par code PUK."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Veuillez contacter l\'assistance clientèle."</string>
-    <string name="lockscreen_sim_locked_message">"La carte SIM est bloquée."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
+    <string name="lockscreen_sim_locked_message">"Téléphone verrouillé"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Déblocage de la carte SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Vous avez mal reproduit le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. "\n\n"Veuillez réessayer dans <xliff:g id="NUMBER_1">%d</xliff:g> secondes."</string>
     <string name="lockscreen_failed_attempts_almost_glogin">"Vous avez mal saisi le motif de déverrouillage <xliff:g id="NUMBER_0">%d</xliff:g> fois. Au bout de <xliff:g id="NUMBER_1">%d</xliff:g> tentatives supplémentaires, vous devrez débloquer votre téléphone à l\'aide de votre identifiant Google."\n\n"Merci de réessayer dans <xliff:g id="NUMBER_2">%d</xliff:g> secondes."</string>
     <string name="lockscreen_too_many_failed_attempts_countdown">"Réessayez dans <xliff:g id="NUMBER">%d</xliff:g> secondes."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Motif oublié ?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Trop de tentatives de motif !"</string>
-    <string name="lockscreen_glogin_instructions">"Pour débloquer votre téléphone,"\n"connectez-vous à l\'aide de votre compte Google"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Nom d\'utilisateur (e-mail)"</string>
     <string name="lockscreen_glogin_password_hint">"Mot de passe"</string>
     <string name="lockscreen_glogin_submit_button">"Se connecter"</string>
@@ -551,6 +565,8 @@
     <string name="monthly">"Tous les mois"</string>
     <string name="yearly">"Tous les ans"</string>
     <string name="VideoView_error_title">"Échec de la lecture de la vidéo"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Désolé, impossible de lire cette vidéo."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"AM"</string>
@@ -572,13 +588,13 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"midi"</string>
     <string name="Noon">"Midi"</string>
     <string name="midnight">"minuit"</string>
     <string name="Midnight">"Minuit"</string>
     <string name="month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g>"</string>
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -613,7 +629,7 @@
     <!-- no translation found for abbrev_month_year (5966980891147982768) -->
     <skip />
     <string name="abbrev_month_day">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%b</xliff:g>"</string>
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"dimanche"</string>
     <string name="day_of_week_long_monday">"lundi"</string>
@@ -806,6 +822,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-it/strings.xml b/core/res/res/values-it/strings.xml
index b4cf458..f987ae2 100644
--- a/core/res/res/values-it/strings.xml
+++ b/core/res/res/values-it/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"ID chiamante generalmente non limitato. Prossima chiamata: non limitato"</string>
     <string name="serviceNotProvisioned">"Servizio non fornito."</string>
     <string name="CLIRPermanent">"Impossibile modificare l\'impostazione dell\'ID del chiamante."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Voce"</string>
     <string name="serviceClassData">"Dati"</string>
     <string name="serviceClassFAX">"FAX"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Consente l\'attivazione/disattivazione delle notifiche di aggiornamento della posizione dal segnale cellulare. Da non usare per normali applicazioni."</string>
     <string name="permlab_checkinProperties">"accesso a proprietà di archiviazione"</string>
     <string name="permdesc_checkinProperties">"Consente l\'accesso di lettura/scrittura alle proprietà caricate dal servizio di archiviazione. Da non usare per normali applicazioni."</string>
-    <string name="permlab_bindGadget">"scegliere gadget"</string>
-    <string name="permdesc_bindGadget">"Consente all\'applicazione di indicare al sistema quali gadget possono essere utilizzati e da quale applicazione. Con questa autorizzazione, le applicazioni possono consentire ad altre applicazioni di accedere a dati personali. Da non usare per normali applicazioni."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"modifica stato del telefono"</string>
     <string name="permdesc_modifyPhoneState">"Consente all\'applicazione di controllare le funzioni telefoniche del dispositivo. Un\'applicazione con questa autorizzazione può cambiare rete, attivare e disattivare il segnale cellulare e così via, senza alcuna notifica."</string>
     <string name="permlab_readPhoneState">"lettura stato del telefono"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Inserisci una SIM."</string>
     <string name="lockscreen_network_locked_message">"Rete bloccata"</string>
     <string name="lockscreen_sim_puk_locked_message">"La SIM è bloccata tramite PUK."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Contatta il servizio clienti."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"La SIM è bloccata."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Sblocco SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"<xliff:g id="NUMBER_0">%d</xliff:g> tentativi di inserimento della sequenza di sblocco. "\n\n"Riprova fra <xliff:g id="NUMBER_1">%d</xliff:g> secondi."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Riprova fra <xliff:g id="NUMBER">%d</xliff:g> secondi."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Hai dimenticato la sequenza?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Troppi tentativi di inserimento della sequenza."</string>
-    <string name="lockscreen_glogin_instructions">"Per sbloccare,"\n"accedi tramite il tuo account Google"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Nome utente (email)"</string>
     <string name="lockscreen_glogin_password_hint">"Password"</string>
     <string name="lockscreen_glogin_submit_button">"Accedi"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Mensilmente"</string>
     <string name="yearly">"Annualmente"</string>
     <string name="VideoView_error_title">"Impossibile riprodurre il video"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Spiacenti. Impossibile riprodurre il video."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"AM"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"mezzogiorno"</string>
     <string name="Noon">"Mezzogiorno"</string>
     <string name="midnight">"mezzanotte"</string>
     <string name="Midnight">"Mezzanotte"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"Domenica"</string>
     <string name="day_of_week_long_monday">"Lunedì"</string>
@@ -725,7 +741,7 @@
     <string name="anr_activity_process">"L\'attività <xliff:g id="ACTIVITY">%1$s</xliff:g> (nel processo <xliff:g id="PROCESS">%2$s</xliff:g>) non risponde."</string>
     <string name="anr_application_process">"L\'applicazione <xliff:g id="APPLICATION">%1$s</xliff:g> (nel processo <xliff:g id="PROCESS">%2$s</xliff:g>) non risponde."</string>
     <string name="anr_process">"Il processo <xliff:g id="PROCESS">%1$s</xliff:g> non risponde."</string>
-    <string name="force_close">"Forza chiusura"</string>
+    <string name="force_close">"Termina"</string>
     <string name="wait">"Attendi"</string>
     <string name="debug">"Debug"</string>
     <string name="sendText">"Seleziona un\'azione per il testo"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ja/strings.xml b/core/res/res/values-ja/strings.xml
index 2a21bd3..25d906f 100644
--- a/core/res/res/values-ja/strings.xml
+++ b/core/res/res/values-ja/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"既定: 発信者番号通知、次の発信: 通知"</string>
     <string name="serviceNotProvisioned">"提供可能なサービスがありません。"</string>
     <string name="CLIRPermanent">"発信者番号の設定は変更できません。"</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"音声"</string>
     <string name="serviceClassData">"データ"</string>
     <string name="serviceClassFAX">"FAX"</string>
@@ -69,7 +79,7 @@
     <string name="cfTemplateRegisteredTime">"<xliff:g id="BEARER_SERVICE_CODE">{0}</xliff:g>:転送できません"</string>
     <string name="httpErrorOk">"OK"</string>
     <string name="httpError">"ウェブページにエラーがあります。"</string>
-    <string name="httpErrorLookup">"URLが見つかりませんでした。"</string>
+    <string name="httpErrorLookup">"URLが見つかりません。"</string>
     <string name="httpErrorUnsupportedAuthScheme">"このサイトの認証方式には対応していません。"</string>
     <string name="httpErrorAuth">"認証できませんでした。"</string>
     <string name="httpErrorProxyAuth">"プロキシサーバーを使用した認証に失敗しました。"</string>
@@ -279,15 +289,17 @@
     <string name="permlab_hardware_test">"ハードウェアのテスト"</string>
     <string name="permdesc_hardware_test">"ハードウェアのテストのためにさまざまな周辺機器を制御することをアプリケーションに許可します。"</string>
     <string name="permlab_callPhone">"電話番号発信"</string>
-    <string name="permdesc_callPhone">"アプリケーションが電話を自動発信することを許可します。悪意のあるアプリケーションが意図しない電話をかけて料金が発生する恐れがあります。緊急呼への発信は許可しません。"</string>
+    <string name="permdesc_callPhone">"電話番号の自動発信をアプリケーションに許可します。悪意のあるアプリケーションが意図しない電話をかけて料金が発生する恐れがあります。緊急通報への発信は許可しません。"</string>
     <string name="permlab_callPrivileged">"電話番号発信"</string>
-    <string name="permdesc_callPrivileged">"緊急呼を含めあらゆる電話番号に自動発信することをアプリケーションに許可します。悪意のあるアプリケーションが緊急サービスに不正な通報をする恐れがあります。"</string>
+    <string name="permdesc_callPrivileged">"緊急通報を含めあらゆる電話番号に自動発信することをアプリケーションに許可します。悪意のあるアプリケーションが緊急サービスに不正な通報をする恐れがあります。"</string>
     <string name="permlab_locationUpdates">"位置情報の更新通知"</string>
     <string name="permdesc_locationUpdates">"無線通信からの位置更新通知を有効/無効にすることを許可します。通常のアプリケーションでは使用しません。"</string>
     <string name="permlab_checkinProperties">"チェックインプロパティへのアクセス"</string>
     <string name="permdesc_checkinProperties">"チェックインサービスがアップロードしたプロパティへの読み書きを許可します。通常のアプリケーションでは使用しません。"</string>
-    <string name="permlab_bindGadget">"ガジェットの選択"</string>
-    <string name="permdesc_bindGadget">"特定のアプリケーションで使用可能なガジェットをシステムに指定することをアプリケーションに許可します。この許可を受けたアプリケーションは、他のアプリケーションに個人データへのアクセスを許可することができます。通常のアプリケーションでは使用しません。"</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"端末ステータスの変更"</string>
     <string name="permdesc_modifyPhoneState">"端末の電話機能のコントロールをアプリケーションに許可します。アプリケーションは、ネットワークの切り替え、携帯電話の無線通信のオン/オフなどを通知せずに行うことができます。"</string>
     <string name="permlab_readPhoneState">"端末ステータスの読み取り"</string>
@@ -316,7 +328,7 @@
     <string name="permdesc_writeApnSettings">"APNのプロキシやポートなどのAPN設定の変更をアプリケーションに許可します。"</string>
     <string name="permlab_changeNetworkState">"ネットワーク接続の変更"</string>
     <string name="permdesc_changeNetworkState">"ネットワークの接続状態の変更をアプリケーションに許可します。"</string>
-    <string name="permlab_changeBackgroundDataSetting">"バックグラウンドデータ使用の設定の変更"</string>
+    <string name="permlab_changeBackgroundDataSetting">"バックグラウンドデータ使用設定の変更"</string>
     <string name="permdesc_changeBackgroundDataSetting">"バックグラウンドデータ使用の設定の変更をアプリケーションに許可します。"</string>
     <string name="permlab_accessWifiState">"Wi-Fi状態の表示"</string>
     <string name="permdesc_accessWifiState">"Wi-Fi状態に関する情報の表示をアプリケーションに許可します。"</string>
@@ -388,13 +400,13 @@
     <string name="keyguard_password_enter_pin_code">"PINコードを入力"</string>
     <string name="keyguard_password_wrong_pin_code">"PINコードが正しくありません。"</string>
     <string name="keyguard_label_text">"ロックを解除するにはMENU、0キーの順に押します。"</string>
-    <string name="emergency_call_dialog_number_for_display">"緊急呼番号"</string>
+    <string name="emergency_call_dialog_number_for_display">"緊急通報番号"</string>
     <string name="lockscreen_carrier_default">"(サービス登録なし)"</string>
     <string name="lockscreen_screen_locked">"画面ロック中"</string>
-    <string name="lockscreen_instructions_when_pattern_enabled">"MENUキーでロック解除(または緊急呼)"</string>
+    <string name="lockscreen_instructions_when_pattern_enabled">"MENUキーでロック解除(または緊急通報)"</string>
     <string name="lockscreen_instructions_when_pattern_disabled">"MENUキーでロック解除"</string>
     <string name="lockscreen_pattern_instructions">"ロックを解除するパターンを入力"</string>
-    <string name="lockscreen_emergency_call">"緊急呼"</string>
+    <string name="lockscreen_emergency_call">"緊急通報"</string>
     <string name="lockscreen_pattern_correct">"一致しました"</string>
     <string name="lockscreen_pattern_wrong">"やり直してください"</string>
     <!-- no translation found for lockscreen_plugged_in (613343852842944435) -->
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"SIMカードを挿入してください。"</string>
     <string name="lockscreen_network_locked_message">"ネットワークがロックされました"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIMカードはPUKでロックされています。"</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"お客様サポートにお問い合わせください。"</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIMカードはロックされています。"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"SIMカードのロック解除中..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"ロック解除のパターンは<xliff:g id="NUMBER_0">%d</xliff:g>回とも正しく指定されていません。"\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>秒後にもう一度指定してください。"</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g>秒後にやり直してください。"</string>
     <string name="lockscreen_forgot_pattern_button_text">"パターンを忘れた場合"</string>
     <string name="lockscreen_glogin_too_many_attempts">"パターンのエラーが多すぎます"</string>
-    <string name="lockscreen_glogin_instructions">"ロックを解除するには、"\n"Googleアカウントでログインしてください。"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"ユーザー名 (メール)"</string>
     <string name="lockscreen_glogin_password_hint">"パスワード"</string>
     <string name="lockscreen_glogin_submit_button">"ログイン"</string>
@@ -427,7 +441,7 @@
     <skip />
     <string name="status_bar_clear_all_button">"通知を消去"</string>
     <string name="status_bar_no_notifications_title">"通知なし"</string>
-    <string name="status_bar_ongoing_events_title">"継続中"</string>
+    <string name="status_bar_ongoing_events_title">"操作中"</string>
     <string name="status_bar_latest_events_title">"通知"</string>
     <!-- no translation found for battery_status_text_percent_format (7660311274698797147) -->
     <skip />
@@ -441,7 +455,7 @@
     <string name="factorytest_reboot">"再起動"</string>
     <string name="js_dialog_title">"ページ「<xliff:g id="TITLE">%s</xliff:g>」の記述:"</string>
     <string name="js_dialog_title_default">"JavaScript"</string>
-    <string name="js_dialog_before_unload">"このページから移動しますか?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"続行する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。"</string>
+    <string name="js_dialog_before_unload">"このページから移動しますか?"\n\n"<xliff:g id="MESSAGE">%s</xliff:g>"\n\n"移動する場合は[OK]、今のページに残る場合は[キャンセル]を選択してください。"</string>
     <string name="save_password_label">"確認"</string>
     <string name="save_password_message">"このパスワードをブラウザで保存しますか?"</string>
     <string name="save_password_notnow">"今は保存しない"</string>
@@ -498,7 +512,7 @@
   </plurals>
   <plurals name="abbrev_num_minutes_ago">
     <item quantity="one">"1分前"</item>
-    <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g>分後"</item>
+    <item quantity="other">"<xliff:g id="COUNT">%d</xliff:g>分前"</item>
   </plurals>
   <plurals name="abbrev_num_hours_ago">
     <item quantity="one">"1時間前"</item>
@@ -552,6 +566,8 @@
     <string name="monthly">"毎月"</string>
     <string name="yearly">"毎年"</string>
     <string name="VideoView_error_title">"動画を再生できません"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"この動画は再生できません。"</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"AM"</string>
@@ -565,22 +581,22 @@
     <string name="time_wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g><xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="wday_date">"<xliff:g id="DATE">%3$s</xliff:g><xliff:g id="WEEKDAY">%2$s</xliff:g>"</string>
     <string name="time_date">"<xliff:g id="DATE">%3$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
-    <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g>、<xliff:g id="TIME">%2$s</xliff:g>"</string>
-    <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g>、<xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="date_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
+    <string name="relative_time">"<xliff:g id="DATE">%1$s</xliff:g> <xliff:g id="TIME">%2$s</xliff:g>"</string>
     <string name="time_wday">"<xliff:g id="WEEKDAY">%2$s</xliff:g>、<xliff:g id="TIME_RANGE">%1$s</xliff:g>"</string>
     <string name="full_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'/'<xliff:g id="MONTH">MMMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>"</string>
     <string name="full_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>'年'<xliff:g id="MONTH">MMMM</xliff:g>'月'<xliff:g id="DAY">d</xliff:g>'日'"</string>
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>'年'"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'/'<xliff:g id="MONTH">MMM</xliff:g>'/'<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"正午"</string>
     <string name="Noon">"正午"</string>
     <string name="midnight">"午前0時"</string>
     <string name="Midnight">"午前0時"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>年<xliff:g id="MONTH">%B</xliff:g><xliff:g id="DAY">%-d</xliff:g>日"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"日曜日"</string>
     <string name="day_of_week_long_monday">"月曜日"</string>
@@ -632,20 +648,20 @@
     <string name="day_of_week_medium_thursday">"(木)"</string>
     <string name="day_of_week_medium_friday">"(金)"</string>
     <string name="day_of_week_medium_saturday">"(土)"</string>
-    <string name="day_of_week_short_sunday">"(日)"</string>
-    <string name="day_of_week_short_monday">"(月)"</string>
-    <string name="day_of_week_short_tuesday">"(火)"</string>
-    <string name="day_of_week_short_wednesday">"(水)"</string>
-    <string name="day_of_week_short_thursday">"(木)"</string>
-    <string name="day_of_week_short_friday">"(金)"</string>
-    <string name="day_of_week_short_saturday">"(土)"</string>
-    <string name="day_of_week_shorter_sunday">"(日)"</string>
+    <string name="day_of_week_short_sunday">"日"</string>
+    <string name="day_of_week_short_monday">"月"</string>
+    <string name="day_of_week_short_tuesday">"火"</string>
+    <string name="day_of_week_short_wednesday">"水"</string>
+    <string name="day_of_week_short_thursday">"木"</string>
+    <string name="day_of_week_short_friday">"金"</string>
+    <string name="day_of_week_short_saturday">"土"</string>
+    <string name="day_of_week_shorter_sunday">"日"</string>
     <string name="day_of_week_shorter_monday">"月"</string>
-    <string name="day_of_week_shorter_tuesday">"(火)"</string>
+    <string name="day_of_week_shorter_tuesday">"火"</string>
     <string name="day_of_week_shorter_wednesday">"水"</string>
-    <string name="day_of_week_shorter_thursday">"(木)"</string>
+    <string name="day_of_week_shorter_thursday">"木"</string>
     <string name="day_of_week_shorter_friday">"金"</string>
-    <string name="day_of_week_shorter_saturday">"(土)"</string>
+    <string name="day_of_week_shorter_saturday">"土"</string>
     <string name="day_of_week_shortest_sunday">"日"</string>
     <string name="day_of_week_shortest_monday">"月"</string>
     <string name="day_of_week_shortest_tuesday">"火"</string>
@@ -712,7 +728,7 @@
     <string name="dialog_alert_title">"注意"</string>
     <string name="capital_on">"オン"</string>
     <string name="capital_off">"オフ"</string>
-    <string name="whichApplication">"操作の完了に使用"</string>
+    <string name="whichApplication">"アプリケーションを選択"</string>
     <string name="alwaysUse">"常にこの操作で使用する"</string>
     <string name="clearDefaultHintMsg">"ホームの[設定]&gt;[アプリケーション]&gt;[アプリケーションの管理]でデフォルト設定をクリアします。"</string>
     <string name="chooseActivity">"操作の選択"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ko/strings.xml b/core/res/res/values-ko/strings.xml
index 8fc7d12..faa1267 100644
--- a/core/res/res/values-ko/strings.xml
+++ b/core/res/res/values-ko/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"발신자 번호가 기본적으로 제한되지 않음으로 설정됩니다. 다음 통화: 제한되지 않음"</string>
     <string name="serviceNotProvisioned">"서비스가 준비되지 않았습니다."</string>
     <string name="CLIRPermanent">"발신자 번호 설정을 변경할 수 없습니다."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"음성"</string>
     <string name="serviceClassData">"데이터"</string>
     <string name="serviceClassFAX">"팩스"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"무선의 위치 업데이트 알림을 활성화하거나 비활성화할 수 있습니다. 일반 응용프로그램에서는 사용하지 않습니다."</string>
     <string name="permlab_checkinProperties">"체크인 속성 액세스"</string>
     <string name="permdesc_checkinProperties">"체크인 서비스에서 업로드한 속성에 대한 읽기/쓰기 액세스를 허용합니다. 일반 응용프로그램에서는 사용하지 않습니다."</string>
-    <string name="permlab_bindGadget">"가젯 선택"</string>
-    <string name="permdesc_bindGadget">"어느 응용프로그램이 어느 가젯을 사용할 수 있는지 시스템에 알려 주는 권한을 본 응용프로그램에 부여합니다. 이 권한을 사용하면 응용프로그램이 개인 데이터에 대한 액세스 권한을 다른 응용프로그램에 제공할 수 있습니다. 일반 응용프로그램은 이 권한을 사용할 수 없습니다."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"전화기 상태 수정"</string>
     <string name="permdesc_modifyPhoneState">"응용프로그램이 장치의 전화 기능을 제어할 수 있습니다. 이 권한을 갖는 응용프로그램은 사용자에게 알리지 않고 네트워크를 전환하거나, 전화 무선 기능을 켜고 끌 수 있습니다."</string>
     <string name="permlab_readPhoneState">"전화기 상태 읽기"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"SIM 카드를 삽입하세요."</string>
     <string name="lockscreen_network_locked_message">"네트워크 잠김"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM 카드의 PUK가 잠겨 있습니다."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"고객지원팀에 문의하세요."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM 카드가 잠겨 있습니다."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM 카드 잠금해제 중..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"잠금해제 패턴을 <xliff:g id="NUMBER_0">%d</xliff:g>회 잘못 가져왔습니다. "\n\n"<xliff:g id="NUMBER_1">%d</xliff:g>초 후에 다시 시도하세요."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g>초 후에 다시 입력하세요."</string>
     <string name="lockscreen_forgot_pattern_button_text">"패턴을 잊으셨나요?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"패턴을 너무 많이 시도했습니다."</string>
-    <string name="lockscreen_glogin_instructions">"잠금해제하려면"\n"Google 계정으로 로그인하세요."</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"사용자 이름(이메일)"</string>
     <string name="lockscreen_glogin_password_hint">"비밀번호"</string>
     <string name="lockscreen_glogin_submit_button">"로그인"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"매월"</string>
     <string name="yearly">"매년"</string>
     <string name="VideoView_error_title">"동영상 재생 안 됨"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"죄송합니다. 동영상을 재생할 수 없습니다."</string>
     <string name="VideoView_error_button">"확인"</string>
     <string name="am">"AM"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"정오"</string>
     <string name="Noon">"정오"</string>
     <string name="midnight">"자정"</string>
     <string name="Midnight">"자정"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g>, <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"일요일"</string>
     <string name="day_of_week_long_monday">"월요일"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-nb/strings.xml b/core/res/res/values-nb/strings.xml
index c1944a4..61b8928 100644
--- a/core/res/res/values-nb/strings.xml
+++ b/core/res/res/values-nb/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Nummervisning er ikke begrenset som standard. Neste anrop: Ikke begrenset"</string>
     <string name="serviceNotProvisioned">"SIM-kortet er ikke tilrettelagt for tjenesten."</string>
     <string name="CLIRPermanent">"Kunne ikke endre innstilling for nummervisning."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Tale"</string>
     <string name="serviceClassData">"Data"</string>
     <string name="serviceClassFAX">"Fax"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Lar applikasjonen slå av/på varsling om plasseringsendringer fra radioen. Ikke ment for vanlige applikasjoner."</string>
     <string name="permlab_checkinProperties">"få tilgang til egenskaper for innsjekking"</string>
     <string name="permdesc_checkinProperties">"Gir lese- og skrivetilgang til egenskaper lastet opp av innsjekkingstjenesten. Ikke ment for vanlige applikasjoner."</string>
-    <string name="permlab_bindGadget">"velg gadgeter"</string>
-    <string name="permdesc_bindGadget">"Lar applikasjonen fortelle systemet hvilke gadgeter som kan brukes av hvilke applikasjoner. Med denne rettigheten kan applikasjoner andre applikasjoner tilgang til personlig data. Ikke ment for vanlige applikasjoner."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"endre telefontilstand"</string>
     <string name="permdesc_modifyPhoneState">"Lar applikasjonen kontrollere telefonfunksjonaliteten i enheten. En applikasjon med denne rettigheten kan endre nettverk, slå telefonens radio av eller på og lignende uten noensinne å varsle brukeren."</string>
     <string name="permlab_readPhoneState">"lese telefontilstand"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Sett inn et SIM-kort."</string>
     <string name="lockscreen_network_locked_message">"Nettverk ikke tillatt"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM-kortet er PUK-låst."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Vennligst ring kundeservice."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM-kortet er låst."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Låser opp SIM-kort…"</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"You have incorrectly drawn your unlock pattern <xliff:g id="NUMBER_0">%d</xliff:g> times. "\n\n"Please try again in <xliff:g id="NUMBER_1">%d</xliff:g> seconds."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Prøv igjen om <xliff:g id="NUMBER">%d</xliff:g> sekunder."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Glemt mønsteret?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Too many pattern attempts!"</string>
-    <string name="lockscreen_glogin_instructions">"To unlock,"\n"sign in with your Google account"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Username (email)"</string>
     <string name="lockscreen_glogin_password_hint">"Password"</string>
     <string name="lockscreen_glogin_submit_button">"Sign in"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"En gang i måneden"</string>
     <string name="yearly">"En gang i året"</string>
     <string name="VideoView_error_title">"Cannot play video"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Sorry, this video cannot be played."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"AM"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>'. '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"middag"</string>
     <string name="Noon">"Middag"</string>
     <string name="midnight">"midnatt"</string>
     <string name="Midnight">"Midnatt"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g>. <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"søndag"</string>
     <string name="day_of_week_long_monday">"mandag"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-nl/strings.xml b/core/res/res/values-nl/strings.xml
index 725e369..2a67cd1 100644
--- a/core/res/res/values-nl/strings.xml
+++ b/core/res/res/values-nl/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Beller-id standaard ingesteld op \'onbeperkt\'. Volgende oproep: onbeperkt."</string>
     <string name="serviceNotProvisioned">"Service niet voorzien."</string>
     <string name="CLIRPermanent">"De instelling voor beller-id kan niet worden gewijzigd."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Spraak"</string>
     <string name="serviceClassData">"Gegevens"</string>
     <string name="serviceClassFAX">"FAX"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Hiermee kunnen updatemeldingen voor locaties van de radio worden ingeschakeld/uitgeschakeld. Niet voor gebruik door normale toepassingen."</string>
     <string name="permlab_checkinProperties">"toegang tot checkin-eigenschappen"</string>
     <string name="permdesc_checkinProperties">"Hiermee wordt lees-/schrijftoegang gegeven tot eigenschappen die door de checkin-service zijn geüpload. Niet voor gebruik door normale toepassingen."</string>
-    <string name="permlab_bindGadget">"gadgets kiezen"</string>
-    <string name="permdesc_bindGadget">"Hiermee kan een toepassing het systeem melden welke gadgets door welke toepassing kunnen worden gebruikt. Met deze toestemming kunnen toepassingen andere toepassingen toegang geven tot persoonlijke gegevens. Niet voor gebruik door normale toepassingen."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"telefoonstatus wijzigen"</string>
     <string name="permdesc_modifyPhoneState">"Hiermee kan de toepassing de telefoonfuncties van het apparaat beheren. Een toepassing met deze machtiging kan schakelen tussen netwerken, de radio van de telefoon in- of uitschakelen en dergelijke zonder dat u hiervan op de hoogte wordt gesteld."</string>
     <string name="permlab_readPhoneState">"telefoonstatus lezen"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Plaats een SIM-kaart."</string>
     <string name="lockscreen_network_locked_message">"Netwerk geblokkeerd"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM-kaart is geblokkeerd met PUK-code."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Neem contact op met de klantenservice."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM-kaart is geblokkeerd."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"SIM-kaart ontgrendelen..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"U heeft uw deblokkeringspatroon <xliff:g id="NUMBER_0">%d</xliff:g> keer onjuist getekend. "\n\n"Probeer het over <xliff:g id="NUMBER_1">%d</xliff:g> seconden opnieuw."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Probeer het over <xliff:g id="NUMBER">%d</xliff:g> seconden opnieuw."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Patroon vergeten?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Te veel patroonpogingen!"</string>
-    <string name="lockscreen_glogin_instructions">"U moet zich aanmelden bij uw Google-account"\n"om te ontgrendelen"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Gebruikersnaam (e-mail)"</string>
     <string name="lockscreen_glogin_password_hint">"Wachtwoord"</string>
     <string name="lockscreen_glogin_submit_button">"Aanmelden"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Maandelijks"</string>
     <string name="yearly">"Jaarlijks"</string>
     <string name="VideoView_error_title">"Video kan niet worden afgespeeld"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Deze video kan niet worden afgespeeld."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"am"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"twaalf uur \'s middags"</string>
     <string name="Noon">"Twaalf uur \'s middags"</string>
     <string name="midnight">"middernacht"</string>
     <string name="Midnight">"Middernacht"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"Zondag"</string>
     <string name="day_of_week_long_monday">"Maandag"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-pl/strings.xml b/core/res/res/values-pl/strings.xml
index 641d335..8c1f61b 100644
--- a/core/res/res/values-pl/strings.xml
+++ b/core/res/res/values-pl/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Identyfikator dzwoniącego ustawiony jest domyślnie na „nie zastrzeżony”. Następne połączenie: nie zastrzeżony"</string>
     <string name="serviceNotProvisioned">"Usługa nie jest świadczona."</string>
     <string name="CLIRPermanent">"Nie można zmienić ustawienia identyfikatora dzwoniącego."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Głos"</string>
     <string name="serviceClassData">"Dane"</string>
     <string name="serviceClassFAX">"FAKS"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Pozwala włączyć/wyłączyć powiadomienia o aktualizacji położenia przez radio. Nie wykorzystywane przez normalne aplikacje."</string>
     <string name="permlab_checkinProperties">"dostęp do właściwości usługi rezerwacji"</string>
     <string name="permdesc_checkinProperties">"Pozwala na dostęp z uprawnieniami do odczytu/zapisu do właściwości przesłanych przez usługę rezerwacji. Nie wykorzystywane przez normalne aplikacje."</string>
-    <string name="permlab_bindGadget">"wybieranie gadżetów"</string>
-    <string name="permdesc_bindGadget">"Zezwala aplikacjom na wskazywanie systemowi, które gadżety mogą być używane przez inne aplikacje. Z użyciem tego pozwolenia aplikacje mogą udzielać dostępu do danych osobistych innym aplikacjom. Nie jest ono przeznaczone dla zwykłych aplikacji."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"zmiana stanu telefonu"</string>
     <string name="permdesc_modifyPhoneState">"Pozwala aplikacji na kontrolowanie funkcji telefonu w urządzeniu. Aplikacja z tymi uprawnieniami może przełączać sieci, włączać i wyłączać radio itp. bez informowania użytkownika."</string>
     <string name="permlab_readPhoneState">"czytanie stanu telefonu"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Włóż kartę SIM."</string>
     <string name="lockscreen_network_locked_message">"Sieć zablokowana"</string>
     <string name="lockscreen_sim_puk_locked_message">"Karta SIM jest zablokowana kodem PUK."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Skontaktuj się z działem obsługi klienta."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"Karta SIM jest zablokowana."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Odblokowywanie karty SIM..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Wzór odblokowania został nieprawidłowo narysowany <xliff:g id="NUMBER_0">%d</xliff:g> razy. "\n\n"Spróbuj ponownie za <xliff:g id="NUMBER_1">%d</xliff:g> sekund."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Spróbuj ponownie za <xliff:g id="NUMBER">%d</xliff:g> sekund."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Zapomniałeś wzoru?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Zbyt wiele prób narysowania wzoru!"</string>
-    <string name="lockscreen_glogin_instructions">"Aby odblokować,"\n"zaloguj się na koncie Google"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Nazwa użytkownika (e-mail)"</string>
     <string name="lockscreen_glogin_password_hint">"Hasło"</string>
     <string name="lockscreen_glogin_submit_button">"Zaloguj"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Miesięcznie"</string>
     <string name="yearly">"Co roku"</string>
     <string name="VideoView_error_title">"Nie można odtworzyć filmu wideo"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"Niestety, nie można odtworzyć tego filmu wideo."</string>
     <string name="VideoView_error_button">"OK"</string>
     <string name="am">"rano"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>', '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"południe"</string>
     <string name="Noon">"Południe"</string>
     <string name="midnight">"północ"</string>
     <string name="Midnight">"Północ"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>, <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"niedziela"</string>
     <string name="day_of_week_long_monday">"poniedziałek"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-ru/strings.xml b/core/res/res/values-ru/strings.xml
index ba88667..4a99da5 100644
--- a/core/res/res/values-ru/strings.xml
+++ b/core/res/res/values-ru/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"Идентификатор звонящего по умолчанию не ограничен. Следующий вызов: не ограничен"</string>
     <string name="serviceNotProvisioned">"Услуга не предоставляется."</string>
     <string name="CLIRPermanent">"Нельзя изменить настройки идентификатора звонящего."</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"Голос"</string>
     <string name="serviceClassData">"Данные"</string>
     <string name="serviceClassFAX">"ФАКС"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"Разрешает включение/отключение уведомлений о местоположении по радиосвязи. Не используется обычными приложениями."</string>
     <string name="permlab_checkinProperties">"открывать свойства проверки"</string>
     <string name="permdesc_checkinProperties">"Разрешает доступ на чтение и запись к свойствам, загруженным службой проверки. Не используется обычными приложениями."</string>
-    <string name="permlab_bindGadget">"выбирать гаджеты"</string>
-    <string name="permdesc_bindGadget">"Позволяет приложению сообщить системе, какие приложения могут использовать какие гаджеты. Это разрешение позволяет приложениям предоставлять другим приложениям доступ к личной информации. Не предназначено для использования обычными приложениями."</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"изменять состояние телефона"</string>
     <string name="permdesc_modifyPhoneState">"Позволяет приложению управлять телефонными функциями устройства. Приложение с такими полномочиями может переключать сети, включать и выключать радиосвязь и т.д., не сообщая вам об этом."</string>
     <string name="permlab_readPhoneState">"считывать состояние телефона"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"Вставьте SIM-карту."</string>
     <string name="lockscreen_network_locked_message">"Заблокирована сетью"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM-карта заблокирована PUK-кодом."</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"Свяжитесь со службой поддержки."</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM-карта заблокирована."</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"Разблокировка SIM-карты..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"Вы неправильно воспроизвели комбинацию разблокировки <xliff:g id="NUMBER_0">%d</xliff:g> раз. "\n\n"Повторите попытку через <xliff:g id="NUMBER_1">%d</xliff:g> сек."</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"Повторите попытку через <xliff:g id="NUMBER">%d</xliff:g> сек."</string>
     <string name="lockscreen_forgot_pattern_button_text">"Забыли комбинацию?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"Слишком много попыток ввести комбинацию!"</string>
-    <string name="lockscreen_glogin_instructions">"Для разблокировки"\n"войдите с помощью своего аккаунта Google"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"Имя пользователя (адрес электронной почты)"</string>
     <string name="lockscreen_glogin_password_hint">"Пароль"</string>
     <string name="lockscreen_glogin_submit_button">"Войти"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"Ежемесячно"</string>
     <string name="yearly">"Ежегодно"</string>
     <string name="VideoView_error_title">"Не удается воспроизвести видео"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"К сожалению, это видео нельзя воспроизвести."</string>
     <string name="VideoView_error_button">"ОК"</string>
     <string name="am">"AM"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"полдень"</string>
     <string name="Noon">"Полдень"</string>
     <string name="midnight">"полночь"</string>
     <string name="Midnight">"Полночь"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="DAY">%-d</xliff:g> <xliff:g id="MONTH">%B</xliff:g> <xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"воскресенье"</string>
     <string name="day_of_week_long_monday">"понедельник"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zh-rCN/strings.xml b/core/res/res/values-zh-rCN/strings.xml
index 346e254..b31c4f4 100644
--- a/core/res/res/values-zh-rCN/strings.xml
+++ b/core/res/res/values-zh-rCN/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"呼叫者 ID 默认情况下不受限制。下一个呼叫:不受限制"</string>
     <string name="serviceNotProvisioned">"未提供服务。"</string>
     <string name="CLIRPermanent">"不能更改呼叫者 ID 设置。"</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"语音"</string>
     <string name="serviceClassData">"数据"</string>
     <string name="serviceClassFAX">"传真"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"允许启用/禁用来自收音机的位置更新通知。普通应用程序不能使用此权限。"</string>
     <string name="permlab_checkinProperties">"访问检入属性"</string>
     <string name="permdesc_checkinProperties">"允许对检入服务上传的属性进行读/写访问。普通应用程序不能使用此权限。"</string>
-    <string name="permlab_bindGadget">"选择小工具"</string>
-    <string name="permdesc_bindGadget">"允许应用程序告诉系统哪些应用程序可以使用哪些小工具。应用程序可以借此授予其他应用程序访问个人数据的权限。普通应用程序不能使用此权限。"</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"修改手机状态"</string>
     <string name="permdesc_modifyPhoneState">"允许应用程序控制设备的手机功能。具有此权限的应用程序可能会切换网络,打开和关闭手机收音机以及类似操作,而不会通知您。"</string>
     <string name="permlab_readPhoneState">"读取手机状态"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"请插入 SIM 卡。"</string>
     <string name="lockscreen_network_locked_message">"网络已锁定"</string>
     <string name="lockscreen_sim_puk_locked_message">"已对 SIM 卡进行 PUK 码锁定。"</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"请联系客服部门。"</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM 卡已被锁定。"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"正在解锁 SIM 卡..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"您 <xliff:g id="NUMBER_0">%d</xliff:g> 次错误地绘制了您的解锁图案。"\n\n"请在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒后重试。"</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g> 秒后重试。"</string>
     <string name="lockscreen_forgot_pattern_button_text">"忘记了图案?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"图案尝试次数太多!"</string>
-    <string name="lockscreen_glogin_instructions">"要解锁,"\n"请用您的 Google 帐户登录"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"用户名(电子邮件)"</string>
     <string name="lockscreen_glogin_password_hint">"密码"</string>
     <string name="lockscreen_glogin_submit_button">"登录"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"每月"</string>
     <string name="yearly">"每年"</string>
     <string name="VideoView_error_title">"无法播放视频"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"很抱歉,此视频不能播放。"</string>
     <string name="VideoView_error_button">"确定"</string>
     <string name="am">"上午"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="MONTH">MMM</xliff:g>' 月 '<xliff:g id="DAY">d</xliff:g>' 日'"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="YEAR">yyyy</xliff:g>' 年 '<xliff:g id="DAY">d</xliff:g>' 月 '<xliff:g id="MONTH">MMM</xliff:g>' 日'"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"中午"</string>
     <string name="Noon">"中午"</string>
     <string name="midnight">"午夜"</string>
     <string name="Midnight">"午夜"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="YEAR">%Y</xliff:g> 年 <xliff:g id="MONTH">%B</xliff:g> 月 <xliff:g id="DAY">%-d</xliff:g> 日"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"周日"</string>
     <string name="day_of_week_long_monday">"周一"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values-zh-rTW/strings.xml b/core/res/res/values-zh-rTW/strings.xml
index 6d4b821..d88ca65 100644
--- a/core/res/res/values-zh-rTW/strings.xml
+++ b/core/res/res/values-zh-rTW/strings.xml
@@ -54,6 +54,16 @@
     <string name="CLIRDefaultOffNextCallOff">"預設顯示本機號碼,下一通也顯示。"</string>
     <string name="serviceNotProvisioned">"服務未設定完成。"</string>
     <string name="CLIRPermanent">"本機號碼設定無法變更。"</string>
+    <!-- no translation found for RestrictedChangedTitle (5592189398956187498) -->
+    <skip />
+    <!-- no translation found for RestrictedOnData (8653794784690065540) -->
+    <skip />
+    <!-- no translation found for RestrictedOnEmergency (6581163779072833665) -->
+    <skip />
+    <!-- no translation found for RestrictedOnNormal (2045364908281990708) -->
+    <skip />
+    <!-- no translation found for RestrictedOnAll (4923139582141626159) -->
+    <skip />
     <string name="serviceClassVoice">"語音"</string>
     <string name="serviceClassData">"資料"</string>
     <string name="serviceClassFAX">"傳真"</string>
@@ -286,8 +296,10 @@
     <string name="permdesc_locationUpdates">"允許啟用/停用無線通訊位置更新通知。一般應用程式不會使用此功能。"</string>
     <string name="permlab_checkinProperties">"存取登機選項"</string>
     <string name="permdesc_checkinProperties">"允許讀寫登機服務上傳的資料。一般應用程式不會使用此功能。"</string>
-    <string name="permlab_bindGadget">"選擇小工具"</string>
-    <string name="permdesc_bindGadget">"允許應用程式告知系統哪些應用程式可以使用哪些小工具。擁有此權限的應用程式可以讓其他應用程式使用個人資料。一般應用程式不會使用此功能。"</string>
+    <!-- no translation found for permlab_bindGadget (776905339015863471) -->
+    <skip />
+    <!-- no translation found for permdesc_bindGadget (2098697834497452046) -->
+    <skip />
     <string name="permlab_modifyPhoneState">"修改手機狀態"</string>
     <string name="permdesc_modifyPhoneState">"允許應用程式控制電話功能。擁有此權限的程式可自行切換網路、開關無線通訊功能。"</string>
     <string name="permlab_readPhoneState">"讀取手機狀態"</string>
@@ -405,7 +417,8 @@
     <string name="lockscreen_missing_sim_instructions">"請插入 SIM 卡。"</string>
     <string name="lockscreen_network_locked_message">"網路已鎖定"</string>
     <string name="lockscreen_sim_puk_locked_message">"SIM 的 PUK 已鎖定。"</string>
-    <string name="lockscreen_sim_puk_locked_instructions">"請聯絡客服中心。"</string>
+    <!-- no translation found for lockscreen_sim_puk_locked_instructions (635967534992394321) -->
+    <skip />
     <string name="lockscreen_sim_locked_message">"SIM 卡已鎖定。"</string>
     <string name="lockscreen_sim_unlock_progress_dialog_message">"解鎖 SIM 卡中..."</string>
     <string name="lockscreen_too_many_failed_attempts_dialog_message">"畫出解鎖圖形已錯誤 <xliff:g id="NUMBER_0">%d</xliff:g> 次。"\n\n" 請在 <xliff:g id="NUMBER_1">%d</xliff:g> 秒後再嘗試。"</string>
@@ -413,7 +426,8 @@
     <string name="lockscreen_too_many_failed_attempts_countdown">"<xliff:g id="NUMBER">%d</xliff:g> 秒後再試一次。"</string>
     <string name="lockscreen_forgot_pattern_button_text">"忘記解鎖圖形?"</string>
     <string name="lockscreen_glogin_too_many_attempts">"解鎖圖形出錯次數過多!"</string>
-    <string name="lockscreen_glogin_instructions">"若要解鎖,"\n"請以您的 Google 帳戶登入"</string>
+    <!-- no translation found for lockscreen_glogin_instructions (1816635201812207709) -->
+    <skip />
     <string name="lockscreen_glogin_username_hint">"使用者名稱 (電子郵件)"</string>
     <string name="lockscreen_glogin_password_hint">"密碼"</string>
     <string name="lockscreen_glogin_submit_button">"登入"</string>
@@ -552,6 +566,8 @@
     <string name="monthly">"每月"</string>
     <string name="yearly">"每年"</string>
     <string name="VideoView_error_title">"無法播放影片"</string>
+    <!-- no translation found for VideoView_error_text_invalid_progressive_playback (897920883624437033) -->
+    <skip />
     <string name="VideoView_error_text_unknown">"抱歉,無法撥放此影片。"</string>
     <string name="VideoView_error_button">"確定"</string>
     <string name="am">"上午"</string>
@@ -573,14 +589,14 @@
     <string name="medium_date_month_first" format="date">"<xliff:g id="MONTH">MMM</xliff:g>' '<xliff:g id="DAY">d</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="medium_date_day_first" format="date">"<xliff:g id="DAY">d</xliff:g>' '<xliff:g id="MONTH">MMM</xliff:g>','<xliff:g id="YEAR">yyyy</xliff:g>"</string>
     <string name="twelve_hour_time_format" format="date">"<xliff:g id="HOUR">h</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>' '<xliff:g id="AMPM">a</xliff:g>"</string>
-    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">H</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
+    <string name="twenty_four_hour_time_format" format="date">"<xliff:g id="HOUR">HH</xliff:g>':'<xliff:g id="MINUTE">mm</xliff:g>"</string>
     <string name="noon">"中午"</string>
     <string name="Noon">"中午"</string>
     <string name="midnight">"午夜"</string>
     <string name="Midnight">"午夜"</string>
     <!-- no translation found for month_day (3693060561170538204) -->
     <skip />
-    <!-- no translation found for month (1976700695144952053) -->
+    <!-- no translation found for month (7026169712234774086) -->
     <skip />
     <string name="month_day_year">"<xliff:g id="MONTH">%B</xliff:g> <xliff:g id="DAY">%-d</xliff:g>,<xliff:g id="YEAR">%Y</xliff:g>"</string>
     <!-- no translation found for month_year (2106203387378728384) -->
@@ -616,7 +632,7 @@
     <skip />
     <!-- no translation found for abbrev_month_day (3156047263406783231) -->
     <skip />
-    <!-- no translation found for abbrev_month (7304935052615731208) -->
+    <!-- no translation found for abbrev_month (3131032032850777433) -->
     <skip />
     <string name="day_of_week_long_sunday">"星期日"</string>
     <string name="day_of_week_long_monday">"星期一"</string>
@@ -810,6 +826,8 @@
     <skip />
     <!-- no translation found for ime_action_next (3138843904009813834) -->
     <skip />
+    <!-- no translation found for ime_action_done (8971516117910934605) -->
+    <skip />
     <!-- no translation found for ime_action_default (2840921885558045721) -->
     <skip />
 </resources>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 899d109..485edca 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -620,12 +620,35 @@
              Corresponds to
              {@link android.view.inputmethod.EditorInfo#IME_ACTION_DONE}. -->
         <flag name="actionDone" value="0x00000006" />
+        <!-- Used to specify that the IME does not need
+             to show its extracted text UI.  For input methods that may be fullscreen,
+             often when in landscape mode, this allows them to be smaller and let part
+             of the application be shown behind.  Though there will likely be limited
+             access to the application available from the user, it can make the
+             experience of a (mostly) fullscreen IME less jarring.  Note that when
+             this flag is specified the IME may <em>not</em> be set up to be able
+             to display text, so it should only be used in situations where this is
+             not needed.
+             <p>Corresponds to
+             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_EXTRACT_UI}. -->
+        <flag name="flagNoExtractUi" value="0x10000000" />
+        <!-- Used in conjunction with a custom action, this indicates that the
+             action should not be available as an accessory button when the
+             input method is full-screen.
+             Note that by setting this flag, there can be cases where the action
+             is simply never available to the user.  Setting this generally means
+             that you think showing text being edited is more important than the
+             action you have supplied.
+             <p>Corresponds to
+             {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ACCESSORY_ACTION}. -->
+        <flag name="flagNoAccessoryAction" value="0x20000000" />
         <!-- Used in conjunction with a custom action,
-             this indicates that the action should not
-             be available in-line as the same as a "enter" key.  Typically this is
+             this indicates that the action should not be available in-line as
+             a replacement for the "enter" key.  Typically this is
              because the action has such a significant impact or is not recoverable
              enough that accidentally hitting it should be avoided, such as sending
-             a message.
+             a message.    Note that {@link android.widget.TextView} will
+             automatically set this flag for you on multi-line text views.
              <p>Corresponds to
              {@link android.view.inputmethod.EditorInfo#IME_FLAG_NO_ENTER_ACTION}. -->
         <flag name="flagNoEnterAction" value="0x40000000" />
@@ -1372,7 +1395,8 @@
     </declare-styleable>
     <declare-styleable name="FrameLayout">
         <!-- Defines the drawable to draw over the content. This can be used as an overlay.
-             The foreground drawable participates in the padding of the content. -->
+             The foreground drawable participates in the padding of the content if the gravity
+             is set to fill. -->
         <attr name="foreground" format="reference|color" />
         <!-- Defines the gravity to apply to the foreground drawable. The gravity defaults
              to fill. -->
@@ -1408,6 +1432,9 @@
                  edge, a right gravity will clip the left edge, and neither will clip both edges. -->
             <flag name="clip_horizontal" value="0x08" />
         </attr>
+        <!-- Defines whether the foreground drawable should be drawn inside the padding.
+             This property is turned on by default. -->
+        <attr name="foregroundInsidePadding" format="boolean" />
         <!-- Determines whether to measure all children or just those in 
              the VISIBLE or INVISIBLE state when measuring. Defaults to false. -->
         <attr name="measureAllChildren" format="boolean" />
@@ -3024,6 +3051,22 @@
         </attr>
     </declare-styleable>
 
+    <declare-styleable name="InputMethodService">
+        <!-- Background to use for entire input method when it is being
+             shown in fullscreen mode with the extract view, to ensure
+             that it completely covers the application.  This allows,
+             for example, the candidate view to be hidden
+             while in fullscreen mode without having the application show through
+             behind it.-->
+        <attr name="imeFullscreenBackground" format="reference|color" />
+        <!-- Animation to use when showing the fullscreen extract UI after
+             it had previously been hidden. -->
+        <attr name="imeExtractEnterAnimation" format="reference" />
+        <!-- Animation to use when hiding the fullscreen extract UI after
+             it had previously been shown. -->
+        <attr name="imeExtractExitAnimation" format="reference" />
+    </declare-styleable>
+    
     <declare-styleable name="KeyboardView">
         <!-- Default KeyboardView style. -->
         <attr name="keyboardViewStyle" format="reference" />
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 88c7b35..c06c7c4 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1010,6 +1010,9 @@
   <public type="attr" name="imeOptions" id="0x01010264" />
   <public type="attr" name="imeActionLabel" id="0x01010265" />
   <public type="attr" name="imeActionId" id="0x01010266" />
+  <public type="attr" name="imeFullscreenBackground" id="0x01010267" />
+  <public type="attr" name="imeExtractEnterAnimation" id="0x01010268" />
+  <public type="attr" name="imeExtractExitAnimation" id="0x01010269" />
 
   <!-- The part of the UI shown by an
        {@link android.inputmethodservice.InputMethodService} that contains the
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 761cedd..7aaee1a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -113,6 +113,17 @@
     <!-- Displayed to tell the user that they cannot change the caller ID setting. -->
     <string name="CLIRPermanent">The caller ID setting cannot be changed.</string>
 
+    <!-- Notification title to tell the user that restricted state is changed by access control. -->
+    <string name="RestrictedChangedTitle">Restricted access changed</string>
+    <!-- Displayed to tell the user that data service is blocked by access control. -->
+    <string name="RestrictedOnData">Data service is blocked.</string>
+    <!-- Displayed to tell the user that emergency service is blocked by access control. -->
+    <string name="RestrictedOnEmergency">Emergency service is blocked.</string>
+    <!-- Displayed to tell the user that normal service is blocked by access control. -->
+    <string name="RestrictedOnNormal">Voice/SMS service is blocked.</string>
+    <!-- Displayed to tell the user that all voice service is blocked by access control. -->
+    <string name="RestrictedOnAll">All voice/SMS services are blocked.</string>
+    
     <!-- Mappings between TS 27.007 +CFCC/+CLCK "service classes" and human-readable strings--> <skip />
     <!-- Example: Service was enabled for: Voice, Data -->
     <string name="serviceClassVoice">Voice</string>
@@ -1148,7 +1159,7 @@
          PUK locked (Pin Unlock Kode) -->
     <string name="lockscreen_sim_puk_locked_message">SIM card is PUK-locked.</string>
     <!-- Shown in the lock screen when the SIM has become PUK locked and the user must call customer care to unlock it. -->
-    <string name="lockscreen_sim_puk_locked_instructions">Please contact Customer Care.</string>
+    <string name="lockscreen_sim_puk_locked_instructions">Please see the User Guide or contact Customer Care.</string>
 
     <!-- Shown in the lock screen to tell the user that their SIM is locked and they must unlock it. -->
     <string name="lockscreen_sim_locked_message">SIM card is locked.</string>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index a152410..fb357a2 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -154,12 +154,11 @@
     <!-- Status Bar Styles -->
 
     <style name="TextAppearance.StatusBarTitle">
-        <item name="android:textSize">14sp</item>
+        <item name="android:textAppearance">?android:attr/textAppearanceSmall</item>
         <item name="android:textStyle">bold</item>
-        <item name="android:textColor">#ffffffff</item>
+        <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
-
     <!-- Widget Styles -->
 
     <style name="Widget">
@@ -317,6 +316,10 @@
         <item name="android:paddingLeft">5sp</item>
     </style>
 
+    <style name="Widget.TextView.ListSeparator.White">
+        <item name="android:textColor">?textColorSecondaryInverse</item>
+    </style>
+
     <style name="Widget.EditText">
         <item name="android:focusable">true</item>
         <item name="android:focusableInTouchMode">true</item>
@@ -663,7 +666,6 @@
     </style>
 
     <style name="ZoomControls">
-        <item name="android:background">@android:drawable/zoom_plate</item>
         <item name="android:gravity">bottom</item>
         <item name="android:paddingLeft">15dip</item>
         <item name="android:paddingRight">15dip</item>
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index 01c46de..76824c3 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -185,6 +185,7 @@
          fills the entire screen -->
     <style name="Theme.NoTitleBar.Fullscreen">
         <item name="android:windowFullscreen">true</item>
+        <item name="android:windowContentOverlay">@null</item>
     </style>
     
     <!-- Theme for a light background with dark text on top.  Set your activity
@@ -218,6 +219,7 @@
 
         <item name="listViewStyle">@android:style/Widget.ListView.White</item>
         <item name="listDivider">@drawable/divider_horizontal_bright</item>
+        <item name="listSeparatorTextViewStyle">@android:style/Widget.TextView.ListSeparator.White</item>
     </style>
     
     <!-- Variant of the light theme with no title bar -->
@@ -229,6 +231,7 @@
          fills the entire screen -->
     <style name="Theme.Light.NoTitleBar.Fullscreen">
         <item name="android:windowFullscreen">true</item>
+        <item name="android:windowContentOverlay">@null</item>
     </style>
     
     <!-- Special variation on the default theme that ensures the background is
@@ -249,6 +252,7 @@
          fills the entire screen -->
     <style name="Theme.Black.NoTitleBar.Fullscreen">
         <item name="android:windowFullscreen">true</item>
+        <item name="android:windowContentOverlay">@null</item>
     </style>
     
     <!-- Default theme for translucent activities, that is windows that allow you
@@ -269,12 +273,14 @@
          fills the entire screen -->
     <style name="Theme.Translucent.NoTitleBar.Fullscreen">
         <item name="android:windowFullscreen">true</item>
+        <item name="android:windowContentOverlay">@null</item>
     </style>
     
     <!-- Default theme for activities that don't actually display a UI; that
          is, they finish themselves before being resumed.  -->
     <style name="Theme.NoDisplay">
         <item name="android:windowBackground">@null</item>
+        <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowIsTranslucent">false</item>
         <item name="android:windowAnimationStyle">@null</item>
         <item name="android:windowDisablePreview">true</item>
@@ -291,7 +297,7 @@
         <item name="android:windowTitleStyle">@android:style/DialogWindowTitle</item>
         <item name="android:windowBackground">@android:drawable/panel_background</item>
         <item name="android:windowIsFloating">true</item>
-        <item name="android:windowContentOverlay">@android:drawable/panel_separator</item>
+        <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item>
         <item name="android:windowSoftInputMode">stateUnspecified|adjustPan</item>
     </style>
@@ -303,21 +309,26 @@
         <item name="windowBackground">@android:color/transparent</item>
         <item name="windowTitleStyle">@android:style/DialogWindowTitle</item>
         <item name="windowIsFloating">true</item>
-        <item name="windowContentOverlay">@drawable/panel_separator</item>
+        <item name="windowContentOverlay">@null</item>
     </style>
     
-    <!-- Default theme for dialog windows and activities, which is used by the
-         {@link android.app.Dialog} class.  This changes the window to be
-         floating (not fill the entire screen), and puts a frame around its
-         contents.  You can set this theme on an activity if you would like to
-         make an activity that looks like a Dialog. -->
-    <style name="Theme.InputMethod" parent="Theme.Light.NoTitleBar">
+    <!-- Default theme for input methods, which is used by the
+         {@link android.inputmethodservice.InputMethodService} class.
+         this inherits from Theme.NoTitleBar, but makes the background
+         transparent, the window floating and translucent, and ensures that
+         it does not dim the UI behind it.  This also configures the window
+         with the standard IME animations and visuals. -->
+    <style name="Theme.InputMethod" parent="Theme.NoTitleBar">
         <item name="android:windowBackground">@android:color/transparent</item>
         <item name="android:windowFrame">@null</item>
+        <item name="android:windowContentOverlay">@null</item>
         <item name="android:windowIsFloating">true</item>
         <item name="android:backgroundDimEnabled">false</item>
         <item name="android:windowIsTranslucent">true</item>
         <item name="android:windowAnimationStyle">@android:style/Animation.InputMethod</item>
+        <item name="android:imeFullscreenBackground">@android:drawable/input_method_fullscreen_background</item>
+        <item name="android:imeExtractEnterAnimation">@android:anim/input_method_extract_enter</item>
+        <item name="android:imeExtractExitAnimation">@android:anim/input_method_extract_exit</item>
     </style>
 
     <!-- Theme for the search input bar. -->
@@ -358,7 +369,7 @@
         <item name="windowTitleStyle">@android:style/DialogWindowTitle</item>
         <item name="windowBackground">@android:color/transparent</item>
         <item name="windowIsFloating">true</item>
-        <item name="windowContentOverlay">@drawable/panel_separator</item>
+        <item name="windowContentOverlay">@null</item>
         <item name="textAppearance">@style/TextAppearance.Theme.Dialog.AppError</item>
     </style>
 </resources>
diff --git a/docs/html/sdk/OLD_RELEASENOTES.jd b/docs/html/sdk/OLD_RELEASENOTES.jd
new file mode 100644
index 0000000..7751681
--- /dev/null
+++ b/docs/html/sdk/OLD_RELEASENOTES.jd
@@ -0,0 +1,527 @@
+page.title=Release Notes for Older SDK Versions
+@jd:body
+
+<div class="special">
+  <p><strong>Note:</strong> These are the release notes for the "early-look" SDK versions, released
+  before the full Android 1.0 release in September 2008.
+  Release notes for the Android 1.0 and later SDK versions are provided in the main
+  <a href="{@docRoot}sdk/RELEASENOTES.html">Release Notes</a> document.</p>
+</div>
+
+
+
+<a name="0.9_r1" id="0.9_r1"></a>
+<h2>Android 0.9 SDK Beta (r1)</h2>
+
+<p>This beta SDK release contains a large number of bug fixes and improvements from the early-look SDKs.&nbsp; 
+The sections below describe the highlights of the release.
+
+<h3>New Features and Notable Changes</h3>
+
+<p><strong>Behavior and System Changes</strong></p>
+<ul>
+	<li>New Home screen and many user interface updates
+	</li>
+	<li>Minor changes to Activity lifecycle and task management
+	</li>
+	<li>New window option to request OpenGL acceleration for certain kinds of View structures
+	</li>
+</ul>
+<p>
+	<b>
+	Significant API Changes</b>
+</p>
+<ul>
+	<li>onFreeze(Bundle) renamed to onSaveInstanceState(Bundle), to better reflect the fact that it does not represent an actual change in application lifecycle
+	</li>
+	<li>IntentReceivers are now known as BroadcastReceivers (but still operate on Intents.)
+	</li>
+	<li>Various parts of the API cleaned up to use Intents instead of Bundles; Intent itself improved to reduce the need for separate payload Bundles.</li>
+	<li>ContentProvider Cursors have had significant changes to make them easier to create and remove certain data consistency bugs.
+	</li>
+	<li>Changes to menus to make them more flexible; also added context menus (similar to "right mouse button" menus)
+	</li>
+	<li>Changes to the Sensor API to make reading sensors more convenient and reduce the need to poll
+	</li>
+	<li>Improvements to the Camera API
+	</li>
+	<li>Significant changes to the Location API to make it easier to use and better self-documenting
+	</li>
+	<li>API cleanup on MapViews
+	</li>
+	<li>Performance-related changes to the MediaPlayer, as well as support for new types of ringtones
+	</li>
+	<li>Apache HTTPClient installation upgraded to 4.x of that API; 3.x version is removed
+	</li>
+	<li>HTTPClient 4.x removes multipart methods, include HttpMime which is an extension of Mime4j (http://james.apache.org/mime4j/index.html) in your project instead
+	</li>
+	<li>Improvements to WiFi and related networking
+	</li>
+	<li>New Preferences API to easily store small amounts of data
+	</li>
+	<li>Improvements to the Telephony API, including ability to obtain source number of incoming phone calls
+	</li>
+	<li>Variety of improvements to the View API
+	</li>
+	<li>Variety of improvements to component management, such as the ability to keep components private, better control over when processes are started, and ability to "alias" an Activity to more than one entry in AndroidManifest.xml
+	</li>
+	<li>Improvements to how the Browser and WebView, such as better control over content downloads
+	</li>
+	<li>A number of enhancements to XML layouts, such as the new &lt;merge&gt; tag
+	</li>
+	<li>Numerous improvements to the standard widgets
+	</li>
+	<li>Network access now requires that applications obtain a permission in their AndroidManifest.xml files.
+	</li>
+</ul>
+<p>
+	<b>
+	Maps &amp; Location</b>
+</p>
+<ul>
+	<li>The MapView will require an API key on final Android 1.0 devices. This key can be obtained at no cost from Google, and will allow access to the full MapView API. In this release, the API key must be provided but can be any dummy value.&nbsp; In the final 1.0-compatible SDKs, this will need to be a real key.
+	</li>
+	<li>The KML-based mock location provider supported in previous releases is no longer supported. In the current SDK, you can use the emulator console to send GPS fix updates to the emulator and applications running on it. Also, the DDMS tool provides an UI that you can use to easily upload GPX and KML files. DDMS handles playback of the KML or GPX tracks automatically. </li>
+</ul>
+<p>
+	<b>ADT Plugin for Eclipse</b></p>
+	<p>The ADT Plugin that accompanies this SDK includes a preview of the Graphical Layout Editor. Files located in &lt;project&gt;/res/layout[-qualifiers]/ will be opened with the new layout editor. This is very much a work in progress, and provided here for preview purpose. The editor feature is subject to change.
+</p>
+<ul>
+	<li>Dual page editor with a WYSIWYG page (the graphical editor) and an XML page with content assist.
+	</li>
+	<li>The interactivity in the editor itself is limited to selection at the moment. Actions on the layout elements can be done from the following standard Eclipse views: Outline (add/remove/up/down), and Properties (editing of all the element properties with a tooltip in the status bar).
+	</li>
+	<li>Top part of the editor allows you to display the layout in different configurations (language, orientation, size, etc...), and different themes.
+
+		<ul>
+			<li>All referenced resources (strings, bitmaps, etc...) are resolved based on the selected configuration/theme.
+			</li>
+			<li>A green check mark next to a resource qualifier indicates that the opened file matches the value of the qualifier. A warning sign indicates that the opened file does not specifies any value for this qualifier.
+			</li>
+			<li>If a different version of the opened layout matches the new configuration selection (in a different res/layout-qualifier folder) then the editor automatically switches to that new file.
+			</li>
+		</ul>
+	</li>
+	<li>Custom Views are supported, however if they do too much in their constructor/onDraw method, it may not work (the layout library used by the editor only includes a sub-part of the Android framework). Check the android console for errors/exceptions.
+	</li>
+</ul>
+
+<p>Known issues/limitations for Graphical Layout Editor include:</p>
+	
+		<ul>
+			<li>Font display is very close but not equals to on-device rendering since the font engine in Java slightly differs from the font engine in Android. This should not have any impact on your layouts.
+			</li>
+			<li>Creating new views in a relative layout automatically puts each new elements below each other using the <i>layout_below</i> attribute. However, until the layout file is saved, they will appear stacked on top of each other.
+			</li>
+			<li>Some XML based drawables don't draw. Fading in the scroll/list view appears as a white rectangle. Generally do not expect every single fancy drawing feature of the android framework to be supported in the layout editor (but we're working on it).
+			</li>
+			<li>Themes defined in the project are not added to the theme drop-down.
+			</li>
+			<li>No animation support!
+			</li>
+			<li>No support for WebView, MapView and SurfaceView.
+			</li>
+			<li>No UI support for &lt;merge&gt;, &lt;include&gt;, &lt;ViewStub&gt; elements. You can add these elements to your manifest using the xml editor only. 
+			</li>
+			<li>If a layout fails to render in a way that prevents the whole editor from opening, you can:
+
+			<ul>
+			<li>open that particular file in a different editor: right click the file in the package explorer and choose Open With... &gt; XML editor
+			</li>
+			<li>completely disable the layout editor, by setting a system wide environment variable called ANDROID_DISABLE_LAYOUT to any value.
+			</li>
+			</ul>
+			<li>If a layout fails to render, check the android console (in the standard Eclipse Console view). Errors/Exceptions will be displayed in there.
+			</li>
+	</ul>
+	</li>
+</ul>
+<p>Other ADT features/notes include:</p>
+<ul>
+	<li>There is a new launch option for activity. You can choose to launch the default activity (finds an activity configured to show up in the home screen), or a specific activity, or none.</li>
+	<li>Normal Java resources (non Java files placed in package folders) are now properly packaged in the final package, and can be accessed through normal java API such as ClassLoader.getResourceAsStream()</li>
+	<li>Launch configuration now has an option to wipe emulator data on launch. This always asks for confirmation.</li>
+	<li>Launch configuration now has an option to disable the boot animation. This will let the emulator start faster on older computers.</li>
+	<li>Installation of application is now more robust and will notify of installation failure. Also installation is blocking, removing issues where ADT tried to launch the activity before the app was installed.</li>
+
+</ul>
+
+<p><b>Ant Build Tools</b></p>
+
+<ul>
+  <li><span>External jar libraries are now directly supported by build.xml, just drop them in the libs directory.</li>
+</ul>
+
+<p><b>Emulator</b></p>
+
+<ul>
+  <li>The console port number of a given emulator instance is now displayed in its window's title bar.</li>
+  <li>You can define the console port number used by a given emulator instance.
+To do so, start the instance with the '-port &lt;port&gt;' option and
+specify which port the emulator should bind to for the console. &lt;port&gt; must be an *even* integer between 5554 and 5584 inclusive. The corresponding ADB port will be &lt;port&gt;+1.</li>
+  <li>The <code>-adb-port</code> command is deprecated. Please do not use it, as it will be removed soon and you cannot use both -port and -adb-port at the same time.</li>
+  <li>Voice/sms are automatically forwarded to other emulator instances running on the same machine, as long as you use their console port number as the destination phone number. For example, if you have two emulators running, the first one will typically use console port 5554, and the second one will use port 5556, dialing 5556 on the first emulator will generate an incoming call on the second emulator. You can also hold/unhold calls. This also works when sending SMS messages from one emulator to the other.</li>
+  <li>A new <code>-scale &lt;fraction&gt;</code> option allows you to scale the emulator window. </li>
+  <li>A new <code>-no-boot-anim</code> option tells the emulator to disable the boot animation. On slower systems, this can significantly reduce the time to boot the system in the emulator.</li>
+
+</ul>
+
+<p>
+	<b>Other Development Tools</b>
+</p>
+
+<p>The SDK includes several new development tools, such as</p>
+<ul>
+	<li><a href="{@docRoot}guide/developing/tools/hierarchy-viewer.html">HierarchyViewer</a> is a visual tool for inspecting and debugging your user interfaces and layout. </li>
+	<li><a href="{@docRoot}guide/developing/tools/draw9patch.html">Draw 9-patch</a> allows you to easily create a NinePatch graphic using a WYSIWYG editor. </li>
+	<li>The <a href="{@docRoot}guide/developing/tools/monkey.html">UI/Application Exerciser Monkey</a> generates pseudo-random system and user events, for testing your application. </li>
+</ul>
+<p>
+	<b>Application Signing</b>
+</p>
+<ul>
+	<li>Starting with this release, Android .apk files must be cryptographically signed, or the system will reject them upon installation.&nbsp; The purpose of this requirement is to securely and uniquely identify developers, so that the system can -- for example -- safely let multiple .apk files signed by the same developer share resources.&nbsp;
+	</li>
+	<li>There are no requirements on the key used to sign .apk files;&nbsp; locally-generated and self-signed keys are allowed.&nbsp; There is no PKI, and developers will not be required to purchase certificates, or similar. &nbsp; For developers who use the Eclipse/ADT plugin, application signing will be largely automatic.&nbsp; Developers who do not use Eclipse/ADT can use the standard Java jarsigner tool to sign .apk files.
+	</li>
+</ul>
+<p>
+	<b>Sample Code</b>
+</p>
+<ul>
+	<li>LunarLander has been converted to render into a SurfaceView via a background Thread, for better performance.
+	</li>
+	<li>New sample: the source code for the now-obsolete Home screen from M5 is included as an example of how to construct a Home screen replacement.
+	</li>
+</ul>
+<p>
+	<b>
+	Removed Functionality</b>
+</p>
+<ul>
+	<li>Due to significant API changes in the upstream open-source project and due to the timeline of getting certain Bluetooth profile implementations certified, a comprehensive Bluetooth API will not be possible or present in Android 1.0.
+	</li>
+	<li>Due to the security risks inherent in accepting arbitrary data from "outside" the device, the data messaging facility of the GTalkService will not be present in Android 1.0.&nbsp; The GTalkService will provide connectivity to Google's servers for Google Talk instant messaging, but the API has been removed from this release while we improve the service.&nbsp; Note that this will be a Google-specific service and is not part of the core of Android.
+	</li>
+	<li>We know that these changes will affect many developers who have worked with the prior early looks at the SDK, and we are very sorry for the resulting inconvenience.&nbsp; We look forward to the possibilty of restoring some or all of this functionality in a later version of the Android platform.
+	</li>
+</ul>
+<p>
+	<b>
+	Miscellaneous</b>
+</p>
+<ul>
+	<li>Many internal and non-public APIs have been removed from the documentation.&nbsp; Classes and methods that are not present in the documentation are non-public and should not be used, even though they may appear in tools such as IDEs.&nbsp; A future version of the SDK will ship with an android.jar file that contains only public classes, to help developers avoid accidentally using non-public APIs.
+	</li>
+	<li>A few extraneous APIs (such as unnecessary packages under java.awt) have been removed.
+	</li>
+	<li>Several additional tools are included, such as a utility for easily drawing 9-patch images.
+	</li>
+	<li>The DDMS utility has been refactored into library form. This is not of direct interest to application developers, but may be of interest to vendors interested in integrating the Android SDK into their products. Watch for more information about the ddmlib library soon.
+	</li>
+	<li>For performance and maintainability reasons, some APIs were moved into separate modules that must be explicitly included in the application via a directive in AndroidManifest.xml.&nbsp; Notable APIs that fall into this category are the MapView, and the java.awt.* classes, which each now reside in separate modules that must be imported.&nbsp; Developers who overlook this requirement will see ClassNotFoundExceptions that seem spurious. 
+	</li>
+	<li>Developers who use 'adb push' to install applications must now use 'adb install', since the full package manager is now implemented. 'adb push' will no longer work to install .apk files.
+	</li>
+	<li>The emulator supports a variety of new options, and some existing options have been changed.&nbsp; Please consult the updated emulator documentation for details.
+	</li>
+</ul>
+
+<h3>
+	Resolved Issues
+</h3>
+<p>
+	The list below is not comprehensive, but instead highlights the most interesting fixes since the last SDK release.
+</p>
+<ul>
+	<li>More of the standard Android user applications are now included, such as the Music and Messaging applications.
+	</li>
+	<li>Many bug fixes to the Media Player
+	</li>
+	<li>Emulator performance is improved, especially for startup
+	</li>
+	<li>More internal APIs are removed from class documentation.&nbsp; (However, this work is not quite yet complete.)
+	</li>
+	<li>It's now much easier to add media content to the SD card and have the ContentProvider locate and expose it to other applications.
+	</li>
+</ul>
+
+<h3>
+	Known Issues
+</h3>
+<ul>
+	<li>The final set of Intent patterns honored by Android 1.0 has not yet been fully documented.&nbsp; Documentation will be provided in future releases.
+	</li>
+	<li>We regret to inform developers that Android 1.0 will not support 3.5" floppy disks.
+	</li>
+	<li>Unfortunately, the ability to play audio streams from memory (such as via an InputStream or Reader) will not be possible in Android 1.0.&nbsp; As a workaround, we recommend that developers save media content to SD card and use MediaPlayer to play from a file URI, or embed a small HTTP server and play from a URI on localhost (such as http://127.0.0.1:4242/something).
+	</li>
+	<li>Android now supports modules or libraries that can be optionally linked into applications; a good example is the MapView, which has been moved into such a library. However, Android 1.0 will not support the ability for third-party developers to create such libraries for sharing with other applications.
+	</li>
+	<li>We believe that we have eliminated the problem with very long emulator startups on Windows, but had some trouble reproducing the issue.&nbsp; We are interested in feedback from developers, if this issue persists.
+	</li>
+</ul>
+
+
+
+
+<a name="m5-rc15"></a>
+<h2>Version m5-rc15</h2>
+
+<h3>New Features</h3>
+<p>m5-rc15 does not introduce any new features.</p>
+
+<h3>Resolved Issues</h3>
+<ul>
+    <li>1012640: Incorrect handling of BMP images.</li>
+</ul>
+
+<h3>Known Issues</h3>
+<p>Unless otherwise noted, Known Issues from m5-rc14 also apply to m5-rc15.</p>
+
+
+
+
+<a name="m5-rc14"></a>
+<h2>Version m5-rc14</h2>
+
+<h3>New Features</h3>
+
+<p>In addition to changes in the Android APIs, m5-rc14 also introduces changes to the Android Developer Tools:</p>
+
+<h4>emulator</h4>
+<ul>
+    <li>The Android emulator now support SD card images up to 128 GB in size.  The previous limit was 2 GB.</li>
+</ul>
+
+<h4>DDMS</h4>
+<ul>
+    <li>Support for managing multiple devices has been integrated into DDMS.  This should make it easier to debug applications that are run on multiple device scenarios.</li>
+</ul>
+
+<h4>ADT</h4>
+<ul>
+    <li>ADT now attempts to connect a debugger to any application that shows up
+    in the wait-for-debugger state, even if this application was not launched
+    from Eclipse.
+    <br /><br />
+    The connection is actually established only if there exists a project
+    in the Eclipse workspace that contains an <code>AndroidManifest.xml</code>
+    declaring a package matching the name of the process.
+    To force this connection from your code, use <code>Debug.waitForDebugger()</code>. Activities declaring that they require their own process through the
+    "process" attribute with a value like ":someProcess" will be
+    recognized and a debugger will be connected accordingly.
+    This should make it easier to debug intent receivers, services,
+    providers, and other activities not launched from the standard app
+    launcher.<br /><br /></li>
+    <li>ADT has launch modes for device target selection.  Automatic mode will: 1) launch an emulator if no device is present, 2) automatically target the device if only one is connected, and 3) prompt the user if 2 or more are connected.  Manual mode will always prompt the user.<br /><br /></li>
+    <li>ADT also contains the same support for multiple devices that has been introduced into DDMS.</li>
+</ul>
+
+<h4>AIDL</h4>
+<ul>
+    <li>AIDL files that import and reuse types is now supported by activityCreator.py and ADT.</li>
+</ul>
+
+<h4>traceview</h4>
+<ul>
+    <li>The <a href="{@docRoot}guide/developing/tools/traceview.html">traceview</a> tool is now included in the SDK.</li>
+</ul>
+
+<h3>Resolved Issues</h3>
+
+<p>The following Known Issues from m3-rc20 have been resolved:</p>
+<ul>
+    <li>917572: The activityCreator created incorrect IntelliJ scripts</li>
+    <li>917465: Unanswered incoming calls placed from the emulator console will result in an unfinished call UI if you press the call back button</li>
+    <li>917247: dmtracedump and traceview tools are not available in the SDK</li>
+    <li>912168: Extremely rapid or prolonged scrolling in the Maps application or MapsView will result in application errors</li>
+    <li>905852: adb emits warnings about deprecated API use on Mac OS X 10.5</li>
+    <li>905242: The Run dialog sometimes failed to show the Android Launcher</li>
+    <li>901122: The focus ring in the browser is sometimes incorrect</li>
+    <li>896274: On Windows, the emulator sometimes starts off-screen</li>
+    <li>778432: Icons for newly installed applications do not display</li>
+</ul>
+
+<h3>Known Issues</h3>
+
+<p>The following are known issues in m5-rc14:</p>
+
+<ul>
+    <li>1017312: The emulator window size has been reduced slightly, to allow it to be fully visible on smaller screens. This causes a slight clipping of the HVGA emulator skin but does not affect its function.</li>
+    <li>1021777: Setting a power requirement in a <code>Criteria</code> object passed to <code>{@link android.location.LocationManager#getBestProvider getBestProvider()}</code> will result in a value not being returned.</li>
+    <li>1025850: Emulator failing to launch from the Eclipse plugin due to wrong custom command line parameters do not report the error anywhere and silently fails.</li>
+</ul>
+
+<p>Unless otherwise noted, Known Issues from m3-rc20a also apply to m5-rc14.</p>
+
+
+
+
+<a name="m3-rc37a"></a>
+<h2>Version m3-rc37a</h2>
+
+<p>Version m3-rc37a and ADT 0.3.3 were released on December 14, 2007.</p>
+
+<h3>New Features</h3>
+
+<h4>Android Debug Bridge (ADB)</h4>
+<ul>
+<li>Now supports multiple emulators on one host computer. Please note that you need to use the <code>-data</code> option when starting secondary emulators, to allow those instances to save their data across sessions. Also, DDMS does not yet support debugging on multiple emulators yet. </li>
+</ul>
+
+<h4>ADT Plugin for Eclipse</h4>
+<ul>
+<li>Adds editor capabilities for working with Android manifest files, such as syntax highlighting and autocompletion. The editor capabilities require the Web Tools WST plugin for Eclipse, which is included in <a href="http://www.eclipse.org/downloads/moreinfo/compare.php">most Eclipse packages</a>. Not having WST does not prevent the ADT plugin from working. If necessary, you can download and install WST from the Web Tools Project <a href="http://download.eclipse.org/webtools/downloads">downloads page</a>. To update directly from an Eclipse installation, you can add a remote update site with this URL: http://download.eclipse.org/webtools/updates . Note that installing WST on Eclipse 3.4 will require installing other packages, as detailed on the WTP downloads page</a>.
+</li>
+<li>Now retries to launch the app on the emulator if it fails due to timing issues when the emulator is booting.</li>
+<li>Adds support for loading custom skins from the &lt;SDK&gt;/lib/images/skins/ directory. The Skin dropdown in the Emulator tab is now built from the content of the skins/ directory in order to support developer-made skins.</li>
+<li>Adds an Emulator control panel. This is a UI on top of the emulator console that allows you to change the state of the network and gsm connection, and to initiate incoming voice call. (This is also present in standalone DDMS.)</li>
+<li>Adds support for referenced projects. Android projects will add to the apk package any code from referenced projects.</li>
+<li>Eclipse console now warns if an .apk that is pushed to the device declares the same package as another already installed package.</li>
+<li>Java classes generated by the Eclipse plugin are now marked as derived automatically, so that Team plugins do not consider them as regular source.</li>
+</ul>
+
+<h4>Emulator Console</h4>
+<ul>
+<li>Now provides support for emulating inbound SMS messages. The ADT plugin and DDMS provide integrated access to 
+this capability. For more information about how to emulate inbound SMS from the console, 
+see <a href="{@docRoot}guide/developing/tools/emulator.html#sms">SMS Emulation</a>. </li>
+</ul>
+
+<h4>Emulator</h4>
+<ul><li>The default emulator skin has been changed to HVGA-P from QVGA-L. For information 
+about emulator skins and how to load a specific skin when starting the emulator, see 
+<a href="{@docRoot}guide/developing/tools/emulator.html#skins">Using Emulator Skins</a>.</li>
+</ul>
+
+<h3>Resolved Issues</h3>
+
+<h4>907947</h4>
+<p><code>adb -version</code> now returns a version number.</p>
+
+<h4>917462</h4>
+<p>Audio on Windows is fixed and is no longer 'choppy'. </p>
+
+<h4>Removed Manifest File Locking on Mac OS X</h4>
+
+<p>ADT plugin now uses a custom java editor for R.java/Manifest.java, to make those files non-editable. This is to replace the current locking mechanism which causes issues on Mac OS (preventing projects from being deleted). Note that your project must recompile at least once for the lock to be removed from the files.</p>
+
+<h4>The following known issues noted in m3-rc20 are now fixed:</h4>
+<p>
+<ul>
+<li>890937: Emulator does not support non-qwerty keyboards.
+<li>894618: <code>adb shell</code> may fail to connect when used the first time.
+<li>896274: On Windows, the emulator window may start off-screen.
+<li>899949: The emulator may fail to start with <code>-useaudio</code> on some environments.
+<li>912619: Emulator console listens on non-local ports 5554-5584.
+<li>917399: On Windows, running multiple emulator consoles can result in unexpected behavior when simulating incoming telephone calls.
+</ul>
+</p>
+
+<h3>Known Issues</h3>
+
+<p>Unless otherwise noted, Known Issues from m3-rc22a also apply to m3-rc37a.</p>
+
+
+
+
+<a name="m3-rc22a"></a>
+<h2>Version m3-rc22a</h2>
+
+<p>Version m3-rc22a and ADT 0.3.1 were released on November 16, 2007.</p>
+
+<h3>Resolved Issues</h3>
+
+<h4>920067</h4>
+<p>The New Android Project wizard provided by ADT 0.3.1 now properly displays error messages when used with Eclipse 3.2 on Windows.</p>
+
+<h4>920045</h4>
+<p>The <code>AndroidManifest.xml</code> files generated by ADT 0.3.1 now include the XML element required for displaying the associated app in the "Applications" menu. If you have applications created with ADT 0.3.0, simply ensure that your <code>AndroidManifest.xml</code> file contains the following highlighted line:</p>
+<pre>
+...
+    &lt;intent-filter&gt;
+        &lt;action android:value=&quot;android.intent.action.MAIN&quot; /&gt;
+        <strong>&lt;category android:value=&quot;android.intent.category.LAUNCHER&quot; /&gt;</strong>
+    &lt;/intent-filter&gt;
+...
+</pre>
+
+<h4>920098</h4>
+<p>ADT 0.3.1 is now compatible with Eclipse 3.4.</p>
+
+<h4>920282</h4>
+<p>Fixes a NullPointerException that is thrown in certain situations with the DDMS perspective in Eclipse.</p>
+
+<h4>918637</h4>
+<p>Address a keyboard lock-up issue when using <code>adb</code> on Mac OS X 10.4 and 10.5.</p>
+
+<h3>Known Issues</h3>
+
+<p>Unless otherwise noted, known issues from m3-rc20a also apply to m3-rc22a.</p>
+
+<a name="m3-rc20a"></a>
+
+<h2>Version m3-rc20a</h2>
+<h3>Known Issues</h3>
+
+<p>The following are known issues in m3-rc20a:</p>
+
+<h4>778432 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>In certain circumstances, icons for newly installed applications do not display as expected.</p>
+
+<h4>890937 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4>
+<p>The emulator currently does not support non-QWERTY keyboards.</p>
+
+<h4>894618 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4>
+<p>The adb shell command may fail to connect when used for the first time.</p>
+
+<h4>896274 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>On Windows, the emulator screen will sometimes show up off-screen when it is started. The workaround for this is to right-click on the emulator taskbar entry, select Move, and move the window using keyboard arrow keys</p>
+
+<h4>899949 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4>
+<p>The emulator may fail to start when using the <code>-useaudio</code> in some environments</p>
+
+<h4>901122 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>The focus ring shown in the browser may sometimes not properly wrap links.</p>
+
+<h4>905242 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>On Mac OS X 10.5, the Eclipse plugin's Run Dialog may sometimes fail to show the option to select the Android Launcher.</p>
+
+<h4>905852 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>On Mac OS X 10.5, adb will emit warnings about deprecated API use when first used.</p>
+
+<h4>912168 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>extremely rapid or prolonged scrolling in the Maps application or in a MapView will result in application errors.</p>
+
+<h4>912619 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4>
+<p>The emulator console listens for connections on ports 5554-5587. Future versions will only accept connections from localhost. It is recommend that you use a firewall to block external connections to those ports on your development machine.</p>
+
+<h4>912849</h4>
+<p>On Mac OS X 10.4, the emulator may hang if started in the background (i.e. <code>./emulator &amp;</code>).</p>
+
+<h4>914692</h4>
+<p>On Mac OS X 10.5, the emulator will emit warnings about deprecated API use when started from the command line.</p>
+
+<h4>917247 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>The dmtracedump and traceview tools are not available in the SDK.</p>
+
+<h4>917399 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m3-rc37a">m3-rc37a</a></span></h4>
+<p>On Windows, running multiple emulator consoles can result in unexpected behavior when simulating incoming telephone calls.</p>
+
+<h4>917465 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>Unanswered incoming calls placed from the emulator console, will result in an unfinished call UI if you press the call back button.</p>
+
+<h4>917572 - <span style="font-weight: normal; font-size: 13px; font-style: italic">Resolved in <a href="#m5-rc14">m5</a></span></h4>
+<p>Using activityCreator with the <code>--ide intellij</code> option creates IntelliJ scripts with incorrect documentation location specified. To correct, change value for the <code>&lt;JAVADOC&gt;</code> element in the generated .ipr file from <code>file://.../docs/framework</code> to <code>file://.../docs/reference</code>.</p>
+
+<h4>917579</h4>
+<p>On Ubuntu 7.10 (Gusty), the Eclipse package installed by the <code>apt-get install eclipse</code> command uses java-gcj by default.  This configuration is not compatible with the Android Eclipse plugin (ADT) and will result in "Class not found" errors whenever you access an ADT feature.</p>
+    <p>The resolution for this issue is to install a Sun JDK</p>
+    <pre>sudo update-java-alternatives --jre java-1.5.0-sun</pre>
+    <p>and then configure Eclipse to use it by exporting the following environment variable:</p>
+    <pre>export JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun</pre>
+    <p>or by adding following to your <code>.eclipse/eclipserc file</code>:</p>
+    <pre>JAVA_HOME=/usr/lib/jvm/java-1.5.0-sun</pre>
+
diff --git a/docs/html/sdk/older_releases.jd b/docs/html/sdk/older_releases.jd
new file mode 100644
index 0000000..ff57a36
--- /dev/null
+++ b/docs/html/sdk/older_releases.jd
@@ -0,0 +1,234 @@
+page.title=Older Releases
+@jd:body
+
+<div class="special">
+  <strong>NOTICE:</strong>
+  <p>The SDKs listed on this page are "early-look" versions that were released in
+  the year preceding the full release of Android 1.0 in September 2008. Because
+  these early-look SDKs were released before the Android 1.0 API specification was
+  finalized, they do not provide a compliant Android execution environment.
+  Consequently, applications that you develop in these SDKs will not be able to
+  run on any Android-powered devices.</p>
+
+  <p>If you have an older application that you built in one of the early-look SDKs,
+  you must migrate it to the Android
+  1.0 SDK (or later release) before you will be able to deploy it to
+  an Android-powered device. To help with this migration, each SDK package below
+  provides information about API changes from the previous version. You can find
+  the migration information in the documentation included in each SDK package.</p>
+
+  <p>If you are just getting started developing on Android, do not use one of these early-look
+  SDKs. Instead, develop using the most <a href="{@docRoot}sdk/index.html">current
+  SDK release</a> available, to ensure that your applications will be compatible
+  with Android-powered devices.</p>
+</div>
+
+
+
+
+ <h2>Android 0.9 SDK beta</h2>
+ <p><em>August 18, 2008 - <a href="OLD_RELEASENOTES.html#0.9_beta">Release Notes</a></em></p>
+ <table>
+   <tr>
+     <th>Platform</th>
+     <th>Package</th>
+     <th>Size</th>
+     <th>MD5 Checksum</th>
+   </tr>
+   <tr>
+     <td>Windows</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk-windows-0.9_beta.zip">android-sdk-windows-0.9_beta.zip</a></td>
+     <td>93,126,573 bytes</td>
+     <td>305031ad8335d1b6040bdd5a65349d6d</td>
+   </tr>
+   <tr class="alt">
+     <td>Mac OS X (intel)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk-mac_x86-0.9_beta.zip">android-sdk-mac_x86-0.9_beta.zip</a></td>
+     <td>91,374,464 bytes</td>
+     <td>9a6969159091cede46302e11049fe3ca</td>
+   </tr>
+   <tr>
+     <td>Linux (i386)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk-linux_x86-0.9_beta.zip">android-sdk-linux_x86-0.9_beta.zip</a></td>
+     <td>91,821,068 bytes</td>
+     <td>077e5ef549dd9c5be54bd88e6a8e196c</td>
+   </tr>
+ </table>
+
+
+
+
+<h2>Version m5-rc15</h2>
+ <p><em>March 3, 2008 - <a href="OLD_RELEASENOTES.html#m5-rc15">Release Notes</a></em></p>
+ <table>
+   <tr>
+     <th>Platform</th>
+     <th>Package</th>
+     <th>Size</th>
+     <th>MD5 Checksum</th>
+   </tr>
+   <tr>
+     <td>Windows</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc15_windows.zip">android-sdk_m5-rc15_windows.zip</a></td>
+     <td>79 MB</td>
+     <td>ecce40bc50201886d95ba2690cdbc5ce</td>
+   </tr>
+   <tr class="alt">
+     <td>Mac OS X (intel)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc15_mac-x86.zip">android-sdk_m5-rc15_mac-x86.zip</a></td>
+     <td>76 MB</td>
+     <td>45a6385bbc1b2cb295409cfc81fb04b4</td>
+   </tr>
+   <tr>
+     <td>Linux (i386)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc15_linux-x86.zip">android-sdk_m5-rc15_linux-x86.zip</a></td>
+     <td>76 MB</td>
+     <td>e913f785afecdeed34c30639fd8c5862</td>
+   </tr>
+ </table>
+
+
+
+
+ <h2>Version m5-rc14</h2>
+ <p><em>February 12, 2008 - <a href="OLD_RELEASENOTES.html#m5-rc14">Release Notes</a></em></p>
+ <table>
+   <tr>
+     <th>Platform</th>
+     <th>Package</th>
+     <th>Size</th>
+     <th>MD5 Checksum</th>
+   </tr>
+   <tr>
+     <td>Windows</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc14_windows.zip">android-sdk_m5-rc14_windows.zip</a></td>
+     <td>79 MB</td>
+     <td>ecc75c1e69588350634ca25867ce05a0</td>
+   </tr>
+   <tr class="alt">
+     <td>Mac OS X (intel)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc14_mac-x86.zip">android-sdk_m5-rc14_mac-x86.zip</a></td>
+     <td>76 MB</td>
+     <td>844c80d0adb1a326f5a9fff262c61efc</td>
+   </tr>
+   <tr>
+     <td>Linux (i386)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android-sdk_m5-rc14_linux-x86.zip">android-sdk_m5-rc14_linux-x86.zip</a></td>
+     <td>76 MB</td>
+     <td>f8b863c8a880afe9bb84124f5976aab1</td>
+   </tr>
+ </table>
+
+
+
+
+ <h2>Version m3-rc37a</h2>
+ <p><em>December 14, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc37a">Release Notes</a></em></p>
+ <table>
+   <tr>
+     <th>Platform</th>
+     <th>Package</th>
+     <th>Size</th>
+     <th>MD5 Checksum</th>
+   </tr>
+   <tr>
+     <td>Windows</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_windows_m3-rc37a.zip">android_sdk_windows_m3-rc37a.zip</a></td>
+     <td>58 MB</td>
+     <td>5db5aea20a2c2f010baefc4b1091a575</td>
+   </tr>
+   <tr class="alt">
+     <td>Mac OS X (intel)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_darwin_m3-rc37a.zip">android_sdk_darwin_m3-rc37a.zip</a></td>
+     <td>54 MB</td>
+     <td>0b22e73fbd07b4af4009387afce3a37f</td>
+   </tr>
+   <tr>
+     <td>Linux (i386)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_linux_m3-rc37a.zip">android_sdk_linux_m3-rc37a.zip</a></td>
+     <td>54 MB</td>
+     <td>41285beecc4f9926e6ecf5f12610b356</td>
+   </tr>
+ </table>
+
+
+
+
+ <h2>Version m3-rc22a</h2>
+ <p><em>November 16, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc22a">Release Notes</a></em></p>
+ <table>
+   <tr>
+     <th>Platform</th>
+     <th>Package</th>
+     <th>Size</th>
+     <th>MD5 Checksum</th>
+   </tr>
+   <tr>
+     <td>Windows</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_windows_m3-rc22a.zip">android_sdk_windows_m3-rc22a.zip</a></td>
+     <td>59 MB</td>
+     <td>aa3dee05a9872752a3bc4efd0f93e98b</td>
+   </tr>
+   <tr class="alt">
+     <td>Mac OS X (intel)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_darwin_m3-rc22a.zip">android_sdk_darwin_m3-rc22a.zip</a></td>
+     <td>55 MB</td>
+     <td>0547f45614ad94c3af22c3c0aa6f709f</td>
+   </tr>
+   <tr>
+     <td>Linux (i386)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_linux_m3-rc22a.zip">android_sdk_linux_m3-rc22a.zip</a></td>
+     <td>55 MB</td>
+     <td>84b3455de5cdfd841a172c13d24c382e</td>
+   </tr>
+ </table>
+
+
+
+
+ <h2>Version m3-rc20a</h2>
+ <p><em>November 12, 2007 - <a href="OLD_RELEASENOTES.html#m3-rc20a">Release Notes</a></em></p>
+ <table>
+   <tr>
+     <th>Platform</th>
+     <th>Package</th>
+     <th>Size</th>
+     <th>MD5 Checksum</th>
+   </tr>
+   <tr>
+     <td>Windows</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_windows_m3-rc20a.zip">android_sdk_windows_m3-rc20a.zip</a></td>
+     <td>59 MB</td>
+     <td>a404b875708df7339ba77bdf2e08dc06</td>
+   </tr>
+   <tr class="alt">
+     <td>Mac OS X (intel)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_darwin_m3-rc20a.zip">android_sdk_darwin_m3-rc20a.zip</a></td>
+     <td>55 MB</td>
+     <td>8fc29aeaa45eda84bfac854ebd02a6da</td>
+   </tr>
+   <tr>
+     <td>Linux (i386)</td>
+     <td>
+<a href="{@docRoot}sdk/download.html?v=android_sdk_linux_m3-rc20a.zip">android_sdk_linux_m3-rc20a.zip</a></td>
+     <td>55 MB</td>
+     <td>9196759df9b69cd89a220b156f133364</td>
+   </tr>
+ </table>
diff --git a/docs/html/sdk/sdk_toc.cs b/docs/html/sdk/sdk_toc.cs
index 76c1c84..9a5a18b 100644
--- a/docs/html/sdk/sdk_toc.cs
+++ b/docs/html/sdk/sdk_toc.cs
@@ -30,6 +30,7 @@
     <ul>
       <li><a href="<?cs var:toroot ?>sdk/1.0_r2/index.html">Android 1.0 SDK, release 2</a></li>
       <li><a href="<?cs var:toroot ?>sdk/1.0_r1/index.html">Android 1.0 SDK, release 1</a></li>
+      <li><a href="<?cs var:toroot ?>sdk/older_releases.html">Older Releases</a></li>
     </ul>
   </li><?cs 
  /if ?>
diff --git a/include/media/mediarecorder.h b/include/media/mediarecorder.h
index 78d7621..b9ea0c6 100644
--- a/include/media/mediarecorder.h
+++ b/include/media/mediarecorder.h
@@ -104,7 +104,8 @@
 // 
 enum media_recorder_info_type {
     MEDIA_RECORDER_INFO_UNKNOWN                   = 1,
-    MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800
+    MEDIA_RECORDER_INFO_MAX_DURATION_REACHED      = 800,
+    MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED      = 801
 };
 
 // ----------------------------------------------------------------------------
diff --git a/include/private/media/AudioTrackShared.h b/include/private/media/AudioTrackShared.h
index 1991aa7..bda969c 100644
--- a/include/private/media/AudioTrackShared.h
+++ b/include/private/media/AudioTrackShared.h
@@ -64,7 +64,8 @@
                 uint16_t    waitTimeMs;      // Cumulated wait time
                 // Padding ensuring that data buffer starts on a cache line boundary (32 bytes). 
                 // See AudioFlinger::TrackBase constructor
-                int32_t     Padding[3];
+                int32_t     Padding[1];
+                // Cache line boundary
                 
                             audio_track_cblk_t();
                 uint32_t    stepUser(uint32_t frameCount);
diff --git a/include/utils/ResourceTypes.h b/include/utils/ResourceTypes.h
index 7d3fcf2..d01d83f 100644
--- a/include/utils/ResourceTypes.h
+++ b/include/utils/ResourceTypes.h
@@ -814,7 +814,7 @@
         ORIENTATION_ANY  = 0x0000,
         ORIENTATION_PORT = 0x0001,
         ORIENTATION_LAND = 0x0002,
-        ORIENTATION_SQUARE = 0x0002,
+        ORIENTATION_SQUARE = 0x0003,
     };
     
     enum {
diff --git a/libs/audioflinger/AudioFlinger.cpp b/libs/audioflinger/AudioFlinger.cpp
index 5652b28..9ba7f90 100644
--- a/libs/audioflinger/AudioFlinger.cpp
+++ b/libs/audioflinger/AudioFlinger.cpp
@@ -58,6 +58,9 @@
 
 namespace android {
 
+static const char* kDeadlockedString = "AudioFlinger may be deadlocked\n";
+static const char* kHardwareLockedString = "Hardware lock is taken\n";
+
 //static const nsecs_t kStandbyTimeInNsecs = seconds(3);
 static const unsigned long kBufferRecoveryInUsecs = 2000;
 static const unsigned long kMaxBufferRecoveryInUsecs = 20000;
@@ -195,7 +198,7 @@
 #ifdef WITH_A2DP
 // setA2dpEnabled_l() must be called with AudioFlinger::mLock held
 void AudioFlinger::setA2dpEnabled_l(bool enable)
-{
+{    
     SortedVector < sp<MixerThread::Track> > tracks;
     SortedVector < wp<MixerThread::Track> > activeTracks;
     
@@ -243,12 +246,6 @@
             streamType == AudioSystem::NOTIFICATION);
 }
 
-bool AudioFlinger::streamDisablesA2dp(int streamType)
-{
-    return (streamType == AudioSystem::VOICE_CALL ||
-            streamType == AudioSystem::BLUETOOTH_SCO);
-}
-
 status_t AudioFlinger::dumpClients(int fd, const Vector<String16>& args)
 {
     const size_t SIZE = 256;
@@ -301,18 +298,39 @@
     return NO_ERROR;
 }
 
+static bool tryLock(Mutex& mutex)
+{
+    bool locked = false;
+    for (int i = 0; i < kDumpLockRetries; ++i) {
+        if (mutex.tryLock() == NO_ERROR) {
+            locked = true;
+            break;
+        }
+        usleep(kDumpLockSleep);
+    }
+    return locked;
+}
+
 status_t AudioFlinger::dump(int fd, const Vector<String16>& args)
 {
     if (checkCallingPermission(String16("android.permission.DUMP")) == false) {
         dumpPermissionDenial(fd, args);
     } else {
-        bool locked = false;
-        for (int i = 0; i < kDumpLockRetries; ++i) {
-            if (mLock.tryLock() == NO_ERROR) {
-                locked = true;
-                break;
-            }
-            usleep(kDumpLockSleep);
+        // get state of hardware lock
+        bool hardwareLocked = tryLock(mHardwareLock);
+        if (!hardwareLocked) {
+            String8 result(kHardwareLockedString);
+            write(fd, result.string(), result.size());
+        } else {
+            mHardwareLock.unlock();
+        }
+
+        bool locked = tryLock(mLock);
+
+        // failed to lock - AudioFlinger is probably deadlocked
+        if (!locked) {
+            String8 result(kDeadlockedString);
+            write(fd, result.string(), result.size());
         }
 
         dumpClients(fd, args);
@@ -496,6 +514,14 @@
         }
         LOGV("setOutput done\n");
     }
+    // setRouting() is always called at least for mode == AudioSystem::MODE_IN_CALL when 
+    // SCO is enabled, whatever current mode is so we can safely handle A2DP disabling only
+    // in this case to avoid doing it several times.
+    if (mode == AudioSystem::MODE_IN_CALL &&
+        (mask & AudioSystem::ROUTE_BLUETOOTH_SCO)) {
+        AutoMutex lock(&mLock);
+        handleRouteDisablesA2dp_l(routes);
+    }
 #endif
 
     // do nothing if only A2DP routing is affected
@@ -657,7 +683,7 @@
     if (uint32_t(stream) >= AudioSystem::NUM_STREAM_TYPES) {
         return BAD_VALUE;
     }
-    
+
 #ifdef WITH_A2DP
     mA2dpMixerThread->setStreamMute(stream, muted);
 #endif
@@ -672,8 +698,6 @@
         mHardwareMixerThread->setStreamMute(stream, muted);
     }
 
-    
-
     return NO_ERROR;
 }
 
@@ -837,36 +861,29 @@
 }
 
 #ifdef WITH_A2DP
-// handleStreamDisablesA2dp_l() must be called with AudioFlinger::mLock held
-void AudioFlinger::handleStreamDisablesA2dp_l(int command)
+// handleRouteDisablesA2dp_l() must be called with AudioFlinger::mLock held
+void AudioFlinger::handleRouteDisablesA2dp_l(int routes)
 {
-    switch(command) {
-    case ACTIVE_TRACK_ADDED:
-        {
-            if (mA2dpDisableCount++ == 0) {
-                if (mA2dpEnabled) {
-                    setA2dpEnabled_l(false);
-                    mA2dpSuppressed = true;
-                }
-            }
-            LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount);
-        }
-        break;
-    case ACTIVE_TRACK_REMOVED:
-        {
-            if (mA2dpDisableCount > 0) {
-                if (--mA2dpDisableCount == 0) {
-                    if (mA2dpSuppressed) {
-                        setA2dpEnabled_l(true);
-                        mA2dpSuppressed = false;
-                    }
-                }
-                LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
-            } else {
-                LOGE("mA2dpDisableCount is already zero");
+   if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
+        if (mA2dpDisableCount++ == 0) {
+            if (mA2dpEnabled) {
+                setA2dpEnabled_l(false);
+                mA2dpSuppressed = true;
             }
         }
-        break;
+        LOGV("mA2dpDisableCount incremented to %d", mA2dpDisableCount);
+   } else {
+        if (mA2dpDisableCount > 0) {
+            if (--mA2dpDisableCount == 0) {
+                if (mA2dpSuppressed) {
+                    setA2dpEnabled_l(true);
+                    mA2dpSuppressed = false;
+                }
+            }
+            LOGV("mA2dpDisableCount decremented to %d", mA2dpDisableCount);
+        } else {
+            LOGE("mA2dpDisableCount is already zero");
+        }
     }
 }
 #endif
@@ -1500,13 +1517,6 @@
         if (streamForcedToSpeaker(track->type())) {
             mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_ADDED);
         }        
-#ifdef WITH_A2DP
-        // AudioFlinger::mLock must be locked before calling
-        // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
-        if (streamDisablesA2dp(track->type())) {
-            mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED);
-        }
-#endif
     }
 }
 
@@ -1524,13 +1534,6 @@
         if (streamForcedToSpeaker(track->type())) {
             mAudioFlinger->handleForcedSpeakerRoute(ACTIVE_TRACK_REMOVED);
         }
-#ifdef WITH_A2DP
-        // AudioFlinger::mLock must be locked before calling
-        // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
-        if (streamDisablesA2dp(track->type())) {
-            mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED);
-        }
-#endif
     }
 }
 
@@ -1598,8 +1601,8 @@
                 new(mCblk) audio_track_cblk_t();
                 // clear all buffers
                 mCblk->frameCount = frameCount;
-                mCblk->sampleRate = sampleRate;
-                mCblk->channels = channelCount;
+                mCblk->sampleRate = (uint16_t)sampleRate;
+                mCblk->channels = (uint16_t)channelCount;
                 if (sharedBuffer == 0) {
                     mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
                     memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
@@ -1622,8 +1625,8 @@
            new(mCblk) audio_track_cblk_t();
            // clear all buffers
            mCblk->frameCount = frameCount;
-           mCblk->sampleRate = sampleRate;
-           mCblk->channels = channelCount;
+           mCblk->sampleRate = (uint16_t)sampleRate;
+           mCblk->channels = (uint16_t)channelCount;
            mBuffer = (char*)mCblk + sizeof(audio_track_cblk_t);
            memset(mBuffer, 0, frameCount*channelCount*sizeof(int16_t));
            // Force underrun condition to avoid false underrun callback until first data is
@@ -1680,7 +1683,7 @@
 }
 
 int AudioFlinger::MixerThread::TrackBase::sampleRate() const {
-    return mCblk->sampleRate;
+    return (int)mCblk->sampleRate;
 }
 
 int AudioFlinger::MixerThread::TrackBase::channelCount() const {
@@ -1693,11 +1696,12 @@
     int16_t *bufferEnd = bufferStart + frames * cblk->channels;
 
     // Check validity of returned pointer in case the track control block would have been corrupted.
-    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd) {
-        LOGW("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
-                server %d, serverBase %d, user %d, userBase %d",
+    if (bufferStart < mBuffer || bufferStart > bufferEnd || bufferEnd > mBufferEnd || 
+            cblk->channels == 2 && ((unsigned long)bufferStart & 3) ) {
+        LOGE("TrackBase::getBuffer buffer out of range:\n    start: %p, end %p , mBuffer %p mBufferEnd %p\n    \
+                server %d, serverBase %d, user %d, userBase %d, channels %d",
                 bufferStart, bufferEnd, mBuffer, mBufferEnd,
-                cblk->server, cblk->serverBase, cblk->user, cblk->userBase);
+                cblk->server, cblk->serverBase, cblk->user, cblk->userBase, cblk->channels);
         return 0;
     }
 
@@ -1864,12 +1868,14 @@
     // STOPPED state
     mState = STOPPED;
 
+    mCblk->lock.lock();
     // NOTE: reset() will reset cblk->user and cblk->server with
     // the risk that at the same time, the AudioMixer is trying to read
     // data. In this case, getNextBuffer() would return a NULL pointer
     // as audio buffer => the AudioMixer code MUST always test that pointer
     // returned by getNextBuffer() is not NULL!
     reset();
+    mCblk->lock.unlock();
 }
 
 void AudioFlinger::MixerThread::Track::reset()
@@ -2478,19 +2484,6 @@
 
     mRecordTrack = recordTrack;
 
-#ifdef WITH_A2DP
-    { // scope for lock2
-
-        // AudioFlinger::mLock must be locked before calling
-        // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
-        AutoMutex lock2(&mAudioFlinger->mLock);
-
-        // Currently there is no way to detect if we are recording over SCO,
-        // so we disable A2DP during any recording.
-        mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_ADDED);
-    }
-#endif
-
     // signal thread to start
     LOGV("Signal record thread");
     mWaitWorkCV.signal();
@@ -2503,18 +2496,6 @@
     LOGV("AudioRecordThread::stop");
     AutoMutex lock(&mLock);
     if (mActive && (recordTrack == mRecordTrack.get())) {
-#ifdef WITH_A2DP
-        { // scope for lock2
-    
-            // AudioFlinger::mLock must be locked before calling
-            // handleStreamDisablesA2dp_l because it calls setA2dpEnabled_l().
-            AutoMutex lock2(&mAudioFlinger->mLock);
-
-            // Currently there is no way to detect if we are recording over SCO,
-            // so we disable A2DP during any recording.
-            mAudioFlinger->handleStreamDisablesA2dp_l(ACTIVE_TRACK_REMOVED);
-        }
-#endif
         mActive = false;
         mStopped.wait(mLock);
     }
diff --git a/libs/audioflinger/AudioFlinger.h b/libs/audioflinger/AudioFlinger.h
index ab15947..db5cc74 100644
--- a/libs/audioflinger/AudioFlinger.h
+++ b/libs/audioflinger/AudioFlinger.h
@@ -165,7 +165,6 @@
     void                    checkA2dpEnabledChange_l();
 #endif
     static bool             streamForcedToSpeaker(int streamType);
-    static bool             streamDisablesA2dp(int streamType);
     
     // Management of forced route to speaker for certain track types.
     enum force_speaker_command {
@@ -176,7 +175,7 @@
     };
     void                    handleForcedSpeakerRoute(int command);
 #ifdef WITH_A2DP
-    void                    handleStreamDisablesA2dp_l(int command);
+    void                    handleRouteDisablesA2dp_l(int routes);
 #endif
 
     // Internal dump utilites.
diff --git a/libs/audioflinger/AudioMixer.cpp b/libs/audioflinger/AudioMixer.cpp
index b03467f..b02efcc 100644
--- a/libs/audioflinger/AudioMixer.cpp
+++ b/libs/audioflinger/AudioMixer.cpp
@@ -16,6 +16,7 @@
 */
 
 #define LOG_TAG "AudioMixer"
+//#define LOG_NDEBUG 0
 
 #include <stdint.h>
 #include <string.h>
@@ -780,8 +781,10 @@
 
         // in == NULL can happen if the track was flushed just after having
         // been enabled for mixing.
-        if (in == NULL) {
+        if (in == NULL || ((unsigned long)in & 3)) {
             memset(out, 0, numFrames*MAX_NUM_CHANNELS*sizeof(int16_t));
+            LOGE_IF(((unsigned long)in & 3), "process stereo track: input buffer alignment pb: buffer %p track %d, channels %d, needs %08x",
+                    in, i, t.channelCount, t.needs);
             return;
         }
         size_t outFrames = b.frameCount;
diff --git a/location/java/com/android/internal/location/GpsLocationProvider.java b/location/java/com/android/internal/location/GpsLocationProvider.java
index 6672e29..887574a 100644
--- a/location/java/com/android/internal/location/GpsLocationProvider.java
+++ b/location/java/com/android/internal/location/GpsLocationProvider.java
@@ -16,8 +16,10 @@
 
 package com.android.internal.location;
 
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.location.Criteria;
 import android.location.IGpsStatusListener;
 import android.location.Location;
@@ -32,9 +34,14 @@
 import android.util.Config;
 import android.util.Log;
 
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.TelephonyIntents;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.net.InetAddress;
+import java.net.UnknownHostException;
 import java.util.ArrayList;
 import java.util.Properties;
 
@@ -78,6 +85,11 @@
      */
     public static final String EXTRA_ENABLED = "enabled";
 
+    // these need to match GpsPositionMode enum in gps.h
+    private static final int GPS_POSITION_MODE_STANDALONE = 0;
+    private static final int GPS_POSITION_MODE_MS_BASED = 1;
+    private static final int GPS_POSITION_MODE_MS_ASSISTED = 2;
+
     // these need to match GpsStatusValue defines in gps.h
     private static final int GPS_STATUS_NONE = 0;
     private static final int GPS_STATUS_SESSION_BEGIN = 1;
@@ -135,6 +147,8 @@
     // requested frequency of fixes, in seconds
     private int mFixInterval = 1;
 
+    private int mPositionMode = GPS_POSITION_MODE_STANDALONE;
+
     // true if we started navigation
     private boolean mStarted;
 
@@ -156,7 +170,11 @@
     private GpsEventThread mEventThread;
     private GpsNetworkThread mNetworkThread;
     private Object mNetworkThreadLock = new Object();
-   
+
+    private String mSuplHost;
+    private int mSuplPort;
+    private boolean mSetSuplServer;
+
     // how often to request NTP time, in milliseconds
     // current setting 4 hours
     private static final long NTP_INTERVAL = 4*60*60*1000; 
@@ -166,6 +184,27 @@
 
     private ILocationCollector mCollector;
 
+    private class TelephonyBroadcastReceiver extends BroadcastReceiver {
+        @Override public void onReceive(Context context, Intent intent) {
+            String action = intent.getAction();
+
+            if (action.equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
+                String state = intent.getStringExtra(Phone.STATE_KEY);
+                String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
+                String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
+
+                if (Config.LOGD) {
+                    Log.d(TAG, "state: " + state +  " apnName: " + apnName + " reason: " + reason);
+                }
+                if ("CONNECTED".equals(state)) {
+                    native_set_supl_apn(apnName);
+                } else {
+                    native_set_supl_apn("");
+                }
+            }
+        }
+    }
+
     public static boolean isSupported() {
         return native_is_supported();
     }
@@ -174,6 +213,11 @@
         super(LocationManager.GPS_PROVIDER);
         mContext = context;
 
+        TelephonyBroadcastReceiver receiver = new TelephonyBroadcastReceiver();
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
+        context.registerReceiver(receiver, intentFilter);
+
         mProperties = new Properties();
         try {
             File file = new File(PROPERTIES_FILE);
@@ -181,6 +225,16 @@
             mProperties.load(stream);
             stream.close();
             mNtpServer = mProperties.getProperty("NTP_SERVER", null);
+            mSuplHost = mProperties.getProperty("SUPL_HOST");
+            String suplPortString = mProperties.getProperty("SUPL_PORT");
+            if (mSuplHost != null && suplPortString != null) {
+                try {
+                    mSuplPort = Integer.parseInt(suplPortString);
+                    mSetSuplServer = true;
+                } catch (NumberFormatException e) {
+                    Log.e(TAG, "unable to parse SUPL_PORT: " + suplPortString);
+                }
+            }
         } catch (IOException e) {
             Log.w(TAG, "Could not open GPS configuration file " + PROPERTIES_FILE);
         }
@@ -198,7 +252,7 @@
     public boolean requiresNetwork() {
         // We want updateNetworkState() to get called when the network state changes
         // for XTRA and NTP time injection support.
-        return (mNtpServer != null || native_supports_xtra());
+        return (mNtpServer != null || native_supports_xtra() || mSuplHost != null);
     }
 
     public void updateNetworkState(int state) {
@@ -542,7 +596,7 @@
         if (!mStarted) {
             if (Config.LOGV) Log.v(TAG, "startNavigating");
             mStarted = true;
-            if (!native_start(false, mFixInterval)) {
+            if (!native_start(mPositionMode, false, mFixInterval)) {
                 mStarted = false;
                 Log.e(TAG, "native_start failed in startNavigating()");
             }
@@ -806,7 +860,7 @@
                         }
                     }
                     waitTime = getWaitTime();
-                } while (!mDone && ((!mXtraDownloadRequested && waitTime > 0)
+                } while (!mDone && ((!mXtraDownloadRequested && !mSetSuplServer && waitTime > 0)
                         || !mNetworkAvailable));
                 if (Config.LOGD) Log.d(TAG, "NetworkThread out of wake loop");
                 
@@ -833,6 +887,29 @@
                         }
                     }
 
+                    // Set the SUPL server address if we have not yet
+                    if (mSetSuplServer) {
+                        try {
+                            InetAddress inetAddress = InetAddress.getByName(mSuplHost);
+                            if (inetAddress != null) {
+                                byte[] addrBytes = inetAddress.getAddress();
+                                long addr = 0;
+                                for (int i = 0; i < addrBytes.length; i++) {
+                                    int temp = addrBytes[i];
+                                    // signed -> unsigned
+                                    if (temp < 0) temp = 256 + temp;
+                                    addr = addr * 256 + temp;
+                                }
+                                // use MS-Based position mode if SUPL support is enabled
+                                mPositionMode = GPS_POSITION_MODE_MS_BASED;
+                                native_set_supl_server((int)addr, mSuplPort);
+                                mSetSuplServer = false; 
+                            }
+                        } catch (UnknownHostException e) {
+                            Log.e(TAG, "unknown host for SUPL server " + mSuplHost);
+                        }
+                    }
+
                     if ((mXtraDownloadRequested || 
                             (mNextXtraTime > 0 && mNextXtraTime <= System.currentTimeMillis()))
                             && xtraDownloader != null) {
@@ -908,7 +985,7 @@
     private native boolean native_init();
     private native void native_disable();
     private native void native_cleanup();
-    private native boolean native_start(boolean singleFix, int fixInterval);
+    private native boolean native_start(int positionMode, boolean singleFix, int fixInterval);
     private native boolean native_stop();
     private native void native_set_fix_frequency(int fixFrequency);
     private native void native_delete_aiding_data(int flags);
@@ -922,4 +999,8 @@
     private native void native_inject_time(long time, long timeReference, int uncertainty);
     private native boolean native_supports_xtra();
     private native void native_inject_xtra_data(byte[] data, int length);
+
+    // SUPL Support    
+    private native void native_set_supl_server(int addr, int port);
+    private native void native_set_supl_apn(String apn);
 }
diff --git a/media/java/android/media/AudioManager.java b/media/java/android/media/AudioManager.java
index 077d016..f509fb5 100644
--- a/media/java/android/media/AudioManager.java
+++ b/media/java/android/media/AudioManager.java
@@ -160,7 +160,7 @@
         16, // STREAM_MUSIC
         8,  // STREAM_ALARM
         8,  // STREAM_NOTIFICATION
-        15, // STREAM_BLUETOOTH_SCO
+        16, // STREAM_BLUETOOTH_SCO
     };
 
     /**  @hide Default volume index values for audio streams */
@@ -220,7 +220,7 @@
      * By default this is on for the ring stream. If this flag is included,
      * this behavior will be present regardless of the stream type being
      * affected by the ringer mode.
-     * 
+     *
      * @see #adjustVolume(int, int)
      * @see #adjustStreamVolume(int, int, int)
      */
@@ -954,25 +954,21 @@
     /**
      * IME standard keypress sound
      * @see #playSoundEffect(int)
-     * @hide FIXME: Unhide before release
      */
     public static final int FX_KEYPRESS_STANDARD = 5;
     /**
      * IME spacebar keypress sound
      * @see #playSoundEffect(int)
-     * @hide FIXME: Unhide before release
      */
     public static final int FX_KEYPRESS_SPACEBAR = 6;
     /**
      * IME delete keypress sound
      * @see #playSoundEffect(int)
-     * @hide FIXME: Unhide before release
      */
     public static final int FX_KEYPRESS_DELETE = 7;
     /**
      * IME return_keypress sound
      * @see #playSoundEffect(int)
-     * @hide FIXME: Unhide before release
      */
     public static final int FX_KEYPRESS_RETURN = 8;
     /**
@@ -988,11 +984,10 @@
      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
-     *            FIXME: include links before release
-     *            {link #FX_KEYPRESS_STANDARD},
-     *            {link #FX_KEYPRESS_SPACEBAR},
-     *            {link #FX_KEYPRESS_DELETE},
-     *            {link #FX_KEYPRESS_RETURN},
+     *            {@link #FX_KEYPRESS_STANDARD},
+     *            {@link #FX_KEYPRESS_SPACEBAR},
+     *            {@link #FX_KEYPRESS_DELETE},
+     *            {@link #FX_KEYPRESS_RETURN},
      * NOTE: This version uses the UI settings to determine
      * whether sounds are heard or not.
      */
@@ -1021,15 +1016,13 @@
      *            {@link #FX_FOCUS_NAVIGATION_DOWN},
      *            {@link #FX_FOCUS_NAVIGATION_LEFT},
      *            {@link #FX_FOCUS_NAVIGATION_RIGHT},
-     *            FIXME: include links before release
-     *            {link #FX_KEYPRESS_STANDARD},
-     *            {link #FX_KEYPRESS_SPACEBAR},
-     *            {link #FX_KEYPRESS_DELETE},
-     *            {link #FX_KEYPRESS_RETURN},
+     *            {@link #FX_KEYPRESS_STANDARD},
+     *            {@link #FX_KEYPRESS_SPACEBAR},
+     *            {@link #FX_KEYPRESS_DELETE},
+     *            {@link #FX_KEYPRESS_RETURN},
      * @param volume Sound effect volume
      * NOTE: This version is for applications that have their own
      * settings panel for enabling and controlling volume.
-     *  @hide FIXME: Unhide before release
      */
     public void  playSoundEffect(int effectType, float volume) {
         if (effectType < 0 || effectType >= NUM_SOUND_EFFECTS) {
diff --git a/media/java/android/media/AudioTrack.java b/media/java/android/media/AudioTrack.java
index 316fa7a..d2bad93 100644
--- a/media/java/android/media/AudioTrack.java
+++ b/media/java/android/media/AudioTrack.java
@@ -171,6 +171,10 @@
      */
     private NativeEventHandlerDelegate mEventHandlerDelegate = null;
     /**
+     * Looper associated with the thread that creates the AudioTrack instance
+     */
+    private Looper mInitializationLooper = null;
+    /**
      * The audio data sampling rate in Hz.
      */
     private int mSampleRate = 22050;
@@ -248,6 +252,11 @@
             int bufferSizeInBytes, int mode)
     throws IllegalArgumentException {
         mState = STATE_UNINITIALIZED;
+        
+        // remember which looper is associated with the AudioTrack instanciation
+        if ((mInitializationLooper = Looper.myLooper()) == null) {
+            mInitializationLooper = Looper.getMainLooper();
+        }
 
         audioParamCheck(streamType, sampleRateInHz, channelConfig, audioFormat, mode);
 
@@ -902,11 +911,10 @@
             if (handler != null) {
                 looper = handler.getLooper();
             } else {
-                // no given handler, look for main looper
-                if ((looper = Looper.myLooper()) == null) {
-                    looper = Looper.getMainLooper();
-                }
+                // no given handler, use the looper the AudioTrack was created in
+                looper = mInitializationLooper;
             }
+            
             // construct the event handler with this looper
             if (looper != null) {
                 // implement the event handler delegate
diff --git a/media/java/android/media/JetPlayer.java b/media/java/android/media/JetPlayer.java
index 9de0eec..6539d84 100644
--- a/media/java/android/media/JetPlayer.java
+++ b/media/java/android/media/JetPlayer.java
@@ -68,21 +68,22 @@
     //--------------------------------------------
     // Member variables
     //------------------------
-    private EventHandler            mNativeEventHandler = null;
+    /**
+     * Handler for jet events and status updates coming from the native code
+     */
+    private NativeEventHandler mEventHandler = null;
     
     /**
-     * Lock to protect status listener updates against status change notifications
+     * Looper associated with the thread that creates the AudioTrack instance
      */
-    private final Object mStatusListenerLock = new Object();
+    private Looper mInitializationLooper = null;
     
     /**
      * Lock to protect the event listener updates against event notifications
      */
     private final Object mEventListenerLock = new Object();
     
-    private JetStatusUpdateListener mJetStatusUpdateListener = null;
-    
-    private JetEventListener mJetEventListener = null;
+    private OnJetEventListener mJetEventListener = null;
     
     private static JetPlayer singletonRef;
     
@@ -115,6 +116,11 @@
     
 
     private JetPlayer() {
+
+        // remember which looper is associated with the JetPlayer instanciation
+        if ((mInitializationLooper = Looper.myLooper()) == null) {
+            mInitializationLooper = Looper.getMainLooper();
+        }
                 
         native_setup(new WeakReference<JetPlayer>(this),
                 JetPlayer.getMaxTracks(), 
@@ -132,18 +138,6 @@
     }
     
     
-    private void createNativeEventHandler() {
-        Looper looper;
-        if ((looper = Looper.myLooper()) != null) {
-            mNativeEventHandler = new EventHandler(this, looper);
-        } else if ((looper = Looper.getMainLooper()) != null) {
-            mNativeEventHandler = new EventHandler(this, looper);
-        } else {
-            mNativeEventHandler = null;
-        }
-    }
-    
-    
     //--------------------------------------------
     // Getters
     //------------------------
@@ -235,24 +229,27 @@
     //---------------------------------------------------------
     // Internal class to handle events posted from native code
     //------------------------
-    private class EventHandler extends Handler
+    private class NativeEventHandler extends Handler
     {
         private JetPlayer mJet;
 
-        public EventHandler(JetPlayer jet, Looper looper) {
+        public NativeEventHandler(JetPlayer jet, Looper looper) {
             super(looper);
             mJet = jet;
         }
 
         @Override
         public void handleMessage(Message msg) {
+            OnJetEventListener listener = null;
+            synchronized (mEventListenerLock) {
+                listener = mJet.mJetEventListener;
+            }
             switch(msg.what) {
             case JET_EVENT:
-                synchronized (mEventListenerLock) {
-                    if (mJetEventListener != null) {
-                        // call the appropriate listener after decoding the event parameters
-                        // encoded in msg.arg1
-                        mJetEventListener.onJetEvent(
+                if (listener != null) {
+                    // call the appropriate listener after decoding the event parameters
+                    // encoded in msg.arg1
+                    mJetEventListener.onJetEvent(
                             mJet,
                             (short)((msg.arg1 & JET_EVENT_SEG_MASK)   >> JET_EVENT_SEG_SHIFT),
                             (byte) ((msg.arg1 & JET_EVENT_TRACK_MASK) >> JET_EVENT_TRACK_SHIFT),
@@ -261,28 +258,21 @@
                             (byte)(((msg.arg1 & JET_EVENT_CHAN_MASK)  >> JET_EVENT_CHAN_SHIFT) + 1),
                             (byte) ((msg.arg1 & JET_EVENT_CTRL_MASK)  >> JET_EVENT_CTRL_SHIFT),
                             (byte)  (msg.arg1 & JET_EVENT_VAL_MASK) );
-                    }
                 }
                 return;
             case JET_USERID_UPDATE:
-                synchronized (mStatusListenerLock) {
-                    if (mJetStatusUpdateListener != null) {
-                        mJetStatusUpdateListener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2);
-                    }
+                if (listener != null) {
+                    listener.onJetUserIdUpdate(mJet, msg.arg1, msg.arg2);
                 }
                 return;
             case JET_NUMQUEUEDSEGMENT_UPDATE:
-                synchronized (mStatusListenerLock) {
-                    if (mJetStatusUpdateListener != null) {
-                        mJetStatusUpdateListener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1);
-                    }
+                if (listener != null) {
+                    listener.onJetNumQueuedSegmentUpdate(mJet, msg.arg1);
                 }
                 return;
             case JET_PAUSE_UPDATE:
-                synchronized (mStatusListenerLock) {
-                    if (mJetStatusUpdateListener != null)
-                        mJetStatusUpdateListener.onJetPauseUpdate(mJet, msg.arg1);
-                }
+                if (listener != null)
+                    listener.onJetPauseUpdate(mJet, msg.arg1);
                 return;
 
             default:
@@ -294,22 +284,48 @@
     
     
     //--------------------------------------------
-    // Jet status update listener
+    // Jet event listener
     //------------------------
-    public void setStatusUpdateListener(JetStatusUpdateListener listener) {
-        synchronized(mStatusListenerLock) {
-            mJetStatusUpdateListener = listener;
-        }
-        
-        if ((listener != null) && (mNativeEventHandler == null)) {
-            createNativeEventHandler();
+    public void setEventListener(OnJetEventListener listener) {
+        setEventListener(listener, null);
+    }
+    
+    public void setEventListener(OnJetEventListener listener, Handler handler) {
+        synchronized(mEventListenerLock) {
+            
+            mJetEventListener = listener;
+            
+            if (listener != null) {
+                if (handler != null) {
+                    mEventHandler = new NativeEventHandler(this, handler.getLooper());
+                } else {
+                    // no given handler, use the looper the AudioTrack was created in
+                    mEventHandler = new NativeEventHandler(this, mInitializationLooper);
+                }
+            } else {
+                mEventHandler = null;
+            }
+            
         }
     }
     
+    
     /**
-     * Handles the notification when the JET status is updated.
+     * Handles the notification when the JET engine generates an event.
      */
-    public interface JetStatusUpdateListener {
+    public interface OnJetEventListener {
+        /**
+         * Callback for when the JET engine generates a new event.
+         * 
+         * @param player the JET player the event is coming from
+         * @param segment 8 bit unsigned value
+         * @param track 6 bit unsigned value
+         * @param channel 4 bit unsigned value
+         * @param controller 7 bit unsigned value
+         * @param value 7 bit unsigned value
+         */
+        void onJetEvent(JetPlayer player,
+                short segment, byte track, byte channel, byte controller, byte value);
         /**
          * Callback for when JET's currently playing segment userID is updated.
          * 
@@ -338,38 +354,6 @@
     
     
     //--------------------------------------------
-    // Jet event listener
-    //------------------------
-    public void setEventListener(JetEventListener listener) {
-        synchronized(mEventListenerLock) {
-            mJetEventListener = listener;
-        }
-        
-        if ((listener != null) && (mNativeEventHandler == null)) {
-            createNativeEventHandler();
-        }
-    }
-    
-    /**
-     * Handles the notification when the JET engine generates an event.
-     */
-    public interface JetEventListener {
-        /**
-         * Callback for when the JET engine generates a new event.
-         * 
-         * @param player the JET player the event is coming from
-         * @param segment 8 bit unsigned value
-         * @param track 6 bit unsigned value
-         * @param channel 4 bit unsigned value
-         * @param controller 7 bit unsigned value
-         * @param value 7 bit unsigned value
-         */
-        void onJetEvent(JetPlayer player,
-                short segment, byte track, byte channel, byte controller, byte value);
-    }
-    
-    
-    //--------------------------------------------
     // Native methods
     //------------------------
     private native final boolean native_setup(Object Jet_this,
@@ -397,13 +381,15 @@
     @SuppressWarnings("unused")
     private static void postEventFromNative(Object jetplayer_ref,
             int what, int arg1, int arg2) {
-        
+        //logd("Event posted from the native side: event="+ what + " args="+ arg1+" "+arg2);
         JetPlayer jet = (JetPlayer)((WeakReference)jetplayer_ref).get();
 
-        if( (jet!=null) && (jet.mNativeEventHandler!=null) ){
-            Message m = jet.mNativeEventHandler.obtainMessage(what, arg1, arg2, null);
-            jet.mNativeEventHandler.sendMessage(m);
+        if ((jet != null) && (jet.mEventHandler != null)) {
+            Message m = 
+                jet.mEventHandler.obtainMessage(what, arg1, arg2, null);
+            jet.mEventHandler.sendMessage(m);
         }
+        
     }
     
  
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 202d0ae..9668efa 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -1036,11 +1036,11 @@
      * Register a callback to be invoked when the media source is ready
      * for playback.
      *
-     * @param l the callback that will be run
+     * @param listener the callback that will be run
      */
-    public void setOnPreparedListener(OnPreparedListener l)
+    public void setOnPreparedListener(OnPreparedListener listener)
     {
-        mOnPreparedListener = l;
+        mOnPreparedListener = listener;
     }
 
     private OnPreparedListener mOnPreparedListener;
@@ -1063,11 +1063,11 @@
      * Register a callback to be invoked when the end of a media source
      * has been reached during playback.
      *
-     * @param l the callback that will be run
+     * @param listener the callback that will be run
      */
-    public void setOnCompletionListener(OnCompletionListener l)
+    public void setOnCompletionListener(OnCompletionListener listener)
     {
-        mOnCompletionListener = l;
+        mOnCompletionListener = listener;
     }
 
     private OnCompletionListener mOnCompletionListener;
@@ -1092,11 +1092,11 @@
      * Register a callback to be invoked when the status of a network
      * stream's buffer has changed.
      *
-     * @param l the callback that will be run
+     * @param listener the callback that will be run.
      */
-    public void setOnBufferingUpdateListener(OnBufferingUpdateListener l)
+    public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener)
     {
-        mOnBufferingUpdateListener = l;
+        mOnBufferingUpdateListener = listener;
     }
 
     private OnBufferingUpdateListener mOnBufferingUpdateListener;
@@ -1119,11 +1119,11 @@
      * Register a callback to be invoked when a seek operation has been
      * completed.
      * 
-     * @param l the callback that will be run
+     * @param listener the callback that will be run
      */
-    public void setOnSeekCompleteListener(OnSeekCompleteListener l)
+    public void setOnSeekCompleteListener(OnSeekCompleteListener listener)
     {
-        mOnSeekCompleteListener = l;
+        mOnSeekCompleteListener = listener;
     }
     
     private OnSeekCompleteListener mOnSeekCompleteListener;
@@ -1151,12 +1151,12 @@
      * Register a callback to be invoked when the video size is
      * known or updated.
      * 
-     * @param l the callback that will be run
+     * @param listener the callback that will be run
      * @hide
      */
-    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener l)
+    public void setOnVideoSizeChangedListener(OnVideoSizeChangedListener listener)
     {
-        mOnVideoSizeChangedListener = l;
+        mOnVideoSizeChangedListener = listener;
     }
     
     private OnVideoSizeChangedListener mOnVideoSizeChangedListener;
diff --git a/media/java/android/media/MediaRecorder.java b/media/java/android/media/MediaRecorder.java
index 1c08cba..676f241 100644
--- a/media/java/android/media/MediaRecorder.java
+++ b/media/java/android/media/MediaRecorder.java
@@ -259,6 +259,12 @@
     /**
      * Sets the maximum duration (in ms) of the recording session.
      * Call this after setOutFormat() but before prepare().
+     * After recording reaches the specified duration, a notification
+     * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
+     * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
+     * and recording will be stopped. Stopping happens asynchronously, there
+     * is no guarantee that the recorder will have stopped by the time the
+     * listener is notified.
      *
      * @param max_duration_ms the maximum duration in ms (if zero or negative, disables the duration limit)
      *
@@ -266,6 +272,21 @@
     public native void setMaxDuration(int max_duration_ms) throws IllegalArgumentException;
 
     /**
+     * Sets the maximum filesize (in bytes) of the recording session.
+     * Call this after setOutFormat() but before prepare().
+     * After recording reaches the specified filesize, a notification
+     * will be sent to the {@link android.media.MediaRecorder.OnInfoListener}
+     * with a "what" code of {@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
+     * and recording will be stopped. Stopping happens asynchronously, there
+     * is no guarantee that the recorder will have stopped by the time the
+     * listener is notified.
+     *
+     * @param max_filesize_bytes the maximum filesize in bytes (if zero or negative, disables the limit)
+     *
+     */
+    public native void setMaxFileSize(long max_filesize_bytes) throws IllegalArgumentException;
+
+    /**
      * Sets the audio encoder to be used for recording. If this method is not
      * called, the output file will not contain an audio track. Call this after
      * setOutputFormat() but before prepare().
@@ -441,6 +462,10 @@
      * @see android.media.MediaRecorder.OnInfoListener
      */
     public static final int MEDIA_RECORDER_INFO_MAX_DURATION_REACHED = 800;
+    /** A maximum filesize had been setup and has now been reached.
+     * @see android.media.MediaRecorder.OnInfoListener
+     */
+    public static final int MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED = 801;
 
     /**
      * Interface definition for a callback to be invoked when an error
@@ -455,6 +480,8 @@
          * @param what    the type of error that has occurred:
          * <ul>
          * <li>{@link #MEDIA_RECORDER_INFO_UNKNOWN}
+         * <li>{@link #MEDIA_RECORDER_INFO_MAX_DURATION_REACHED}
+         * <li>{@link #MEDIA_RECORDER_INFO_MAX_FILESIZE_REACHED}
          * </ul>
          * @param extra   an extra code, specific to the error type
          */
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index 1e508d2..209b09f 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -268,6 +268,19 @@
 }
 
 static void
+android_media_MediaRecorder_setMaxFileSize(
+        JNIEnv *env, jobject thiz, jlong max_filesize_bytes)
+{
+    LOGV("setMaxFileSize(%lld)", max_filesize_bytes);
+    sp<MediaRecorder> mr = getMediaRecorder(env, thiz);
+
+    char params[64];
+    sprintf(params, "max-filesize=%lld", max_filesize_bytes);
+
+    process_media_recorder_call(env, mr->setParameters(String8(params)), "java/lang/RuntimeException", "setMaxFileSize failed.");
+}
+
+static void
 android_media_MediaRecorder_prepare(JNIEnv *env, jobject thiz)
 {
     LOGV("prepare");
@@ -370,6 +383,7 @@
     {"setVideoSize",         "(II)V",                           (void *)android_media_MediaRecorder_setVideoSize},
     {"setVideoFrameRate",    "(I)V",                            (void *)android_media_MediaRecorder_setVideoFrameRate},
     {"setMaxDuration",       "(I)V",                            (void *)android_media_MediaRecorder_setMaxDuration},
+    {"setMaxFileSize",       "(J)V",                            (void *)android_media_MediaRecorder_setMaxFileSize},
     {"_prepare",             "()V",                             (void *)android_media_MediaRecorder_prepare},
     {"getMaxAmplitude",      "()I",                             (void *)android_media_MediaRecorder_native_getMaxAmplitude},
     {"start",                "()V",                             (void *)android_media_MediaRecorder_start},
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index d26b0c5..7537ddf 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -387,12 +387,10 @@
     LOGV("flush");
 
     if (!mActive) {
-        mCblk->lock.lock();
         mAudioTrack->flush();
         // Release AudioTrack callback thread in case it was waiting for new buffers
         // in AudioTrack::obtainBuffer()
         mCblk->cv.signal();
-        mCblk->lock.unlock();
     }
 }
 
@@ -443,7 +441,7 @@
     if (rate > afSamplingRate*2) rate = afSamplingRate*2;
     if (rate > MAX_SAMPLE_RATE) rate = MAX_SAMPLE_RATE;
 
-    mCblk->sampleRate = rate;
+    mCblk->sampleRate = (uint16_t)rate;
 }
 
 uint32_t AudioTrack::getSampleRate()
diff --git a/media/libmedia/JetPlayer.cpp b/media/libmedia/JetPlayer.cpp
index 2c62104..77a9013 100644
--- a/media/libmedia/JetPlayer.cpp
+++ b/media/libmedia/JetPlayer.cpp
@@ -194,8 +194,15 @@
     }
 
    while (1) {
+    
         mMutex.lock(); // [[[[[[[[ LOCK ---------------------------------------
 
+        if (mEasData == NULL) {
+            mMutex.unlock();
+            LOGV("JetPlayer::render(): NULL EAS data, exiting render.");
+            goto threadExit;
+        }
+            
         // nothing to render, wait for client thread to wake us up
         while (!mRender)
         {
@@ -255,7 +262,10 @@
     }//while (1)
 
 threadExit:
-    mAudioTrack->flush();
+    if (mAudioTrack) {
+        mAudioTrack->stop();
+        mAudioTrack->flush();
+    }
     if (mAudioBuffer) {
         delete [] mAudioBuffer;
         mAudioBuffer = NULL;
diff --git a/media/libmedia/mediarecorder.cpp b/media/libmedia/mediarecorder.cpp
index 23b3b9d..6b26faf 100644
--- a/media/libmedia/mediarecorder.cpp
+++ b/media/libmedia/mediarecorder.cpp
@@ -367,8 +367,9 @@
     status_t ret = mMediaRecorder->setParameters(params);
     if (OK != ret) {
         LOGE("setParameters(%s) failed: %d", params.string(), ret);
-        mCurrentState = MEDIA_RECORDER_ERROR;
-        return ret;
+        // Do not change our current state to MEDIA_RECORDER_ERROR, failures
+        // of the only currently supported parameters, "max-duration" and
+        // "max-filesize" are _not_ fatal.
     }
 
     return ret;
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
index 3c449c9..6edc2cc 100755
--- a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/MediaFrameworkTestRunner.java
@@ -16,12 +16,13 @@
 
 package com.android.mediaframeworktest;
 
-import com.android.mediaframeworktest.functional.MediaPlayerApiTest;
-import com.android.mediaframeworktest.functional.SimTonesTest;
-import com.android.mediaframeworktest.functional.MediaMetadataTest;
 import com.android.mediaframeworktest.functional.CameraTest;
-import com.android.mediaframeworktest.functional.MediaRecorderTest;
 import com.android.mediaframeworktest.functional.MediaAudioTrackTest;
+import com.android.mediaframeworktest.functional.MediaMetadataTest;
+import com.android.mediaframeworktest.functional.MediaMimeTest;
+import com.android.mediaframeworktest.functional.MediaPlayerApiTest;
+import com.android.mediaframeworktest.functional.MediaRecorderTest;
+import com.android.mediaframeworktest.functional.SimTonesTest;
 
 import junit.framework.TestSuite;
 
@@ -50,6 +51,7 @@
         suite.addTestSuite(CameraTest.class);
         suite.addTestSuite(MediaRecorderTest.class);
         suite.addTestSuite(MediaAudioTrackTest.class);
+        suite.addTestSuite(MediaMimeTest.class);
         return suite;
     }
 
diff --git a/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
new file mode 100644
index 0000000..d2809c1
--- /dev/null
+++ b/media/tests/MediaFrameworkTest/src/com/android/mediaframeworktest/functional/MediaMimeTest.java
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.mediaframeworktest.functional;
+
+import java.io.File;
+
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.net.Uri;
+import android.test.ActivityInstrumentationTestCase2;
+import android.test.suitebuilder.annotation.LargeTest;
+import android.test.suitebuilder.annotation.MediumTest;
+import android.test.suitebuilder.annotation.Suppress;
+import android.util.Log;
+import com.android.mediaframeworktest.MediaFrameworkTest;
+
+/*
+ * System tests for the handling of mime type in the media framework.
+ *
+ * To run this test suite:
+     make frameworks/base/media/tests/MediaFrameworkTest
+     make mediaframeworktest
+
+     adb install -r out/target/product/dream/data/app/mediaframeworktest.apk
+
+     adb shell am instrument -e class \
+     com.android.mediaframeworktest.functional.MediaMimeTest \
+     -w com.android.mediaframeworktest/.MediaFrameworkTestRunner
+ *
+ */
+public class MediaMimeTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {    
+    private final String TAG = "MediaMimeTest";
+    private Context mContext;
+    private final String MP3_FILE = "/sdcard/media_api/music/SHORTMP3.mp3";
+    private final String MEDIA_PLAYBACK_NAME = "com.android.music.MediaPlaybackActivity";
+
+    public MediaMimeTest() {
+        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
+    }
+
+    @Override
+    protected void setUp() throws Exception {
+      super.setUp();
+      mContext = getActivity();
+      // Checks you have all the test files on your SDCARD.
+      assertTrue(new File(MP3_FILE).exists());
+    }
+    
+    @Override 
+    protected void tearDown() throws Exception {     
+        super.tearDown();              
+    }
+
+    // ----------------------------------------------------------------------
+    // AUDIO mime type resolution tests.
+
+    @MediumTest
+    // Checks the MediaPlaybackActivity handles audio/mp3.
+    public void testCheckMediaPlaybackHandlesAudioMp3() throws Exception {
+        assertMediaPlaybackActivityHandles("audio/mp3");
+    }
+
+    @MediumTest
+    // Checks the MediaPlaybackActivity handles audio/*.
+    public void testCheckMediaPlaybackHandlesAudio() throws Exception {
+        assertMediaPlaybackActivityHandles("audio/*");
+    }
+
+    @MediumTest
+    // Checks the MediaPlaybackActivity handles application/itunes. Some servers
+    // set the Content-type header to application/iTunes (with capital T, but
+    // the download manager downcasts it) for their MP3 podcasts. This is non
+    // standard but we try to support it anyway.
+    // See bug 1401491
+    public void testCheckMediaPlaybackHandlesApplicationItunes() throws Exception {
+        assertMediaPlaybackActivityHandles("application/itunes");
+    }
+
+    @MediumTest
+    // Checks the activity resolver handling of mime types is case sensitive.
+    // See bug 1710534
+    public void testCheckActivityResolverMimeHandlingIsCaseSensitive() throws Exception {
+        assertNoActivityHandles("AUDIO/MP3");   // <--- look uppercase
+    }
+
+    @MediumTest
+    // Checks the activity resolver does not trims leading whitespaces when
+    // resolving mime types. Trailing whitespaces seems to be non
+    // significant.
+    // See bug 1710534
+    public void testCheckWhiteSpacesInMimeTypeHandling() throws Exception {
+        assertNoActivityHandles(" audio/mp3");
+        assertNoActivityHandles(" audio/mp3 ");
+        assertMediaPlaybackActivityHandles("audio/mp3 ");
+    }
+
+    // @return a ResolveInfo instance for the mime type or null if the type is
+    // not handled by any activity.
+    private ResolveInfo resolveMime(String mime) {
+        Intent viewIntent = new Intent(Intent.ACTION_VIEW);
+        Uri uri = Uri.fromParts("file", MP3_FILE, null);
+
+        viewIntent.setDataAndType(uri, mime);
+        return mContext.getPackageManager().resolveActivity(
+                viewIntent, PackageManager.MATCH_DEFAULT_ONLY);
+    }
+
+    // Helper method to check the media playback activity handles the given mime type.
+    // @param mime type to test for
+    private void assertMediaPlaybackActivityHandles(String mime) throws Exception {
+        ResolveInfo ri = resolveMime(mime);
+
+        assertNotNull(ri);
+        assertEquals(MEDIA_PLAYBACK_NAME, ri.activityInfo.name.toString());
+    }
+
+    // Helper method to check that NO activity handles the given mime type.
+    // @param mime type to test for
+    private void assertNoActivityHandles(String mime) throws Exception {
+        assertNull(resolveMime(mime));
+    }
+}
diff --git a/packages/SettingsProvider/etc/Android.mk b/packages/SettingsProvider/etc/Android.mk
index d73175f..81ca4b1 100644
--- a/packages/SettingsProvider/etc/Android.mk
+++ b/packages/SettingsProvider/etc/Android.mk
@@ -31,17 +31,3 @@
 
 include $(BUILD_PREBUILT)
 
-########################
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := favorites.xml
-
-LOCAL_MODULE_TAGS := user
-
-# This will install the file in /system/etc
-#
-LOCAL_MODULE_CLASS := ETC
-
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-
-include $(BUILD_PREBUILT)
diff --git a/packages/SettingsProvider/etc/favorites.xml b/packages/SettingsProvider/etc/favorites.xml
deleted file mode 100644
index ae74b8e..0000000
--- a/packages/SettingsProvider/etc/favorites.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2009 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.
--->
-
-<favorites>
-    <favorite package="com.android.contacts" class="com.android.contacts.DialtactsActivity" screen="1" x="0" y="3"/>
-    <favorite package="com.android.contacts" class="com.android.contacts.DialtactsContactsEntryActivity" screen="1" x="1" y="3" />
-    <favorite package="com.android.browser" class="com.android.browser.BrowserActivity" screen="1" x="2" y="3" />
-    <favorite package="com.google.android.apps.maps" class="com.google.android.maps.MapsActivity" screen="1" x="3" y="3" />
-    <favorite package="com.android.vending" class="com.android.vending.AssetBrowserActivity" screen="1" x="0" y="2" />
-</favorites>
diff --git a/services/java/com/android/server/BatteryService.java b/services/java/com/android/server/BatteryService.java
index 3a9a59f..73ff501 100644
--- a/services/java/com/android/server/BatteryService.java
+++ b/services/java/com/android/server/BatteryService.java
@@ -176,6 +176,9 @@
     private synchronized final void update() {
         native_update();
 
+        boolean logOutlier = false;
+        long dischargeDuration = 0;
+        
         mBatteryLevelCritical = mBatteryLevel <= CRITICAL_BATTERY_LEVEL;
         if (mAcOnline) {
             mPlugType = BatteryManager.BATTERY_PLUGGED_AC;
@@ -199,13 +202,12 @@
                     // There's no value in this data unless we've discharged at least once and the
                     // battery level has changed; so don't log until it does.
                     if (mDischargeStartTime != 0 && mDischargeStartLevel != mBatteryLevel) {
-                        long duration = SystemClock.elapsedRealtime() - mDischargeStartTime;
-                        EventLog.writeEvent(LOG_BATTERY_DISCHARGE_STATUS, duration,
+                        dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
+                        logOutlier = true;
+                        EventLog.writeEvent(LOG_BATTERY_DISCHARGE_STATUS, dischargeDuration,
                                 mDischargeStartLevel, mBatteryLevel);
                         // make sure we see a discharge event before logging again
                         mDischargeStartTime = 0; 
-                        
-                        logOutlier(duration);
                     }
                 } else if (mPlugType == BATTERY_PLUGGED_NONE) {
                     // charging -> discharging or we just powered up
@@ -231,7 +233,8 @@
                     mPlugType == BATTERY_PLUGGED_NONE) {
                 // We want to make sure we log discharge cycle outliers
                 // if the battery is about to die.
-                logOutlier(SystemClock.elapsedRealtime() - mDischargeStartTime);
+                dischargeDuration = SystemClock.elapsedRealtime() - mDischargeStartTime;
+                logOutlier = true;
             }
             
             mLastBatteryStatus = mBatteryStatus;
@@ -244,6 +247,11 @@
             mLastBatteryLevelCritical = mBatteryLevelCritical;
             
             sendIntent();
+            
+            // This needs to be done after sendIntent() so that we get the lastest battery stats.
+            if (logOutlier && dischargeDuration != 0) {
+                logOutlier(dischargeDuration);
+            }
         }
     }
 
@@ -252,7 +260,7 @@
         Intent intent = new Intent(Intent.ACTION_BATTERY_CHANGED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY);
         try {
-            mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE);
+            mBatteryStats.setOnBattery(mPlugType == BATTERY_PLUGGED_NONE, mBatteryLevel);
         } catch (RemoteException e) {
             // Should never happen.
         }
diff --git a/services/java/com/android/server/HardwareService.java b/services/java/com/android/server/HardwareService.java
index 2131ffd..7466a37 100755
--- a/services/java/com/android/server/HardwareService.java
+++ b/services/java/com/android/server/HardwareService.java
@@ -35,11 +35,23 @@
 public class HardwareService extends IHardwareService.Stub {
     private static final String TAG = "HardwareService";
 
+    static final int LIGHT_ID_BACKLIGHT = 0;
+    static final int LIGHT_ID_KEYBOARD = 1;
+    static final int LIGHT_ID_BUTTONS = 2;
+    static final int LIGHT_ID_BATTERY = 3;
+    static final int LIGHT_ID_NOTIFICATIONS = 4;
+    static final int LIGHT_ID_ATTENTION = 5;
+
+    static final int LIGHT_FLASH_NONE = 0;
+    static final int LIGHT_FLASH_TIMED = 1;
+
     HardwareService(Context context) {
         // Reset the hardware to a default state, in case this is a runtime
         // restart instead of a fresh boot.
         vibratorOff();
 
+        mNativePointer = init_native();
+
         mContext = context;
         PowerManager pm = (PowerManager)context.getSystemService(
                 Context.POWER_SERVICE);
@@ -51,9 +63,18 @@
         context.registerReceiver(mIntentReceiver, filter);
     }
 
+    protected void finalize() throws Throwable {
+        finalize_native(mNativePointer);
+        super.finalize();
+    }
+
     public void vibrate(long milliseconds) {
-        vibratePattern(new long[] { 0, milliseconds }, -1,
-                       new Binder());
+        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.VIBRATE)
+                != PackageManager.PERMISSION_GRANTED) {
+            throw new SecurityException("Requires VIBRATE permission");
+        }
+        doCancelVibrate();
+        vibratorOn(milliseconds);
     }
 
     private boolean isAll0(long[] pattern) {
@@ -164,38 +185,40 @@
         Hardware.enableCameraFlash(milliseconds);
     }
 
-    public void setScreenBacklight(int brightness) {
+    public void setBacklights(int brightness) {
         if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
                 != PackageManager.PERMISSION_GRANTED) {
             throw new SecurityException("Requires HARDWARE_TEST permission");
         }
         // Don't let applications turn the screen all the way off
         brightness = Math.max(brightness, Power.BRIGHTNESS_DIM);
-        Hardware.setScreenBacklight(brightness);
+        setLightBrightness_UNCHECKED(LIGHT_ID_BACKLIGHT, brightness);
+        setLightBrightness_UNCHECKED(LIGHT_ID_KEYBOARD, brightness);
+        setLightBrightness_UNCHECKED(LIGHT_ID_BUTTONS, brightness);
     }
 
-    public void setKeyboardBacklight(boolean on) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        Hardware.setKeyboardBacklight(on);
+    void setLightOff_UNCHECKED(int light) {
+        setLight_native(mNativePointer, light, 0, LIGHT_FLASH_NONE, 0, 0);
     }
 
-    public void setButtonBacklight(boolean on) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        Hardware.setButtonBacklight(on);
+    void setLightBrightness_UNCHECKED(int light, int brightness) {
+        int b = brightness & 0x000000ff;
+        b = 0xff000000 | (b << 16) | (b << 8) | b;
+        setLight_native(mNativePointer, light, b, LIGHT_FLASH_NONE, 0, 0);
     }
 
-    public void setLedState(int colorARGB, int onMS, int offMS) {
-        if (mContext.checkCallingOrSelfPermission(android.Manifest.permission.HARDWARE_TEST) 
-                != PackageManager.PERMISSION_GRANTED) {
-            throw new SecurityException("Requires HARDWARE_TEST permission");
-        }
-        Hardware.setLedState(colorARGB, onMS, offMS);
+    void setLightColor_UNCHECKED(int light, int color) {
+        setLight_native(mNativePointer, light, color, LIGHT_FLASH_NONE, 0, 0);
+    }
+
+    void setLightFlashing_UNCHECKED(int light, int color, int mode, int onMS, int offMS) {
+        setLight_native(mNativePointer, light, color, mode, onMS, offMS);
+    }
+
+    public void setAttentionLight(boolean on) {
+        // Not worthy of a permission.  We shouldn't have a flashlight permission.
+        setLight_native(mNativePointer, LIGHT_ID_ATTENTION, on ? 0xffffffff : 0,
+                LIGHT_FLASH_NONE, 0, 0);
     }
 
     private void doCancelVibrate() {
@@ -206,8 +229,8 @@
                     mThread.notify();
                 }
                 mThread = null;
-                vibratorOff();
             }
+            vibratorOff();
         }
     }
 
@@ -315,6 +338,12 @@
             }
         }
     };
+    
+    private static native int init_native();
+    private static native void finalize_native(int ptr);
+
+    private static native void setLight_native(int ptr, int light, int color, int mode,
+            int onMS, int offMS);
 
     private Context mContext;
     private PowerManager.WakeLock mWakeLock;
@@ -323,6 +352,8 @@
     volatile Death mDeath;
     volatile IBinder mToken;
 
+    private int mNativePointer;
+
     native static void vibratorOn(long milliseconds);
     native static void vibratorOff();
 }
diff --git a/services/java/com/android/server/HeadsetObserver.java b/services/java/com/android/server/HeadsetObserver.java
index 855734d..c9066be 100644
--- a/services/java/com/android/server/HeadsetObserver.java
+++ b/services/java/com/android/server/HeadsetObserver.java
@@ -98,12 +98,12 @@
             sendIntent(isUnplug);
 
             if (isUnplug) {
-                // It often takes >200ms to flush the audio pipeline after apps
-                // pause audio playback, but audio route changes are immediate,
-                // so delay the route change by 400ms.
+                // It can take hundreds of ms flush the audio pipeline after
+                // apps pause audio playback, but audio route changes are
+                // immediate, so delay the route change by 1000ms.
                 // This could be improved once the audio sub-system provides an
                 // interface to clear the audio pipeline.
-                mHandler.sendEmptyMessageDelayed(0, 400);
+                mHandler.sendEmptyMessageDelayed(0, 1000);
             } else {
                 updateAudioRoute();
             }
diff --git a/services/java/com/android/server/InputMethodManagerService.java b/services/java/com/android/server/InputMethodManagerService.java
index 9948322..4198154 100644
--- a/services/java/com/android/server/InputMethodManagerService.java
+++ b/services/java/com/android/server/InputMethodManagerService.java
@@ -308,6 +308,9 @@
                 mScreenOn = true;
             } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) {
                 mScreenOn = false;
+            } else if (intent.getAction().equals(Intent.ACTION_CLOSE_SYSTEM_DIALOGS)) {
+                hideInputMethodMenu();
+                return;
             } else {
                 Log.w(TAG, "Unexpected intent " + intent);
             }
@@ -436,6 +439,7 @@
         IntentFilter screenOnOffFilt = new IntentFilter();
         screenOnOffFilt.addAction(Intent.ACTION_SCREEN_ON);
         screenOnOffFilt.addAction(Intent.ACTION_SCREEN_OFF);
+        screenOnOffFilt.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
         mContext.registerReceiver(new ScreenOnOffReceiver(), screenOnOffFilt);
         
         buildInputMethodListLocked(mMethodList, mMethodMap);
@@ -585,6 +589,8 @@
                         + mCurClient.pid + " uid " + mCurClient.uid);
             }
             mCurClient = null;
+            
+            hideInputMethodMenuLocked();
         }
     }
     
@@ -820,6 +826,7 @@
             mCurToken = null;
         }
         
+        mCurId = null;
         clearCurMethodLocked();
         
         if (reportToClient && mCurClient != null) {
@@ -896,10 +903,12 @@
                 setInputMethodLocked(id);
             } catch (IllegalArgumentException e) {
                 Log.w(TAG, "Unknown input method from prefs: " + id, e);
+                mCurMethodId = null;
                 unbindCurrentMethodLocked(true);
             }
         } else {
             // There is no longer an input method set, so stop any current one.
+            mCurMethodId = null;
             unbindCurrentMethodLocked(true);
         }
     }
@@ -1436,18 +1445,22 @@
     }
     
     void hideInputMethodMenu() {
+        synchronized (mMethodMap) {
+            hideInputMethodMenuLocked();
+        }
+    }
+    
+    void hideInputMethodMenuLocked() {
         if (DEBUG) Log.v(TAG, "Hide switching menu");
 
-        synchronized (mMethodMap) {
-            if (mSwitchingDialog != null) {
-                mSwitchingDialog.dismiss();
-                mSwitchingDialog = null;
-            }
-            
-            mDialogBuilder = null;
-            mItems = null;
-            mIms = null;
+        if (mSwitchingDialog != null) {
+            mSwitchingDialog.dismiss();
+            mSwitchingDialog = null;
         }
+        
+        mDialogBuilder = null;
+        mItems = null;
+        mIms = null;
     }
     
     // ----------------------------------------------------------------------
@@ -1584,7 +1597,7 @@
             }
             p.println("  mInputMethodIcon=" + mInputMethodIcon);
             p.println("  mInputMethodData=" + mInputMethodData);
-            p.println("  mCurrentMethod=" + mCurMethodId);
+            p.println("  mCurMethodId=" + mCurMethodId);
             client = mCurClient;
             p.println("  mCurClient=" + client + " mCurSeq=" + mCurSeq);
             p.println("  mCurFocusedWindow=" + mCurFocusedWindow);
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 63b486c..411cd6b 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -176,7 +176,7 @@
                 keycode, repeatCount,
                 device != null ? device.mMetaKeysState : 0,
                 device != null ? device.id : -1, scancode,
-                flags);
+                flags | KeyEvent.FLAG_FROM_SYSTEM);
     }
     
     Thread mThread = new Thread("InputDeviceReader") {
diff --git a/services/java/com/android/server/LocationManagerService.java b/services/java/com/android/server/LocationManagerService.java
index e48e047..5abf249 100644
--- a/services/java/com/android/server/LocationManagerService.java
+++ b/services/java/com/android/server/LocationManagerService.java
@@ -86,6 +86,7 @@
 public class LocationManagerService extends ILocationManager.Stub
         implements INetworkLocationManager {
     private static final String TAG = "LocationManagerService";
+    private static final boolean LOCAL_LOGV = false;
 
     // Minimum time interval between last known location writes, in milliseconds.
     private static final long MIN_LAST_KNOWN_LOCATION_TIME = 60L * 1000L;
@@ -338,8 +339,8 @@
         }
 
         public void binderDied() {
-            if (Config.LOGD) {
-                Log.d(TAG, "Location listener died");
+            if (LOCAL_LOGV) {
+                Log.v(TAG, "Location listener died");
             }
             synchronized (mLocationListeners) {
                 removeUpdatesLocked(this);
@@ -486,9 +487,9 @@
 
                 String name = subdirs[i].getName();
 
-                if (Config.LOGD) {
-                    Log.d(TAG, "Found dir " + subdirs[i].getAbsolutePath());
-                    Log.d(TAG, "name = " + name);
+                if (LOCAL_LOGV) {
+                    Log.v(TAG, "Found dir " + subdirs[i].getAbsolutePath());
+                    Log.v(TAG, "name = " + name);
                 }
 
                 // Don't create a fake provider if a real provider exists
@@ -551,8 +552,8 @@
         mContext = context;
         mLocationHandler = new LocationWorkerHandler();
 
-        if (Config.LOGD) {
-            Log.d(TAG, "Constructed LocationManager Service");
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "Constructed LocationManager Service");
         }
 
         // Alarm manager, needs to be done before calling loadProviders() below
@@ -731,8 +732,8 @@
     }
 
     private List<String> _getAllProvidersLocked() {
-        if (Config.LOGD) {
-            Log.d(TAG, "getAllProviders");
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "getAllProviders");
         }
         List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
         ArrayList<String> out = new ArrayList<String>(providers.size());
@@ -751,14 +752,14 @@
         } catch (SecurityException se) {
             throw se;
         } catch (Exception e) {
-            Log.e(TAG, "getProviders gotString exception:", e);
+            Log.e(TAG, "getProviders got exception:", e);
             return null;
         }
     }
 
     private List<String> _getProvidersLocked(boolean enabledOnly) {
-        if (Config.LOGD) {
-            Log.d(TAG, "getProviders");
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "getProviders");
         }
         List<LocationProviderImpl> providers = LocationProviderImpl.getProviders();
         ArrayList<String> out = new ArrayList<String>();
@@ -990,8 +991,8 @@
 
     private void requestLocationUpdatesLocked(String provider,
             long minTime, float minDistance, Receiver receiver) {
-        if (Config.LOGD) {
-            Log.d(TAG, "_requestLocationUpdates: listener = " + receiver);
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "_requestLocationUpdates: listener = " + receiver);
         }
 
         LocationProviderImpl impl = LocationProviderImpl.getProvider(provider);
@@ -1088,8 +1089,8 @@
     }
 
     private void removeUpdatesLocked(Receiver receiver) {
-        if (Config.LOGD) {
-            Log.d(TAG, "_removeUpdates: listener = " + receiver);
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "_removeUpdates: listener = " + receiver);
         }
 
         // so wakelock calls will succeed
@@ -1292,8 +1293,8 @@
                     boolean inProximity =
                         alert.isInProximity(latitude, longitude);
                     if (!entered && inProximity) {
-                        if (Config.LOGD) {
-                            Log.i(TAG, "Entered alert");
+                        if (LOCAL_LOGV) {
+                            Log.v(TAG, "Entered alert");
                         }
                         mProximitiesEntered.add(alert);
                         Intent enteredIntent = new Intent();
@@ -1301,8 +1302,8 @@
                         try {
                             intent.send(mContext, 0, enteredIntent, null, null);
                         } catch (PendingIntent.CanceledException e) {
-                            if (Config.LOGD) {
-                                Log.i(TAG, "Canceled proximity alert: " + alert, e);
+                            if (LOCAL_LOGV) {
+                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
                             }
                             if (intentsToRemove == null) {
                                 intentsToRemove = new ArrayList<PendingIntent>();
@@ -1310,8 +1311,8 @@
                             intentsToRemove.add(intent);
                         }
                     } else if (entered && !inProximity) {
-                        if (Config.LOGD) {
-                            Log.i(TAG, "Exited alert");
+                        if (LOCAL_LOGV) {
+                            Log.v(TAG, "Exited alert");
                         }
                         mProximitiesEntered.remove(alert);
                         Intent exitedIntent = new Intent();
@@ -1319,8 +1320,8 @@
                         try {
                             intent.send(mContext, 0, exitedIntent, null, null);
                         } catch (PendingIntent.CanceledException e) {
-                            if (Config.LOGD) {
-                                Log.i(TAG, "Canceled proximity alert: " + alert, e);
+                            if (LOCAL_LOGV) {
+                                Log.v(TAG, "Canceled proximity alert: " + alert, e);
                             }
                             if (intentsToRemove == null) {
                                 intentsToRemove = new ArrayList<PendingIntent>();
@@ -1330,8 +1331,8 @@
                     }
                 } else {
                     // Mark alert for expiration
-                    if (Config.LOGD) {
-                        Log.i(TAG, "Expiring proximity alert: " + alert);
+                    if (LOCAL_LOGV) {
+                        Log.v(TAG, "Expiring proximity alert: " + alert);
                     }
                     if (intentsToRemove == null) {
                         intentsToRemove = new ArrayList<PendingIntent>();
@@ -1387,8 +1388,8 @@
 
     private void addProximityAlertLocked(double latitude, double longitude,
         float radius, long expiration, PendingIntent intent) {
-        if (Config.LOGD) {
-            Log.d(TAG, "addProximityAlert: latitude = " + latitude +
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "addProximityAlert: latitude = " + latitude +
                     ", longitude = " + longitude +
                     ", expiration = " + expiration +
                     ", intent = " + intent);
@@ -1439,8 +1440,8 @@
     }
 
     private void removeProximityAlertLocked(PendingIntent intent) {
-        if (Config.LOGD) {
-            Log.d(TAG, "removeProximityAlert: intent = " + intent);
+        if (LOCAL_LOGV) {
+            Log.v(TAG, "removeProximityAlert: intent = " + intent);
         }
 
         mProximityAlerts.remove(intent);
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index bc4b169..c4b0587 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -38,7 +38,6 @@
 import android.os.Binder;
 import android.os.RemoteException;
 import android.os.Handler;
-import android.os.Hardware;
 import android.os.IBinder;
 import android.os.Message;
 import android.os.Power;
@@ -80,6 +79,7 @@
 
     private WorkerHandler mHandler;
     private StatusBarService mStatusBarService;
+    private HardwareService mHardware;
 
     private NotificationRecord mSoundNotification;
     private AsyncPlayer mSound;
@@ -99,25 +99,11 @@
     private boolean mBatteryFull;
     private NotificationRecord mLedNotification;
     
-    // Low battery - red, blinking on 0.125s every 3 seconds
-    private static final int BATTERY_LOW_ARGB = 0xFFFF0000;
-    private static final int BATTERY_LOW_ON = 125;
-    private static final int BATTERY_LOW_OFF = 2875;
-
-    // Charging Low - red solid on
-    private static final int CHARGING_LOW_ARGB = 0xFFFF0000;
-    private static final int CHARGING_LOW_ON = 0;
-    private static final int CHARGING_LOW_OFF = 0;
-
-    // Charging - orange solid on
-    private static final int CHARGING_ARGB = 0xFFFFFF00;
-    private static final int CHARGING_ON = 0;
-    private static final int CHARGING_OFF = 0;
-
-    // Charging Full - green solid on
-    private static final int CHARGING_FULL_ARGB = 0xFF00FF00;
-    private static final int CHARGING_FULL_ON = 0;
-    private static final int CHARGING_FULL_OFF = 0;
+    private static final int BATTERY_LOW_ARGB = 0xFFFF0000; // Charging Low - red solid on
+    private static final int BATTERY_MEDIUM_ARGB = 0xFFFFFF00;    // Charging - orange solid on
+    private static final int BATTERY_FULL_ARGB = 0xFF00FF00; // Charging Full - green solid on
+    private static final int BATTERY_BLINK_ON = 125;
+    private static final int BATTERY_BLINK_OFF = 2875;
 
     // Tag IDs for EventLog.
     private static final int EVENT_LOG_ENQUEUE = 2750;
@@ -326,10 +312,12 @@
         }
     };
 
-    NotificationManagerService(Context context, StatusBarService statusBar)
+    NotificationManagerService(Context context, StatusBarService statusBar,
+            HardwareService hardware)
     {
         super();
         mContext = context;
+        mHardware = hardware;
         mAm = ActivityManagerNative.getDefault();
         mSound = new AsyncPlayer(TAG);
         mSound.setUsesWakeLock(context);
@@ -830,35 +818,40 @@
     // lock on mNotificationList
     private void updateLightsLocked()
     {
-        // battery low has highest priority, then charging
-        if (mBatteryLow && !mBatteryCharging) {
-            Hardware.setLedState(BATTERY_LOW_ARGB, BATTERY_LOW_ON, BATTERY_LOW_OFF);
+        // Battery low always shows, other states only show if charging.
+        if (mBatteryLow) {
+            mHardware.setLightFlashing_UNCHECKED(HardwareService.LIGHT_ID_BATTERY, BATTERY_LOW_ARGB,
+                    HardwareService.LIGHT_FLASH_TIMED, BATTERY_BLINK_ON, BATTERY_BLINK_OFF);
         } else if (mBatteryCharging) {
-            if (mBatteryLow) {
-                Hardware.setLedState(CHARGING_LOW_ARGB, CHARGING_LOW_ON, CHARGING_LOW_OFF);
-            } else if (mBatteryFull) {
-                Hardware.setLedState(CHARGING_FULL_ARGB, CHARGING_FULL_ON, CHARGING_FULL_OFF);
+            if (mBatteryFull) {
+                mHardware.setLightColor_UNCHECKED(HardwareService.LIGHT_ID_BATTERY,
+                        BATTERY_FULL_ARGB);
             } else {
-                Hardware.setLedState(CHARGING_ARGB, CHARGING_ON, CHARGING_OFF);
+                mHardware.setLightColor_UNCHECKED(HardwareService.LIGHT_ID_BATTERY,
+                        BATTERY_MEDIUM_ARGB);
             }
         } else {
-            // handle notification lights
-            if (mLedNotification == null) {
-                // get next notification, if any
-                int n = mLights.size();
-                if (n > 0) {
-                    mLedNotification = mLights.get(n-1);
-                }
-            }
+            mHardware.setLightOff_UNCHECKED(HardwareService.LIGHT_ID_BATTERY);
+        }
 
-            if (mLedNotification == null) {
-                Hardware.setLedState(0, 0, 0);
-            } else {
-                Hardware.setLedState(mLedNotification.notification.ledARGB,
-                        mLedNotification.notification.ledOnMS,
-                        mLedNotification.notification.ledOffMS);
+        // handle notification lights
+        if (mLedNotification == null) {
+            // get next notification, if any
+            int n = mLights.size();
+            if (n > 0) {
+                mLedNotification = mLights.get(n-1);
             }
         }
+        if (mLedNotification == null) {
+            mHardware.setLightOff_UNCHECKED(HardwareService.LIGHT_ID_NOTIFICATIONS);
+        } else {
+            mHardware.setLightFlashing_UNCHECKED(
+                    HardwareService.LIGHT_ID_NOTIFICATIONS,
+                    mLedNotification.notification.ledARGB,
+                    HardwareService.LIGHT_FLASH_TIMED,
+                    mLedNotification.notification.ledOnMS,
+                    mLedNotification.notification.ledOffMS);
+        }
     }
 
     // lock on mNotificationList
diff --git a/services/java/com/android/server/PackageManagerService.java b/services/java/com/android/server/PackageManagerService.java
index 9f428e9..2cf47df 100644
--- a/services/java/com/android/server/PackageManagerService.java
+++ b/services/java/com/android/server/PackageManagerService.java
@@ -57,7 +57,6 @@
 import android.content.pm.ResolveInfo;
 import android.content.pm.ServiceInfo;
 import android.content.pm.Signature;
-import android.content.pm.PackageParser.Package;
 import android.net.Uri;
 import android.os.Binder;
 import android.os.Bundle;
@@ -129,6 +128,7 @@
     static final int SCAN_FORCE_DEX = 1<<2;
     static final int SCAN_UPDATE_SIGNATURE = 1<<3;
     static final int SCAN_FORWARD_LOCKED = 1<<4;
+    static final int SCAN_NEW_INSTALL = 1<<5;
     
     static final int LOG_BOOT_PROGRESS_PMS_START = 3060;
     static final int LOG_BOOT_PROGRESS_PMS_SYSTEM_SCAN_START = 3070;
@@ -1963,6 +1963,31 @@
                 }
                 removeExisting = true;
             }
+            
+            // Verify that this new package doesn't have any content providers
+            // that conflict with existing packages.  Only do this if the
+            // package isn't already installed, since we don't want to break
+            // things that are installed.
+            if ((scanMode&SCAN_NEW_INSTALL) != 0) {
+                int N = pkg.providers.size();
+                int i;
+                for (i=0; i<N; i++) {
+                    PackageParser.Provider p = pkg.providers.get(i);
+                    String names[] = p.info.authority.split(";");
+                    for (int j = 0; j < names.length; j++) {
+                        if (mProviders.containsKey(names[j])) {
+                            PackageParser.Provider other = mProviders.get(names[j]);
+                            Log.w(TAG, "Can't install because provider name " + names[j] +
+                                    " (in package " + pkg.applicationInfo.packageName +
+                                    ") is already used by "
+                                    + ((other != null && other.component != null)
+                                            ? other.component.getPackageName() : "?"));
+                            mLastScanError = PackageManager.INSTALL_FAILED_CONFLICTING_PROVIDER;
+                            return null;
+                        }
+                    }
+                }
+            }
         }
 
         if (removeExisting) {
@@ -2181,9 +2206,12 @@
                             ", className = " + p.info.name +
                             ", isSyncable = " + p.info.isSyncable);
                     } else {
+                        PackageParser.Provider other = mProviders.get(names[j]);
                         Log.w(TAG, "Skipping provider name " + names[j] +
                               " (in package " + pkg.applicationInfo.packageName +
-                              "): name already used");
+                              "): name already used by "
+                              + ((other != null && other.component != null)
+                                      ? other.component.getPackageName() : "?"));
                     }
                 }
                 if ((parseFlags&PackageParser.PARSE_CHATTY) != 0) {
@@ -3205,7 +3233,7 @@
                 mHandler.removeCallbacks(this);
                 PackageInstalledInfo res;
                 synchronized (mInstallLock) {
-                    res = installPackageLI(packageURI, flags);
+                    res = installPackageLI(packageURI, flags, true);
                 }
                 if (observer != null) {
                     try {
@@ -3246,7 +3274,7 @@
     private void installNewPackageLI(String pkgName,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         // Remember this for later, in case we need to rollback this install
         boolean dataDirExists = (new File(mAppDataDir, pkgName)).exists();
@@ -3270,7 +3298,8 @@
                 destResourceFile, pkg, 0,
                 SCAN_MONITOR | SCAN_FORCE_DEX
                 | SCAN_UPDATE_SIGNATURE 
-                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
+                | (newInstall ? SCAN_NEW_INSTALL : 0));
         if (newPackage == null) {
             Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -3302,7 +3331,7 @@
     private void replacePackageLI(String pkgName,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         PackageParser.Package deletedPackage;
         // First find the old package info and check signatures
@@ -3317,17 +3346,19 @@
         if(sysPkg) {
             replaceSystemPackageLI(deletedPackage, 
                     tmpPackageFile, destFilePath, 
-                    destPackageFile, destResourceFile, pkg, forwardLocked, res);
+                    destPackageFile, destResourceFile, pkg, forwardLocked,
+                    newInstall, res);
         } else {
             replaceNonSystemPackageLI(deletedPackage, tmpPackageFile, destFilePath, 
-                    destPackageFile, destResourceFile, pkg, forwardLocked, res);
+                    destPackageFile, destResourceFile, pkg, forwardLocked,
+                    newInstall, res);
         }
     }
     
     private void replaceNonSystemPackageLI(PackageParser.Package deletedPackage,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         String pkgName = deletedPackage.packageName;
@@ -3347,7 +3378,8 @@
                     destResourceFile, pkg, parseFlags,
                     SCAN_MONITOR | SCAN_FORCE_DEX
                     | SCAN_UPDATE_SIGNATURE 
-                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
+                    | (newInstall ? SCAN_NEW_INSTALL : 0));
             if (newPackage == null) {
                     Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
                 if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -3404,7 +3436,7 @@
                         Uri.fromFile(new File(deletedPackage.mPath)),
                         isForwardLocked(deletedPackage)
                         ? PackageManager.FORWARD_LOCK_PACKAGE
-                                : 0);
+                                : 0, false);
             }
         }
     }
@@ -3412,7 +3444,7 @@
     private void replaceSystemPackageLI(PackageParser.Package deletedPackage,
             File tmpPackageFile, 
             String destFilePath, File destPackageFile, File destResourceFile,
-            PackageParser.Package pkg, boolean forwardLocked,
+            PackageParser.Package pkg, boolean forwardLocked, boolean newInstall,
             PackageInstalledInfo res) {
         PackageParser.Package newPackage = null;
         boolean updatedSettings = false;
@@ -3450,7 +3482,8 @@
                 destResourceFile, pkg, parseFlags,
                 SCAN_MONITOR | SCAN_FORCE_DEX
                 | SCAN_UPDATE_SIGNATURE 
-                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                | (forwardLocked ? SCAN_FORWARD_LOCKED : 0)
+                | (newInstall ? SCAN_NEW_INSTALL : 0));
         if (newPackage == null) {
             Log.w(TAG, "Package couldn't be installed in " + destPackageFile);
             if ((res.returnCode=mLastScanError) == PackageManager.INSTALL_SUCCEEDED) {
@@ -3484,8 +3517,7 @@
                     oldPkgSetting.resourcePath,
                     oldPkg, parseFlags,
                     SCAN_MONITOR
-                    | SCAN_UPDATE_SIGNATURE
-                    | (forwardLocked ? SCAN_FORWARD_LOCKED : 0));
+                    | SCAN_UPDATE_SIGNATURE);
             // Restore the old system information in Settings
             synchronized(mPackages) {
                 if(updatedSettings) {
@@ -3556,7 +3588,8 @@
         }
     }
     
-    private PackageInstalledInfo installPackageLI(Uri pPackageURI, int pFlags) {
+    private PackageInstalledInfo installPackageLI(Uri pPackageURI,
+            int pFlags, boolean newInstall) {
         File tmpPackageFile = null;
         String pkgName = null;
         boolean forwardLocked = false;
@@ -3669,21 +3702,21 @@
                 replacePackageLI(pkgName,
                         tmpPackageFile, 
                         destFilePath, destPackageFile, destResourceFile,
-                        pkg, forwardLocked,
+                        pkg, forwardLocked, newInstall,
                         res);
             } else {
                 installNewPackageLI(pkgName,
                         tmpPackageFile, 
                         destFilePath, destPackageFile, destResourceFile,
-                        pkg, forwardLocked,
+                        pkg, forwardLocked, newInstall,
                         res);
             }
         } finally {
             if (tmpPackageFile != null && tmpPackageFile.exists()) {
                 tmpPackageFile.delete();
             }
-            return res;
         }
+        return res;
     }
     
     private int setPermissionsLI(String pkgName,
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index ad30ffc..5c7ab93 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -154,6 +154,7 @@
     private final LockList mLocks = new LockList();
     private Intent mScreenOffIntent;
     private Intent mScreenOnIntent;
+    private HardwareService mHardware;
     private Context mContext;
     private UnsynchronizedWakeLock mBroadcastWakeLock;
     private UnsynchronizedWakeLock mStayOnWhilePluggedInScreenDimLock;
@@ -164,11 +165,11 @@
     private TimeoutTask mTimeoutTask = new TimeoutTask();
     private LightAnimator mLightAnimator = new LightAnimator();
     private final BrightnessState mScreenBrightness
-            = new BrightnessState(Power.SCREEN_LIGHT);
+            = new BrightnessState(SCREEN_BRIGHT_BIT);
     private final BrightnessState mKeyboardBrightness
-            = new BrightnessState(Power.KEYBOARD_LIGHT);
+            = new BrightnessState(KEYBOARD_BRIGHT_BIT);
     private final BrightnessState mButtonBrightness
-            = new BrightnessState(Power.BUTTON_LIGHT);
+            = new BrightnessState(BUTTON_BRIGHT_BIT);
     private boolean mIsPowered = false;
     private IActivityManager mActivityService;
     private IBatteryStats mBatteryStats;
@@ -357,7 +358,9 @@
 
     private ContentQueryMap mSettings;
 
-    void init(Context context, IActivityManager activity, BatteryService battery) {
+    void init(Context context, HardwareService hardware, IActivityManager activity,
+            BatteryService battery) {
+        mHardware = hardware;
         mContext = context;
         mActivityService = activity;
         mBatteryStats = BatteryStatsService.getService();
@@ -1226,10 +1229,7 @@
             }
 
             if (mPowerState != newState) {
-                err = updateLightsLocked(newState, 0);
-                if (err != 0) {
-                    return;
-                }
+                updateLightsLocked(newState, 0);
                 mPowerState = (mPowerState & ~LIGHTS_MASK) | (newState & LIGHTS_MASK);
             }
 
@@ -1327,11 +1327,11 @@
                 mBatteryService.getBatteryLevel() <= Power.LOW_BATTERY_THRESHOLD);
     }
 
-    private int updateLightsLocked(int newState, int forceState) {
+    private void updateLightsLocked(int newState, int forceState) {
         int oldState = mPowerState;
         int difference = (newState ^ oldState) | forceState;
         if (difference == 0) {
-            return 0;
+            return;
         }
         
         int offMask = 0;
@@ -1353,9 +1353,9 @@
                 startAnimation = true;
             } else {
                 if ((newState & KEYBOARD_BRIGHT_BIT) == 0) {
-                    offMask |= Power.KEYBOARD_LIGHT;
+                    offMask |= KEYBOARD_BRIGHT_BIT;
                 } else {
-                    onMask |= Power.KEYBOARD_LIGHT;
+                    onMask |= KEYBOARD_BRIGHT_BIT;
                 }
             }
         }
@@ -1372,9 +1372,9 @@
                 startAnimation = true;
             } else {
                 if ((newState & BUTTON_BRIGHT_BIT) == 0) {
-                    offMask |= Power.BUTTON_LIGHT;
+                    offMask |= BUTTON_BRIGHT_BIT;
                 } else {
-                    onMask |= Power.BUTTON_LIGHT;
+                    onMask |= BUTTON_BRIGHT_BIT;
                 }
             }
         }
@@ -1428,12 +1428,12 @@
                 if ((newState & SCREEN_BRIGHT_BIT) == 0) {
                     // dim or turn off backlight, depending on if the screen is on
                     if ((newState & SCREEN_ON_BIT) == 0) {
-                        offMask |= Power.SCREEN_LIGHT;
+                        offMask |= SCREEN_BRIGHT_BIT;
                     } else {
-                        dimMask |= Power.SCREEN_LIGHT;
+                        dimMask |= SCREEN_BRIGHT_BIT;
                     }
                 } else {
-                    onMask |= Power.SCREEN_LIGHT;
+                    onMask |= SCREEN_BRIGHT_BIT;
                 }
             }
         }
@@ -1446,10 +1446,9 @@
             mHandler.post(mLightAnimator);
         }
         
-        int err = 0;
         if (offMask != 0) {
             //Log.i(TAG, "Setting brightess off: " + offMask);
-            err |= Power.setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
+            setLightBrightness(offMask, Power.BRIGHTNESS_OFF);
         }
         if (dimMask != 0) {
             int brightness = Power.BRIGHTNESS_DIM;
@@ -1458,7 +1457,7 @@
                 brightness = Power.BRIGHTNESS_LOW_BATTERY;
             }
             //Log.i(TAG, "Setting brightess dim " + brightness + ": " + offMask);
-            err |= Power.setLightBrightness(dimMask, brightness);
+            setLightBrightness(dimMask, brightness);
         }
         if (onMask != 0) {
             int brightness = getPreferredBrightness();
@@ -1467,10 +1466,20 @@
                 brightness = Power.BRIGHTNESS_LOW_BATTERY;
             }
             //Log.i(TAG, "Setting brightess on " + brightness + ": " + onMask);
-            err |= Power.setLightBrightness(onMask, brightness);
+            setLightBrightness(onMask, brightness);
         }
+    }
 
-        return err;
+    private void setLightBrightness(int mask, int value) {
+        if ((mask & SCREEN_BRIGHT_BIT) != 0) {
+            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BACKLIGHT, value);
+        }
+        if ((mask & BUTTON_BRIGHT_BIT) != 0) {
+            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_BUTTONS, value);
+        }
+        if ((mask & KEYBOARD_BRIGHT_BIT) != 0) {
+            mHardware.setLightBrightness_UNCHECKED(HardwareService.LIGHT_ID_KEYBOARD, value);
+        }
     }
 
     class BrightnessState {
@@ -1530,10 +1539,10 @@
                 }
             }
             //Log.i(TAG, "Animating brightess " + curIntValue + ": " + mask);
-            Power.setLightBrightness(mask, curIntValue);
+            setLightBrightness(mask, curIntValue);
             animating = more;
             if (!more) {
-                if (mask == Power.SCREEN_LIGHT && curIntValue == Power.BRIGHTNESS_OFF) {
+                if (mask == SCREEN_BRIGHT_BIT && curIntValue == Power.BRIGHTNESS_OFF) {
                     screenOffFinishedAnimating(mOffBecauseOfUser);
                 }
             }
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index a629ec6..1f508a6 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -86,6 +86,7 @@
         int factoryTest = "".equals(factoryTestStr) ? SystemServer.FACTORY_TEST_OFF
                 : Integer.parseInt(factoryTestStr);
 
+        HardwareService hardware = null;
         PowerManagerService power = null;
         IPackageManager pm = null;
         Context context = null;
@@ -127,9 +128,13 @@
             BatteryService battery = new BatteryService(context);
             ServiceManager.addService("battery", battery);
 
+            Log.i(TAG, "Starting Hardware Service.");
+            hardware = new HardwareService(context);
+            ServiceManager.addService("hardware", hardware);
+
             // only initialize the power service after we have started the
-            // content providers and the batter service.
-            power.init(context, ActivityManagerService.getDefault(), battery);
+            // hardware service, content providers and the battery service.
+            power.init(context, hardware, ActivityManagerService.getDefault(), battery);
 
             Log.i(TAG, "Starting Alarm Manager.");
             AlarmManagerService alarm = new AlarmManagerService(context);
@@ -171,7 +176,7 @@
                 int bluetoothOn = Settings.Secure.getInt(mContentResolver,
                     Settings.Secure.BLUETOOTH_ON, 0);
                 if (bluetoothOn > 0) {
-                    bluetooth.enable(null);
+                    bluetooth.enable();
                 }
             }
 
@@ -208,13 +213,6 @@
             }
 
             try {
-                Log.i(TAG, "Starting Hardware Service.");
-                ServiceManager.addService("hardware", new HardwareService(context));
-            } catch (Throwable e) {
-                Log.e(TAG, "Failure starting Hardware Service", e);
-            }
-
-            try {
                 Log.i(TAG, "Starting NetStat Service.");
                 ServiceManager.addService("netstat", new NetStatService(context));
             } catch (Throwable e) {
@@ -232,7 +230,7 @@
             try {
                 Log.i(TAG, "Starting Notification Manager.");
                 ServiceManager.addService(Context.NOTIFICATION_SERVICE,
-                        new NotificationManagerService(context, statusBar));
+                        new NotificationManagerService(context, statusBar, hardware));
             } catch (Throwable e) {
                 Log.e(TAG, "Failure starting Notification Manager", e);
             }
diff --git a/services/java/com/android/server/ViewServer.java b/services/java/com/android/server/ViewServer.java
index 4201b39..07826a6 100644
--- a/services/java/com/android/server/ViewServer.java
+++ b/services/java/com/android/server/ViewServer.java
@@ -24,6 +24,9 @@
 import java.io.IOException;
 import java.io.BufferedReader;
 import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.BufferedWriter;
+import java.io.OutputStreamWriter;
 
 /**
  * The ViewServer is local socket server that can be used to communicate with the
@@ -41,7 +44,14 @@
     // Debug facility
     private static final String LOG_TAG = "ViewServer";
 
+    private static final String VALUE_PROTOCOL_VERSION = "2";
+    private static final String VALUE_SERVER_VERSION = "2";
+
     // Protocol commands
+    // Returns the protocol version
+    private static final String COMMAND_PROTOCOL_VERSION = "PROTOCOL";
+    // Returns the server version
+    private static final String COMMAND_SERVER_VERSION = "SERVER";
     // Lists all of the available windows in the system
     private static final String COMMAND_WINDOW_MANAGER_LIST = "LIST";
 
@@ -169,7 +179,11 @@
                     }
 
                     boolean result;
-                    if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {
+                    if (COMMAND_PROTOCOL_VERSION.equalsIgnoreCase(command)) {
+                        result = writeValue(client, VALUE_PROTOCOL_VERSION);
+                    } else if (COMMAND_SERVER_VERSION.equalsIgnoreCase(command)) {
+                        result = writeValue(client, VALUE_SERVER_VERSION);
+                    } else if (COMMAND_WINDOW_MANAGER_LIST.equalsIgnoreCase(command)) {
                         result = mWindowManager.viewServerListWindows(client);
                     } else {
                         result = mWindowManager.viewServerWindowCommand(client,
@@ -197,4 +211,28 @@
             }
         }
     }
+
+    private static boolean writeValue(Socket client, String value) {
+        boolean result;
+        BufferedWriter out = null;
+        try {
+            OutputStream clientStream = client.getOutputStream();
+            out = new BufferedWriter(new OutputStreamWriter(clientStream), 8 * 1024);
+            out.write(value);
+            out.write("\n");
+            out.flush();
+            result = true;
+        } catch (Exception e) {
+            result = false;
+        } finally {
+            if (out != null) {
+                try {
+                    out.close();
+                } catch (IOException e) {
+                    result = false;
+                }
+            }
+        }
+        return result;
+    }
 }
diff --git a/services/java/com/android/server/WifiService.java b/services/java/com/android/server/WifiService.java
index e298f49..ddf92e2 100644
--- a/services/java/com/android/server/WifiService.java
+++ b/services/java/com/android/server/WifiService.java
@@ -50,6 +50,7 @@
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.util.Log;
+import android.telephony.TelephonyManager;
 import android.text.TextUtils;
 
 import java.util.ArrayList;
@@ -62,6 +63,10 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 
+import com.android.internal.app.IBatteryStats;
+import com.android.internal.os.BatteryStatsImpl;
+import com.android.server.am.BatteryStatsService;
+
 /**
  * WifiService handles remote WiFi operation requests by implementing
  * the IWifiManager interface. It also creates a WifiMonitor to listen
@@ -86,6 +91,9 @@
     private int mPluggedType;
 
     private final LockList mLocks = new LockList();
+
+    private final IBatteryStats mBatteryStats;
+    
     /**
      * See {@link Settings.Gservices#WIFI_IDLE_MS}. This is the default value if a
      * Settings.Gservices value is not present. This timeout value is chosen as
@@ -168,7 +176,8 @@
     WifiService(Context context, WifiStateTracker tracker) {
         mContext = context;
         mWifiStateTracker = tracker;
-
+        mBatteryStats = BatteryStatsService.getService();
+        
         /*
          * Initialize the hidden-networks state
          */
@@ -532,6 +541,18 @@
     private void setWifiEnabledState(int wifiState) {
         final int previousWifiState = mWifiState;
 
+        long ident = Binder.clearCallingIdentity();
+        try {
+            if (wifiState == WIFI_STATE_ENABLED) {
+                mBatteryStats.noteWifiOn();
+            } else if (wifiState == WIFI_STATE_DISABLED) {
+                mBatteryStats.noteWifiOff();
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
         // Update state
         mWifiState = wifiState;
 
@@ -1828,6 +1849,19 @@
 
     private boolean acquireWifiLockLocked(WifiLock wifiLock) {
         mLocks.addLock(wifiLock);
+        
+        int uid = Binder.getCallingUid();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            switch(wifiLock.mLockMode) {
+            case (WifiManager.WIFI_MODE_FULL): mBatteryStats.noteFullWifiLockAcquired(uid);
+            case (WifiManager.WIFI_MODE_SCAN_ONLY): mBatteryStats.noteScanWifiLockAcquired(uid);
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
         updateWifiState();
         return true;
     }
@@ -1841,7 +1875,22 @@
 
     private boolean releaseWifiLockLocked(IBinder lock) {
         boolean result;
-        result = (mLocks.removeLock(lock) != null);
+        
+        WifiLock wifiLock = mLocks.removeLock(lock);
+        result = (wifiLock != null);
+        
+        int uid = Binder.getCallingUid();
+        long ident = Binder.clearCallingIdentity();
+        try {
+            switch(wifiLock.mLockMode) {
+            case (WifiManager.WIFI_MODE_FULL): mBatteryStats.noteFullWifiLockReleased(uid);
+            case (WifiManager.WIFI_MODE_SCAN_ONLY): mBatteryStats.noteScanWifiLockReleased(uid);
+            }
+        } catch (RemoteException e) {
+        } finally {
+            Binder.restoreCallingIdentity(ident);
+        }
+        
         updateWifiState();
         return result;
     }
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index e4bd3c3..5623b02 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -1294,7 +1294,7 @@
             // Update Orientation after adding a window, only if the window needs to be
             // displayed right away
             if (win.isVisibleOrAdding()) {
-                if (updateOrientationFromAppTokens(null) != null) {
+                if (updateOrientationFromAppTokens(null, null) != null) {
                     sendNewConfiguration();
                 }
             }
@@ -1663,7 +1663,7 @@
             if (assignLayers) {
                 assignLayersLocked();
             }
-            newConfig = updateOrientationFromAppTokensLocked(null);
+            newConfig = updateOrientationFromAppTokensLocked(null, null);
             performLayoutAndPlaceSurfacesLocked();
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -2079,6 +2079,11 @@
             while (pos >= 0) {
                 AppWindowToken wtoken = mAppTokens.get(pos);
                 pos--;
+                // if we're about to tear down this window, don't use it for orientation
+                if (!wtoken.hidden && wtoken.hiddenRequested) {
+                    continue;
+                }
+
                 if (!haveGroup) {
                     // We ignore any hidden applications on the top.
                     if (wtoken.hiddenRequested || wtoken.willBeHidden) {
@@ -2119,11 +2124,11 @@
     }
     
     public Configuration updateOrientationFromAppTokens(
-        IBinder freezeThisOneIfNeeded) {
+            Configuration currentConfig, IBinder freezeThisOneIfNeeded) {
         Configuration config;
         long ident = Binder.clearCallingIdentity();
         synchronized(mWindowMap) {
-            config = updateOrientationFromAppTokensLocked(freezeThisOneIfNeeded);
+            config = updateOrientationFromAppTokensLocked(currentConfig, freezeThisOneIfNeeded);
         }
         if (config != null) {
             mLayoutNeeded = true;
@@ -2141,7 +2146,7 @@
      * android.os.IBinder)
      */
     Configuration updateOrientationFromAppTokensLocked(
-            IBinder freezeThisOneIfNeeded) {
+            Configuration appConfig, IBinder freezeThisOneIfNeeded) {
         boolean changed = false;
         long ident = Binder.clearCallingIdentity();
         try {
@@ -2170,6 +2175,15 @@
                     return computeNewConfiguration();
                 }
             }
+
+            // No obvious action we need to take, but if our current
+            // state mismatches the activity maanager's, update it
+            if (appConfig != null) {
+                Configuration wmConfig = computeNewConfiguration();
+                if (wmConfig.diff(appConfig) != 0) {
+                    return wmConfig;
+                }
+            }
         } finally {
             Binder.restoreCallingIdentity(ident);
         }
@@ -4053,7 +4067,7 @@
         if (downTime == 0) downTime = eventTime;
 
         KeyEvent newEvent = new KeyEvent(downTime, eventTime, action, code, repeatCount, metaState,
-                deviceId, scancode);
+                deviceId, scancode, KeyEvent.FLAG_FROM_SYSTEM);
 
         boolean result = dispatchKey(newEvent, Binder.getCallingPid(), Binder.getCallingUid());
         if (sync) {
@@ -5107,7 +5121,7 @@
                         if (DEBUG_INPUT) Log.v(
                             TAG, "Key repeat: count=" + keyRepeatCount
                             + ", next @ " + nextKeyTime);
-                        dispatchKey(new KeyEvent(lastKey, curTime, keyRepeatCount), 0, 0);
+                        dispatchKey(KeyEvent.changeTimeRepeat(lastKey, curTime, keyRepeatCount), 0, 0);
                         
                     } else {
                         curTime = SystemClock.uptimeMillis();
@@ -5361,6 +5375,7 @@
         final Session mSession;
         final IWindow mClient;
         WindowToken mToken;
+        WindowToken mRootToken;
         AppWindowToken mAppToken;
         AppWindowToken mTargetAppToken;
         final WindowManager.LayoutParams mAttrs = new WindowManager.LayoutParams();
@@ -5573,6 +5588,7 @@
                 }
                 appToken = parent;
             }
+            mRootToken = appToken;
             mAppToken = appToken.appWindowToken;
 
             mSurface = null;
@@ -6231,7 +6247,7 @@
          */
         boolean isVisibleNow() {
             return mSurface != null && mPolicyVisibility && !mAttachedHidden
-                    && !mToken.hidden && !mExiting && !mDestroying;
+                    && !mRootToken.hidden && !mExiting && !mDestroying;
         }
 
         /**
@@ -6272,7 +6288,7 @@
             final AppWindowToken atoken = mAppToken;
             final boolean animating = atoken != null ? atoken.animating : false;
             return mSurface != null && mPolicyVisibility && !mDestroying
-                    && ((!mAttachedHidden && !mToken.hidden)
+                    && ((!mAttachedHidden && !mRootToken.hidden)
                             || mAnimating || animating);
         }
 
@@ -6431,6 +6447,7 @@
                   + " mLastLayer=" + mLastLayer);
             pw.println(prefix + "mSurface=" + mSurface);
             pw.println(prefix + "mToken=" + mToken);
+            pw.println(prefix + "mRootToken=" + mRootToken);
             pw.println(prefix + "mAppToken=" + mAppToken);
             pw.println(prefix + "mTargetAppToken=" + mTargetAppToken);
             pw.println(prefix + "mViewVisibility=0x" + Integer.toHexString(mViewVisibility)
@@ -7279,7 +7296,7 @@
                 }
                 
                 case COMPUTE_AND_SEND_NEW_CONFIGURATION: {
-                    if (updateOrientationFromAppTokens(null) != null) {
+                    if (updateOrientationFromAppTokens(null, null) != null) {
                         sendNewConfiguration();
                     }
                     break;
@@ -7458,7 +7475,7 @@
     
                 boolean gone = win.mViewVisibility == View.GONE
                         || !win.mRelayoutCalled
-                        || win.mToken.hidden;
+                        || win.mRootToken.hidden;
 
                 // If this view is GONE, then skip it -- keep the current
                 // frame, and let the caller know so they can ignore it
diff --git a/services/java/com/android/server/am/ActivityManagerService.java b/services/java/com/android/server/am/ActivityManagerService.java
index 9d720d1..9e2ecba 100644
--- a/services/java/com/android/server/am/ActivityManagerService.java
+++ b/services/java/com/android/server/am/ActivityManagerService.java
@@ -121,6 +121,7 @@
     static final boolean DEBUG_VISBILITY = localLOGV || false;
     static final boolean DEBUG_PROCESSES = localLOGV || false;
     static final boolean DEBUG_USER_LEAVING = localLOGV || false;
+    static final boolean DEBUG_RESULTS = localLOGV || false;
     static final boolean VALIDATE_TOKENS = false;
     static final boolean SHOW_ACTIVITY_START_TIME = true;
     
@@ -1536,6 +1537,7 @@
         // just restarting it anyway.
         if (checkConfig) {
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    mConfiguration,
                     r.mayFreezeScreenLocked(app) ? r : null);
             updateConfigurationLocked(config, r);
         }
@@ -2336,6 +2338,7 @@
             // Have the window manager re-evaluate the orientation of
             // the screen based on the new activity order.
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    mConfiguration,
                     next.mayFreezeScreenLocked(next.app) ? next : null);
             if (config != null) {
                 next.frozenBeforeDestroy = true;
@@ -2364,7 +2367,7 @@
                 if (a != null) {
                     final int N = a.size();
                     if (!next.finishing && N > 0) {
-                        if (localLOGV) Log.v(
+                        if (DEBUG_RESULTS) Log.v(
                                 TAG, "Delivering results to " + next
                                 + ": " + a);
                         next.app.thread.scheduleSendResult(next, a);
@@ -2701,7 +2704,7 @@
         HistoryRecord resultRecord = null;
         if (resultTo != null) {
             int index = indexOfTokenLocked(resultTo, false);
-            if (localLOGV) Log.v(
+            if (DEBUG_RESULTS) Log.v(
                 TAG, "Sending result to " + resultTo + " (index " + index + ")");
             if (index >= 0) {
                 sourceRecord = (HistoryRecord)mHistory.get(index);
@@ -3358,6 +3361,7 @@
             final long origId = Binder.clearCallingIdentity();
             mWindowManager.setAppOrientation(r, requestedOrientation);
             Configuration config = mWindowManager.updateOrientationFromAppTokens(
+                    mConfiguration,
                     r.mayFreezeScreenLocked(r.app) ? r : null);
             if (config != null) {
                 r.frozenBeforeDestroy = true;
@@ -3486,7 +3490,7 @@
         // send the result
         HistoryRecord resultTo = r.resultTo;
         if (resultTo != null) {
-            if (localLOGV) Log.v(TAG, "Adding result to " + resultTo);
+            if (DEBUG_RESULTS) Log.v(TAG, "Adding result to " + resultTo);
             if (r.info.applicationInfo.uid > 0) {
                 grantUriPermissionFromIntentLocked(r.info.applicationInfo.uid,
                         r.packageName, resultData, r);
@@ -3652,6 +3656,9 @@
                     data, r);
         }
 
+        if (DEBUG_RESULTS) Log.v(TAG, "Send activity result to " + r
+                + " : who=" + resultWho + " req=" + requestCode
+                + " res=" + resultCode + " data=" + data);
         if (mResumedActivity == r && r.app != null && r.app.thread != null) {
             try {
                 ArrayList<ResultInfo> list = new ArrayList<ResultInfo>();
@@ -9013,7 +9020,7 @@
         }
 
         r.app = app;
-        r.restartTime = SystemClock.uptimeMillis();
+        r.restartTime = r.lastActivity = SystemClock.uptimeMillis();
 
         app.services.add(r);
         bumpServiceExecutingLocked(r);
@@ -10133,8 +10140,19 @@
             // installed.  Maybe in the future we want to have a special install
             // broadcast or such for apps, but we'd like to deliberately make
             // this decision.
-            String skipPackage = (intent.ACTION_PACKAGE_ADDED.equals(
-                    intent.getAction()) && intent.getData() != null)
+            boolean skip = false;
+            if (intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) {
+                // If this is replacing an existing package, then we allow it
+                // to see the broadcast for it to restart itself.
+                if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
+                    skip = true;
+                }
+            } else if (intent.ACTION_PACKAGE_RESTARTED.equals(intent.getAction())) {
+                skip = true;
+            } else if (intent.ACTION_PACKAGE_DATA_CLEARED.equals(intent.getAction())) {
+                skip = true;
+            }
+            String skipPackage = (skip && intent.getData() != null)
                     ? intent.getData().getSchemeSpecificPart()
                     : null;
             if (skipPackage != null && receivers != null) {
@@ -11306,6 +11324,10 @@
                         // XXX should compute this based on the max of
                         // all connected clients.
                         ConnectionRecord cr = kt.next();
+                        if (cr.binding.client == app) {
+                            // Binding to ourself is not interesting.
+                            continue;
+                        }
                         if ((cr.flags&Context.BIND_AUTO_CREATE) != 0) {
                             ProcessRecord client = cr.binding.client;
                             int myHiddenAdj = hiddenAdj;
@@ -11352,6 +11374,10 @@
                     Iterator<ProcessRecord> kt = cpr.clients.iterator();
                     while (kt.hasNext() && adj > FOREGROUND_APP_ADJ) {
                         ProcessRecord client = kt.next();
+                        if (client == app) {
+                            // Being our own client is not interesting.
+                            continue;
+                        }
                         int myHiddenAdj = hiddenAdj;
                         if (myHiddenAdj > client.hiddenAdj) {
                             if (client.hiddenAdj > FOREGROUND_APP_ADJ) {
diff --git a/services/java/com/android/server/am/BatteryStatsService.java b/services/java/com/android/server/am/BatteryStatsService.java
index 27d0401..cc9a0af 100644
--- a/services/java/com/android/server/am/BatteryStatsService.java
+++ b/services/java/com/android/server/am/BatteryStatsService.java
@@ -148,14 +148,70 @@
             mStats.notePhoneOffLocked();
         }
     }
+    
+    public void noteWifiOn() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteWifiOnLocked();
+        }
+    }
+    
+    public void noteWifiOff() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteWifiOffLocked();
+        }
+    }
+    
+    public void noteBluetoothOn() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteBluetoothOnLocked();
+        }
+    }
+    
+    public void noteBluetoothOff() {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteBluetoothOffLocked();
+        }
+    }
+    
+    public void noteFullWifiLockAcquired(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteFullWifiLockAcquiredLocked(uid);
+        }
+    }
+    
+    public void noteFullWifiLockReleased(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteFullWifiLockReleasedLocked(uid);
+        }
+    }
+    
+    public void noteScanWifiLockAcquired(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScanWifiLockAcquiredLocked(uid);
+        }
+    }
+    
+    public void noteScanWifiLockReleased(int uid) {
+        enforceCallingPermission();
+        synchronized (mStats) {
+            mStats.noteScanWifiLockReleasedLocked(uid);
+        }
+    }
 
     public boolean isOnBattery() {
         return mStats.isOnBattery();
     }
     
-    public void setOnBattery(boolean onBattery) {
+    public void setOnBattery(boolean onBattery, int level) {
         enforceCallingPermission();
-        mStats.setOnBattery(onBattery);
+        mStats.setOnBattery(onBattery, level);
     }
     
     public long getAwakeTimeBattery() {
diff --git a/services/java/com/android/server/status/StatusBarPolicy.java b/services/java/com/android/server/status/StatusBarPolicy.java
index 8433227..36d1465 100644
--- a/services/java/com/android/server/status/StatusBarPolicy.java
+++ b/services/java/com/android/server/status/StatusBarPolicy.java
@@ -24,6 +24,7 @@
 import android.app.AlertDialog;
 import android.bluetooth.BluetoothA2dp;
 import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothError;
 import android.bluetooth.BluetoothHeadset;
 import android.bluetooth.BluetoothIntent;
 import android.content.BroadcastReceiver;
@@ -222,8 +223,7 @@
             else if (action.equals(Intent.ACTION_BATTERY_CHANGED)) {
                 updateBattery(intent);
             }
-            else if (action.equals(BluetoothIntent.ENABLED_ACTION) ||
-                    action.equals(BluetoothIntent.DISABLED_ACTION) ||
+            else if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION) ||
                     action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION) ||
                     action.equals(BluetoothA2dp.SINK_STATE_CHANGED_ACTION)) {
                 updateBluetooth(intent);
@@ -345,8 +345,7 @@
         filter.addAction(Intent.ACTION_SYNC_STATE_CHANGED);
         filter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION);
         filter.addAction(AudioManager.VIBRATE_SETTING_CHANGED_ACTION);
-        filter.addAction(BluetoothIntent.ENABLED_ACTION);
-        filter.addAction(BluetoothIntent.DISABLED_ACTION);
+        filter.addAction(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION);
         filter.addAction(BluetoothA2dp.SINK_STATE_CHANGED_ACTION);
         filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
@@ -796,10 +795,10 @@
         int iconId = com.android.internal.R.drawable.stat_sys_data_bluetooth;
 
         String action = intent.getAction();
-        if (action.equals(BluetoothIntent.DISABLED_ACTION)) {
-            mBluetoothEnabled = false;
-        } else if (action.equals(BluetoothIntent.ENABLED_ACTION)) {
-            mBluetoothEnabled = true;
+        if (action.equals(BluetoothIntent.BLUETOOTH_STATE_CHANGED_ACTION)) {
+            int state = intent.getIntExtra(BluetoothIntent.BLUETOOTH_STATE,
+                                           BluetoothError.ERROR);
+            mBluetoothEnabled = state == BluetoothDevice.BLUETOOTH_STATE_ON;
         } else if (action.equals(BluetoothIntent.HEADSET_STATE_CHANGED_ACTION)) {
             mBluetoothHeadsetState = intent.getIntExtra(BluetoothIntent.HEADSET_STATE,
                     BluetoothHeadset.STATE_ERROR);
diff --git a/services/java/com/android/server/status/StatusBarService.java b/services/java/com/android/server/status/StatusBarService.java
index 5442e1d..5336e27 100644
--- a/services/java/com/android/server/status/StatusBarService.java
+++ b/services/java/com/android/server/status/StatusBarService.java
@@ -57,6 +57,8 @@
 import android.widget.RemoteViews;
 import android.widget.ScrollView;
 import android.widget.TextView;
+import android.widget.FrameLayout;
+
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -1476,9 +1478,11 @@
 
         /// ---------- Expanded View --------------
         pixelFormat = PixelFormat.TRANSLUCENT;
-        bg = mExpandedView.getBackground();
-        if (bg != null) {
-            pixelFormat = bg.getOpacity();
+        if (false) {
+            bg = mExpandedView.getBackground();
+            if (bg != null) {
+                pixelFormat = bg.getOpacity();
+            }
         }
 
         lp = mExpandedDialog.getWindow().getAttributes();
@@ -1490,11 +1494,13 @@
         lp.flags = WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
                 | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                 | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
+                | WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM
+                | WindowManager.LayoutParams.FLAG_DITHER;
         lp.format = pixelFormat;
         lp.gravity = Gravity.TOP | Gravity.FILL_HORIZONTAL;
         lp.setTitle("StatusBarExpanded");
         mExpandedDialog.getWindow().setAttributes(lp);
+        mExpandedDialog.getWindow().setFormat(pixelFormat);
         mExpandedParams = lp;
 
         mExpandedDialog.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
@@ -1503,7 +1509,8 @@
                                            ViewGroup.LayoutParams.WRAP_CONTENT));
         mExpandedDialog.show();
         mExpandedDialog.hide();
-        View hack = (View)mExpandedView.getParent();
+        FrameLayout hack = (FrameLayout)mExpandedView.getParent();
+        hack.setForeground(null);
     }
 
     void setDateViewVisibility(boolean visible, int anim) {
diff --git a/services/java/com/android/server/status/TrackingPatternView.java b/services/java/com/android/server/status/TrackingPatternView.java
new file mode 100644
index 0000000..0ae9984
--- /dev/null
+++ b/services/java/com/android/server/status/TrackingPatternView.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.status;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.view.View;
+import android.graphics.BitmapFactory;
+import android.graphics.Bitmap;
+import android.graphics.Paint;
+import android.graphics.Canvas;
+
+public class TrackingPatternView extends View {
+    private Bitmap mTexture;
+    private Paint mPaint;
+    private int mTextureWidth;
+    private int mTextureHeight;
+    
+    public TrackingPatternView(Context context, AttributeSet attrs) {
+        super(context, attrs);
+
+        mTexture = BitmapFactory.decodeResource(getResources(), 
+                com.android.internal.R.drawable.status_bar_background);
+        mTextureWidth = mTexture.getWidth();
+        mTextureHeight = mTexture.getHeight();
+
+        mPaint = new Paint();
+        mPaint.setDither(false);
+    }
+
+    @Override
+    public void onDraw(Canvas canvas) {
+        final Bitmap texture = mTexture;
+        final Paint paint = mPaint;
+
+        final int width = getWidth();
+        final int height = getHeight();
+
+        final int textureWidth = mTextureWidth;
+        final int textureHeight = mTextureHeight;
+
+        Log.d("TrackingPatternView", "width=" + width + " textureWidth=" + textureWidth);
+
+        int x = 0;
+        int y;
+
+        while (x < width) {
+            y = 0;
+            while (y < height) {
+                canvas.drawBitmap(texture, x, y, paint);
+                y += textureHeight;
+            }
+            x += textureWidth;
+        }
+    }
+}
diff --git a/services/jni/com_android_server_HardwareService.cpp b/services/jni/com_android_server_HardwareService.cpp
index ac36348..b0aab59 100644
--- a/services/jni/com_android_server_HardwareService.cpp
+++ b/services/jni/com_android_server_HardwareService.cpp
@@ -15,19 +15,110 @@
 ** limitations under the License.
 */
 
-#define LOG_TAG "Vibrator"
+#define LOG_TAG "HardwareService"
 
 #include "jni.h"
 #include "JNIHelp.h"
-#include <stdio.h>
 #include "android_runtime/AndroidRuntime.h"
+
 #include <utils/misc.h>
 #include <utils/Log.h>
 #include <hardware_legacy/vibrator.h>
+#include <hardware/hardware.h>
+#include <hardware/lights.h>
+
+#include <stdio.h>
+//#include <string.h>
 
 namespace android
 {
 
+// These values must correspond with the LIGHT_ID constants in
+// HardwareService.java
+enum {
+    LIGHT_INDEX_BACKLIGHT = 0,
+    LIGHT_INDEX_KEYBOARD = 1,
+    LIGHT_INDEX_BUTTONS = 2,
+    LIGHT_INDEX_BATTERY = 3,
+    LIGHT_INDEX_NOTIFICATIONS = 4,
+    LIGHT_INDEX_ATTENTION = 5,
+    LIGHT_COUNT
+};
+
+struct Devices {
+    light_device_t* lights[LIGHT_COUNT];
+};
+
+static light_device_t* get_device(hw_module_t* module, char const* name)
+{
+    int err;
+    hw_device_t* device;
+    err = module->methods->open(module, name, &device);
+    if (err == 0) {
+        return (light_device_t*)device;
+    } else {
+        return NULL;
+    }
+}
+
+static jint init_native(JNIEnv *env, jobject clazz)
+{
+    int err;
+    hw_module_t* module;
+    Devices* devices;
+    
+    devices = (Devices*)malloc(sizeof(Devices));
+
+    err = hw_get_module(LIGHTS_HARDWARE_MODULE_ID, (hw_module_t const**)&module);
+    if (err == 0) {
+        devices->lights[LIGHT_INDEX_BACKLIGHT]
+                = get_device(module, LIGHT_ID_BACKLIGHT);
+        devices->lights[LIGHT_INDEX_KEYBOARD]
+                = get_device(module, LIGHT_ID_KEYBOARD);
+        devices->lights[LIGHT_INDEX_BUTTONS]
+                = get_device(module, LIGHT_ID_BUTTONS);
+        devices->lights[LIGHT_INDEX_BATTERY]
+                = get_device(module, LIGHT_ID_BATTERY);
+        devices->lights[LIGHT_INDEX_NOTIFICATIONS]
+                = get_device(module, LIGHT_ID_NOTIFICATIONS);
+        devices->lights[LIGHT_INDEX_ATTENTION]
+                = get_device(module, LIGHT_ID_ATTENTION);
+    } else {
+        memset(devices, 0, sizeof(Devices));
+    }
+
+    return (jint)devices;
+}
+
+static void finalize_native(JNIEnv *env, jobject clazz, int ptr)
+{
+    Devices* devices = (Devices*)ptr;
+    if (devices == NULL) {
+        return;
+    }
+
+    free(devices);
+}
+
+static void setLight_native(JNIEnv *env, jobject clazz, int ptr,
+        int light, int colorARGB, int flashMode, int onMS, int offMS)
+{
+    Devices* devices = (Devices*)ptr;
+    light_state_t state;
+
+    if (light < 0 || light >= LIGHT_COUNT || devices->lights[light] == NULL) {
+        return ;
+    }
+
+    memset(&state, 0, sizeof(light_state_t));
+    state.color = colorARGB;
+    state.flashMode = flashMode;
+    state.flashOnMS = onMS;
+    state.flashOffMS = offMS;
+
+    devices->lights[light]->set_light(devices->lights[light], &state);
+}
+
 static void vibratorOn(JNIEnv *env, jobject clazz, jlong timeout_ms)
 {
     // LOGI("vibratorOn\n");
@@ -41,11 +132,14 @@
 }
 
 static JNINativeMethod method_table[] = {
+    { "init_native", "()I", (void*)init_native },
+    { "finalize_native", "(I)V", (void*)init_native },
+    { "setLight_native", "(IIIIII)V", (void*)setLight_native },
     { "vibratorOn", "(J)V", (void*)vibratorOn },
     { "vibratorOff", "()V", (void*)vibratorOff }
 };
 
-int register_android_os_Vibrator(JNIEnv *env)
+int register_android_server_HardwareService(JNIEnv *env)
 {
     return jniRegisterNativeMethods(env, "com/android/server/HardwareService",
             method_table, NELEM(method_table));
diff --git a/services/jni/onload.cpp b/services/jni/onload.cpp
index 3d68cfb..26200d3 100644
--- a/services/jni/onload.cpp
+++ b/services/jni/onload.cpp
@@ -7,7 +7,7 @@
 int register_android_server_AlarmManagerService(JNIEnv* env);
 int register_android_server_BatteryService(JNIEnv* env);
 int register_android_server_KeyInputQueue(JNIEnv* env);
-int register_android_os_Vibrator(JNIEnv* env);
+int register_android_server_HardwareService(JNIEnv* env);
 int register_android_server_SensorService(JNIEnv* env);
 int register_android_server_SystemServer(JNIEnv* env);
 };
@@ -26,7 +26,7 @@
     LOG_ASSERT(env, "Could not retrieve the env!");
 
     register_android_server_KeyInputQueue(env);
-    register_android_os_Vibrator(env);
+    register_android_server_HardwareService(env);
     register_android_server_AlarmManagerService(env);
     register_android_server_BatteryService(env);
     register_android_server_SensorService(env);
diff --git a/telephony/java/com/android/internal/telephony/CallerInfo.java b/telephony/java/com/android/internal/telephony/CallerInfo.java
index 13b6e5c..da53e15 100644
--- a/telephony/java/com/android/internal/telephony/CallerInfo.java
+++ b/telephony/java/com/android/internal/telephony/CallerInfo.java
@@ -39,6 +39,7 @@
 
     public static final String UNKNOWN_NUMBER = "-1";
     public static final String PRIVATE_NUMBER = "-2";
+    public static final String PAYPHONE_NUMBER = "-3";
 
     /**
      * Please note that, any one of these member variables can be null,
diff --git a/telephony/java/com/android/internal/telephony/Connection.java b/telephony/java/com/android/internal/telephony/Connection.java
index d833810..ead49bf 100644
--- a/telephony/java/com/android/internal/telephony/Connection.java
+++ b/telephony/java/com/android/internal/telephony/Connection.java
@@ -21,6 +21,13 @@
  */
 public abstract class Connection
 {
+    // Number presentation type for caller id display
+    public static int PRESENTATION_ALLOWED = 1;    // normal
+    public static int PRESENTATION_RESTRICTED = 2; // block by user
+    public static int PRESENTATION_UNKNOWN = 3;    // no specified or unknown by network
+    public static int PRESENTATION_PAYPHONE = 4;   // show pay phone info
+
+    
     public enum DisconnectCause {
         NOT_DISCONNECTED,   /* has not yet disconnected */
         INCOMING_MISSED,    /* an incoming call that was missed and never answered */
@@ -218,7 +225,12 @@
     /**
      * Cancel any post
      */
-    public abstract void cancelPostDial();
+    public abstract void cancelPostDial();       
     
-
+    /**
+     * Returns the caller id presentation type for incoming and waiting calls
+     * @return one of PRESENTATION_*
+     */
+    public abstract int getNumberPresentation();
+    
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java b/telephony/java/com/android/internal/telephony/gsm/DriverCall.java
index 178e661..aab885a 100644
--- a/telephony/java/com/android/internal/telephony/gsm/DriverCall.java
+++ b/telephony/java/com/android/internal/telephony/gsm/DriverCall.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony.gsm;
 import com.android.internal.telephony.*;
+
 import android.util.Log;
 import java.lang.Comparable;
 import android.telephony.PhoneNumberUtils;
@@ -36,7 +37,7 @@
         WAITING;    // MT call only
         // If you add a state, make sure to look for the switch()
         // statements that use this enum
-    };
+    }
 
     public int index;
     public boolean isMT;
@@ -46,6 +47,7 @@
     public int TOA;
     public boolean isVoice;
     public int als;
+    public int numberPresentation;
   
     /** returns null on error */
     static DriverCall
@@ -64,7 +66,10 @@
 
             ret.isVoice = (0 == p.nextInt());
             ret.isMpty = p.nextBoolean();
-
+            
+            // use ALLOWED as default presentation while parsing CLCC
+            ret.numberPresentation = Connection.PRESENTATION_ALLOWED;
+            
             if (p.hasMore()) {
                 // Some lame implementations return strings
                 // like "NOT AVAILABLE" in the CLCC line
@@ -105,7 +110,7 @@
                 + state + ","
                 + (isVoice ? "voice" : "no_voc") + ","
                 + (isMpty ? "conf" : "norm") + ","
-                + TOA + "," + als;
+                + TOA + "," + als + ",cli " + numberPresentation;
     }
 
     public static State
@@ -122,6 +127,19 @@
                 throw new ATParseEx("illegal call state " + state);
         }
     }
+    
+    public static int
+    presentationFromCLIP(int cli) throws ATParseEx
+    {
+        switch(cli) {
+            case 0: return Connection.PRESENTATION_ALLOWED;
+            case 1: return Connection.PRESENTATION_RESTRICTED;
+            case 2: return Connection.PRESENTATION_UNKNOWN;
+            case 3: return Connection.PRESENTATION_PAYPHONE;
+            default:
+                throw new ATParseEx("illegal presentation " + cli);
+        }
+    }
 
     //***** Comparable Implementation 
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java b/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
index 7179bb7..4feaf21 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMCall.java
@@ -37,7 +37,7 @@
     {
         switch (dcState) {
             case ACTIVE:        return State.ACTIVE;
-            case HOLDING:          return State.HOLDING;
+            case HOLDING:       return State.HOLDING;
             case DIALING:       return State.DIALING;
             case ALERTING:      return State.ALERTING;
             case INCOMING:      return State.INCOMING;
diff --git a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java b/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
index 70e9f62..4777892 100644
--- a/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
+++ b/telephony/java/com/android/internal/telephony/gsm/GSMConnection.java
@@ -16,6 +16,7 @@
 
 package com.android.internal.telephony.gsm;
 import com.android.internal.telephony.*;
+
 import android.content.Context;
 import android.os.Handler;
 import android.os.PowerManager;
@@ -71,6 +72,7 @@
 
     DisconnectCause cause = DisconnectCause.NOT_DISCONNECTED;
     PostDialState postDialState = PostDialState.NOT_STARTED;
+    int numberPresentation = Connection.PRESENTATION_ALLOWED;
 
     Handler h;
 
@@ -124,6 +126,7 @@
 
         isIncoming = dc.isMT;
         createTime = System.currentTimeMillis();
+        numberPresentation = dc.numberPresentation;
 
         this.index = index;
 
@@ -756,4 +759,9 @@
     private void log(String msg) {
         Log.d(LOG_TAG, "[GSMConn] " + msg);
     }
+
+    @Override
+    public int getNumberPresentation() {
+        return numberPresentation;
+    }
 }
diff --git a/telephony/java/com/android/internal/telephony/gsm/RIL.java b/telephony/java/com/android/internal/telephony/gsm/RIL.java
index 7622560..b210868 100644
--- a/telephony/java/com/android/internal/telephony/gsm/RIL.java
+++ b/telephony/java/com/android/internal/telephony/gsm/RIL.java
@@ -201,7 +201,7 @@
     private Context mContext;
     WakeLock mWakeLock;
     int mRequestMessagesPending;
-
+    
     // Is this the first radio state change?
     private boolean mInitialRadioStateChange = true;
 
@@ -2319,7 +2319,9 @@
             case RIL_SIM_NETWORK_PERSONALIZATION:   
                                     return SimStatus.SIM_NETWORK_PERSONALIZATION;
             default:
-                throw new RuntimeException ("Invalid RIL_REQUEST_GET_SIM_STATUS result: " + status);
+                // Unrecognized SIM status.  Treat it like a missing SIM.
+                Log.e(LOG_TAG, "Unrecognized RIL_REQUEST_GET_SIM_STATUS result: " + status);
+                return SimStatus.SIM_ABSENT;
         }
     }
 
@@ -2345,7 +2347,10 @@
             dc.als = p.readInt();
             dc.isVoice = (0 == p.readInt()) ? false : true;
             dc.number = p.readString();
-
+            
+            // TODO get presentation from p.readInt() after checkin new RIL
+            dc.numberPresentation = DriverCall.presentationFromCLIP(0);
+            
             // Make sure there's a leading + on addresses with a TOA
             // of 145
 
diff --git a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
index 89ce506..e336d7d 100644
--- a/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/gsm/ServiceStateTracker.java
@@ -24,6 +24,7 @@
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_ALPHA;
 import static com.android.internal.telephony.TelephonyProperties.PROPERTY_SIM_OPERATOR_NUMERIC;
 
+import com.android.internal.telephony.SimCard;
 import com.android.internal.telephony.TelephonyIntents;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.gsm.DataConnectionTracker.State;
@@ -175,16 +176,17 @@
     // waiting period before recheck gprs and voice registration
     static final int DEFAULT_GPRS_CHECK_PERIOD_MILLIS = 60 * 1000;
 
-    // notification type
+    // restricted state type
     static final int PS_ENABLED = 1001;             // Access Control blocks data service
     static final int PS_DISABLED = 1002;            // Access Control enables data service
     static final int CS_ENABLED = 1003;             // Access Control blocks all voice/sms service
     static final int CS_DISABLED = 1004;            // Access Control enables all voice/sms service
     static final int CS_NORMAL_ENABLED = 1005;      // Access Control blocks normal voice/sms service
-    static final int CS_NORMAL_DISABLED = 1006;     // Access Control enables normal voice/sms service
-    static final int CS_EMERGENCY_ENABLED = 1007;   // Access Control blocks emergency call service
-    static final int CS_EMERGENCY_DISABLED  = 1008; // Access Control enables emergency call service       
+    static final int CS_EMERGENCY_ENABLED = 1006;   // Access Control blocks emergency call service
     
+    // notification id
+    static final int PS_NOTIFICATION = 888; //id to update and cancel PS restricted 
+    static final int CS_NOTIFICATION = 999; //id to update and cancel CS restricted
     
     //***** Events
     static final int EVENT_RADIO_STATE_CHANGED       = 1;
@@ -1181,7 +1183,8 @@
     /**
      * Set restricted state based on the OnRestrictedStateChanged notification
      * If any voice or packet restricted state changes, trigger a UI
-     * notification and notify registrants.
+     * notification and notify registrants when sim is ready.
+     * 
      * @param ar an int value of RIL_RESTRICTED_STATE_*
      */
     private void onRestrictedStateChanged(AsyncResult ar)
@@ -1198,38 +1201,78 @@
             newRs.setCsEmergencyRestricted(
                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_EMERGENCY) != 0) ||
                     ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
-            newRs.setCsNormalRestricted(
-                    ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
-                    ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
-            newRs.setPsRestricted(
-                    (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
+            
+
+            //ignore the normal call and data restricted state before SIM READY
+            if (phone.getSimCard().getState() == SimCard.State.READY){ 
+                newRs.setCsNormalRestricted(
+                        ((state & RILConstants.RIL_RESTRICTED_STATE_CS_NORMAL) != 0) ||
+                        ((state & RILConstants.RIL_RESTRICTED_STATE_CS_ALL) != 0) );
+                newRs.setPsRestricted(
+                        (state & RILConstants.RIL_RESTRICTED_STATE_PS_ALL)!= 0);
+            }
             
             Log.d(LOG_TAG, "[DSAC DEB] " + "new rs "+ newRs);         
             
             if (!rs.isPsRestricted() && newRs.isPsRestricted()) {
                 psRestrictEnabledRegistrants.notifyRegistrants();
-                setNotification(PS_ENABLED, false);
+                setNotification(PS_ENABLED);
             } else if (rs.isPsRestricted() && !newRs.isPsRestricted()) {
                 psRestrictDisabledRegistrants.notifyRegistrants();
-                setNotification(PS_DISABLED, false);
+                setNotification(PS_DISABLED);
             }
             
-            if (!rs.isCsRestricted() && newRs.isCsRestricted()) {
-                setNotification(CS_ENABLED, false);
-            } else if (rs.isCsRestricted() && !newRs.isCsRestricted()) {
-                setNotification(CS_DISABLED, false);
-            } else {
-                if (!rs.isCsEmergencyRestricted() && newRs.isCsEmergencyRestricted()) {
-                    setNotification(CS_EMERGENCY_ENABLED, false); 
-                } else if (rs.isCsEmergencyRestricted() && !newRs.isCsEmergencyRestricted()) {
-                    setNotification(CS_EMERGENCY_DISABLED, false); 
+            /**
+             * There are two kind of cs restriction, normal and emergency. So 
+             * there are 4 x 4 combinations in current and new restricted states
+             * and we only need to notify when state is changed.
+             */
+            if (rs.isCsRestricted()) {
+                if (!newRs.isCsRestricted()) {
+                    // remove all restriction
+                    setNotification(CS_DISABLED);
+                } else if (!newRs.isCsNormalRestricted()) {
+                    // remove normal restriction
+                    setNotification(CS_EMERGENCY_ENABLED); 
+                } else if (!newRs.isCsEmergencyRestricted()) {
+                    // remove emergency restriction
+                    setNotification(CS_NORMAL_ENABLED); 
                 }
-                if (!rs.isCsNormalRestricted() && newRs.isCsNormalRestricted()) {
-                    setNotification(CS_NORMAL_ENABLED, false); 
-                } else if (rs.isCsEmergencyRestricted() && !newRs.isCsEmergencyRestricted()) {
-                    setNotification(CS_NORMAL_DISABLED, false); 
+            } else if (rs.isCsEmergencyRestricted() && !rs.isCsNormalRestricted()) {
+                if (!newRs.isCsRestricted()) {
+                    // remove all restriction
+                    setNotification(CS_DISABLED); 
+                } else if (newRs.isCsRestricted()) {
+                    // enable all restriction
+                    setNotification(CS_ENABLED);
+                } else if (newRs.isCsNormalRestricted()) {
+                    // remove emergency restriction and enable normal restriction
+                    setNotification(CS_NORMAL_ENABLED); 
+                }
+            } else if (!rs.isCsEmergencyRestricted() && rs.isCsNormalRestricted()) {
+                if (!newRs.isCsRestricted()) {
+                    // remove all restriction
+                    setNotification(CS_DISABLED); 
+                } else if (newRs.isCsRestricted()) {
+                    // enable all restriction
+                    setNotification(CS_ENABLED);
+                } else if (newRs.isCsEmergencyRestricted()) {
+                    // remove normal restriction and enable emergency restriction
+                    setNotification(CS_EMERGENCY_ENABLED); 
+                }
+            } else {
+                if (newRs.isCsRestricted()) {
+                    // enable all restriction
+                    setNotification(CS_ENABLED);
+                } else if (newRs.isCsEmergencyRestricted()) {
+                    // enable emergency restriction
+                    setNotification(CS_EMERGENCY_ENABLED); 
+                } else if (newRs.isCsNormalRestricted()) {
+                    // enable normal restriction
+                    setNotification(CS_NORMAL_ENABLED); 
                 }
             }
+            
             rs = newRs;
         }
         Log.d(LOG_TAG, "[DSAC DEB] " + "current rs at return "+ rs);
@@ -1593,67 +1636,61 @@
      * Post a notification to NotificationManager for restricted state
      * 
      * @param notifyType is one state of PS/CS_*_ENABLE/DISABLE
-     * @param isCancel true to cancel the previous posted notification 
-     *                 (current is not implemented yet)
      */
-    private void setNotification(int notifyType, boolean isCancel) {
+    private void setNotification(int notifyType) {
 
         Log.d(LOG_TAG, "[DSAC DEB] " + "create notification " + notifyType);
+        
+        Context context = phone.getContext();
+
         mNotification = new Notification();
         mNotification.when = System.currentTimeMillis();
         mNotification.flags = Notification.FLAG_AUTO_CANCEL;
-        mNotification.icon = com.android.internal.R.drawable.icon_highlight_square;
+        mNotification.icon = com.android.internal.R.drawable.stat_sys_warning;
         Intent intent = new Intent();
         mNotification.contentIntent = PendingIntent
-        .getActivity(phone.getContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
+        .getActivity(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
 
-        // TODO 
-        // should use getResources().getText(com.android.internal.R.)
-        CharSequence title = "Restricted State Changed";
         CharSequence details = "";
+        CharSequence title = context.getText(com.android.internal.R.string.RestrictedChangedTitle);
+        int notificationId = CS_NOTIFICATION;
+        
         switch (notifyType) {
         case PS_ENABLED:
-            details = "Access Control blocks data service.";
+            notificationId = PS_NOTIFICATION;
+            details = context.getText(com.android.internal.R.string.RestrictedOnData);;
             break;
         case PS_DISABLED:
-            details = "Access Control enables data service.";
+            notificationId = PS_NOTIFICATION;
             break;
         case CS_ENABLED:
-            details = "Access Control blocks all voice/sms service.";
+            details = context.getText(com.android.internal.R.string.RestrictedOnAll);;
+            break;   
+        case CS_NORMAL_ENABLED:
+            details = context.getText(com.android.internal.R.string.RestrictedOnNormal);;
+            break;   
+        case CS_EMERGENCY_ENABLED:
+            details = context.getText(com.android.internal.R.string.RestrictedOnEmergency);;
             break;   
         case CS_DISABLED:
-            details = "Access Control enables all voice/sms service.";
-            break;  
-        case CS_NORMAL_ENABLED:
-            details = "Access Control blocks normal voice/sms service.";
-            break;   
-        case CS_NORMAL_DISABLED:
-            details = "Access Control enables normal voice/sms service.";
-            break; 
-        case CS_EMERGENCY_ENABLED:
-            details = "Access Control blocks emergency call service.";
-            break;   
-        case CS_EMERGENCY_DISABLED:
-            details = "Access Control enables emergency call service.";
+            // do nothing and cancel the notification later
             break;  
         }
         
         Log.d(LOG_TAG, "[DSAC DEB] " + "put notification " + title + " / " +details);
         mNotification.tickerText = title;
-        mNotification.setLatestEventInfo(phone.getContext(), title, details, 
+        mNotification.setLatestEventInfo(context, title, details, 
                 mNotification.contentIntent);
         
         NotificationManager notificationManager = (NotificationManager) 
-            phone.getContext().getSystemService(Context.NOTIFICATION_SERVICE);
+            context.getSystemService(Context.NOTIFICATION_SERVICE);
 
-        if (isCancel) {
-            // TODO
-            //if we go the notification route, probably want to only put up a single
-            //notification if both CS+PS is restricted, instead of one for each.nnnnn
-            //Anyway, need UX team input on UI.
-            //notificationManager.cancel(notifyType);
+        if (notifyType == PS_DISABLED || notifyType == CS_DISABLED) {
+            // cancel previous post notification
+            notificationManager.cancel(notificationId);
+        } else {
+            // update restricted state notification
+            notificationManager.notify(notificationId, mNotification);
         }
-        notificationManager.notify(notifyType, mNotification);
     }
-
 }
diff --git a/tests/AndroidTests/res/values-12key-63x57/configVarying.xml b/tests/AndroidTests/res/values-12key-63x57/configVarying.xml
new file mode 100644
index 0000000..50b3765
--- /dev/null
+++ b/tests/AndroidTests/res/values-12key-63x57/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple 12key 63x57</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag 12key 63x57</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-12key-dpad/configVarying.xml b/tests/AndroidTests/res/values-12key-dpad/configVarying.xml
new file mode 100644
index 0000000..83eb080
--- /dev/null
+++ b/tests/AndroidTests/res/values-12key-dpad/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple 12key dpad</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag 12key dpad</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-12key/configVarying.xml b/tests/AndroidTests/res/values-12key/configVarying.xml
index 14ce1a7..e11340c 100644
--- a/tests/AndroidTests/res/values-12key/configVarying.xml
+++ b/tests/AndroidTests/res/values-12key/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag 12key</item>
     </bag>
-    <item type="configVarying" name="simple_12key">only simple 12key</item>
-    <bag type="configVarying" name="bag_12key">
-        <item name="testString">only bag 12key</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-240dpi/configVarying.xml b/tests/AndroidTests/res/values-240dpi/configVarying.xml
new file mode 100644
index 0000000..9f32f8d
--- /dev/null
+++ b/tests/AndroidTests/res/values-240dpi/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple 240dpi</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag 240dpi</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-320x200/configVarying.xml b/tests/AndroidTests/res/values-320x200/configVarying.xml
index 035e55e..ca2a286 100644
--- a/tests/AndroidTests/res/values-320x200/configVarying.xml
+++ b/tests/AndroidTests/res/values-320x200/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag 320x200</item>
     </bag>
-    <item type="configVarying" name="simple_320x200">only simple 320x200</item>
-    <bag type="configVarying" name="bag_320x200">
-        <item name="testString">only bag 320x200</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-32dpi-keysexposed/configVarying.xml b/tests/AndroidTests/res/values-32dpi-keysexposed/configVarying.xml
new file mode 100644
index 0000000..cd7f8da
--- /dev/null
+++ b/tests/AndroidTests/res/values-32dpi-keysexposed/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple 32dpi keysexposed</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag 32dpi keysexposed</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-32dpi-stylus/configVarying.xml b/tests/AndroidTests/res/values-32dpi-stylus/configVarying.xml
new file mode 100644
index 0000000..63fcdc8
--- /dev/null
+++ b/tests/AndroidTests/res/values-32dpi-stylus/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple 32dpi stylus</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag 32dpi stylus</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-480x320/configVarying.xml b/tests/AndroidTests/res/values-480x320/configVarying.xml
index 8b28d89..d4305fc 100644
--- a/tests/AndroidTests/res/values-480x320/configVarying.xml
+++ b/tests/AndroidTests/res/values-480x320/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag 480x320</item>
     </bag>
-    <item type="configVarying" name="simple_480x320">only simple 480x320</item>
-    <bag type="configVarying" name="bag_480x320">
-        <item name="testString">only bag 480x320</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-dpad-63x57/configVarying.xml b/tests/AndroidTests/res/values-dpad-63x57/configVarying.xml
new file mode 100644
index 0000000..8383e9e
--- /dev/null
+++ b/tests/AndroidTests/res/values-dpad-63x57/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple dpad 63x57</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag dpad 63x57</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-finger/configVarying.xml b/tests/AndroidTests/res/values-finger/configVarying.xml
index efe4758..674787e 100644
--- a/tests/AndroidTests/res/values-finger/configVarying.xml
+++ b/tests/AndroidTests/res/values-finger/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag finger</item>
     </bag>
-    <item type="configVarying" name="simple_finger">only simple finger</item>
-    <bag type="configVarying" name="bag_finger">
-        <item name="testString">only bag finger</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-keysexposed-12key/configVarying.xml b/tests/AndroidTests/res/values-keysexposed-12key/configVarying.xml
new file mode 100644
index 0000000..2a2b8d9
--- /dev/null
+++ b/tests/AndroidTests/res/values-keysexposed-12key/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple keysexposed 12key</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag keysexposed 12key</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-keysexposed-dpad/configVarying.xml b/tests/AndroidTests/res/values-keysexposed-dpad/configVarying.xml
new file mode 100644
index 0000000..f279eb0
--- /dev/null
+++ b/tests/AndroidTests/res/values-keysexposed-dpad/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple keysexposed dpad</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag keysexposed dpad</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-land/configVarying.xml b/tests/AndroidTests/res/values-land/configVarying.xml
new file mode 100644
index 0000000..7d3d7e8
--- /dev/null
+++ b/tests/AndroidTests/res/values-land/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple landscape</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag landscape</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-mcc111-mnc222/configVarying.xml b/tests/AndroidTests/res/values-mcc111-mnc222/configVarying.xml
new file mode 100644
index 0000000..84c31c6
--- /dev/null
+++ b/tests/AndroidTests/res/values-mcc111-mnc222/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple mcc111 mnc222</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mcc111 mnc222</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-mcc111-xx-rYY/configVarying.xml b/tests/AndroidTests/res/values-mcc111-xx-rYY/configVarying.xml
new file mode 100644
index 0000000..3aa1ba0
--- /dev/null
+++ b/tests/AndroidTests/res/values-mcc111-xx-rYY/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple mcc111 xx-rYY</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mcc111 xx-rYY</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-mcc111-xx/configVarying.xml b/tests/AndroidTests/res/values-mcc111-xx/configVarying.xml
new file mode 100644
index 0000000..09bd817
--- /dev/null
+++ b/tests/AndroidTests/res/values-mcc111-xx/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple mcc111 xx</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mcc111 xx</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-mcc111/configVarying.xml b/tests/AndroidTests/res/values-mcc111/configVarying.xml
index 16b13a5..b516194 100644
--- a/tests/AndroidTests/res/values-mcc111/configVarying.xml
+++ b/tests/AndroidTests/res/values-mcc111/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag mcc111</item>
     </bag>
-    <item type="configVarying" name="simple_mcc111">only simple mcc111</item>
-    <bag type="configVarying" name="bag_mcc111">
-        <item name="testString">only bag mcc111</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-mnc222-square/configVarying.xml b/tests/AndroidTests/res/values-mnc222-square/configVarying.xml
new file mode 100644
index 0000000..952c595
--- /dev/null
+++ b/tests/AndroidTests/res/values-mnc222-square/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple mnc222 square</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mnc222 square</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-mnc222-xx/configVarying.xml b/tests/AndroidTests/res/values-mnc222-xx/configVarying.xml
new file mode 100644
index 0000000..c1cafbc
--- /dev/null
+++ b/tests/AndroidTests/res/values-mnc222-xx/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple mnc222 xx</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag mnc222 xx</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-mnc222/configVarying.xml b/tests/AndroidTests/res/values-mnc222/configVarying.xml
index 7f68729..a37b7ef 100644
--- a/tests/AndroidTests/res/values-mnc222/configVarying.xml
+++ b/tests/AndroidTests/res/values-mnc222/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag mnc222</item>
     </bag>
-    <item type="configVarying" name="simple_mnc222">only simple mnc222</item>
-    <bag type="configVarying" name="bag_mnc222">
-        <item name="testString">only bag mnc222</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-notouch/configVarying.xml b/tests/AndroidTests/res/values-notouch/configVarying.xml
index 8a71de4..f919f87 100644
--- a/tests/AndroidTests/res/values-notouch/configVarying.xml
+++ b/tests/AndroidTests/res/values-notouch/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag notouch</item>
     </bag>
-    <item type="configVarying" name="simple_notouch">only simple notouch</item>
-    <bag type="configVarying" name="bag_notouch">
-        <item name="testString">only bag notouch</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-port/configVarying.xml b/tests/AndroidTests/res/values-port/configVarying.xml
new file mode 100644
index 0000000..0e1f247
--- /dev/null
+++ b/tests/AndroidTests/res/values-port/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple portrait</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag portrait</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-square-32dpi/configVarying.xml b/tests/AndroidTests/res/values-square-32dpi/configVarying.xml
new file mode 100644
index 0000000..41a69cd
--- /dev/null
+++ b/tests/AndroidTests/res/values-square-32dpi/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple square 32dpi</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag square 32dpi</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-square-stylus/configVarying.xml b/tests/AndroidTests/res/values-square-stylus/configVarying.xml
new file mode 100644
index 0000000..de7892e
--- /dev/null
+++ b/tests/AndroidTests/res/values-square-stylus/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple square stylus</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag square stylus</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-square/configVarying.xml b/tests/AndroidTests/res/values-square/configVarying.xml
new file mode 100644
index 0000000..ba3a036
--- /dev/null
+++ b/tests/AndroidTests/res/values-square/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple square</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag square</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-stylus-12key/configVarying.xml b/tests/AndroidTests/res/values-stylus-12key/configVarying.xml
new file mode 100644
index 0000000..d79f079
--- /dev/null
+++ b/tests/AndroidTests/res/values-stylus-12key/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple stylus 12key</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag stylus 12key</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-stylus-keysexposed/configVarying.xml b/tests/AndroidTests/res/values-stylus-keysexposed/configVarying.xml
new file mode 100644
index 0000000..ff4e766
--- /dev/null
+++ b/tests/AndroidTests/res/values-stylus-keysexposed/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple stylus keysexposed</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag stylus keysexposed</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-stylus/configVarying.xml b/tests/AndroidTests/res/values-stylus/configVarying.xml
index 87df119..83936a7 100644
--- a/tests/AndroidTests/res/values-stylus/configVarying.xml
+++ b/tests/AndroidTests/res/values-stylus/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag stylus</item>
     </bag>
-    <item type="configVarying" name="simple_stylus">only simple stylus</item>
-    <bag type="configVarying" name="bag_stylus">
-        <item name="testString">only bag stylus</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-xx-32dpi/configVarying.xml b/tests/AndroidTests/res/values-xx-32dpi/configVarying.xml
new file mode 100644
index 0000000..4cc162c
--- /dev/null
+++ b/tests/AndroidTests/res/values-xx-32dpi/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple xx 32dpi</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag xx 32dpi</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-xx-rYY/configVarying.xml b/tests/AndroidTests/res/values-xx-rYY/configVarying.xml
index 4e52db9..2d2a9a1 100644
--- a/tests/AndroidTests/res/values-xx-rYY/configVarying.xml
+++ b/tests/AndroidTests/res/values-xx-rYY/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag xx-rYY</item>
     </bag>
-    <item type="configVarying" name="simple_xx_rYY">only simple xx_rYY</item>
-    <bag type="configVarying" name="bag_xx_rYY">
-        <item name="testString">only bag xx_rYY</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values-xx-square/configVarying.xml b/tests/AndroidTests/res/values-xx-square/configVarying.xml
new file mode 100644
index 0000000..807feec
--- /dev/null
+++ b/tests/AndroidTests/res/values-xx-square/configVarying.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2007 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+  
+          http://www.apache.org/licenses/LICENSE-2.0
+  
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<resources>
+    <item type="configVarying" name="simple">simple xx square</item>
+    <bag type="configVarying" name="bag">
+        <item name="testString">bag xx square</item>
+    </bag>
+</resources>
diff --git a/tests/AndroidTests/res/values-xx/configVarying.xml b/tests/AndroidTests/res/values-xx/configVarying.xml
index e50649d..fef2737 100644
--- a/tests/AndroidTests/res/values-xx/configVarying.xml
+++ b/tests/AndroidTests/res/values-xx/configVarying.xml
@@ -19,8 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag xx</item>
     </bag>
-    <item type="configVarying" name="simple_xx">only simple xx</item>
-    <bag type="configVarying" name="bag_xx">
-        <item name="testString">only bag xx</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/res/values/configVarying.xml b/tests/AndroidTests/res/values/configVarying.xml
index c4a20ad..3b3e4a4 100644
--- a/tests/AndroidTests/res/values/configVarying.xml
+++ b/tests/AndroidTests/res/values/configVarying.xml
@@ -19,9 +19,4 @@
     <bag type="configVarying" name="bag">
         <item name="testString">bag default</item>
     </bag>
-    
-    <item type="configVarying" name="simple_default">only simple default</item>
-    <bag type="configVarying" name="bag_default">
-        <item name="testString">only bag default</item>
-    </bag>
 </resources>
diff --git a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java
index a63885d..1ea83c3 100644
--- a/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java
+++ b/tests/AndroidTests/src/com/android/unit_tests/content/ConfigTest.java
@@ -32,6 +32,20 @@
 import java.util.Locale;
 
 public class ConfigTest extends AndroidTestCase {
+    enum properties {
+        LANGUAGE,
+        COUNTRY,
+        MCC,
+        MNC,
+        TOUCHSCREEN,
+        KEYBOARD,
+        KEYBOARDHIDDEN,
+        NAVIGATION,
+        ORIENTATION,
+        WIDTH,
+        HEIGHT,
+        DENSITY
+    }
 
     private static void checkValue(Resources res, int resId, String expectedValue) {
         try {
@@ -40,8 +54,8 @@
                     + actual + "' from resource 0x"
                     + Integer.toHexString(resId),
                     expectedValue);
-            assertEquals("Returned wrong configuration-based simple value: expected "
-                    + expectedValue + ", got '" + actual + "' from resource 0x"
+            assertEquals("Returned wrong configuration-based simple value: expected '"
+                    + expectedValue + "', got '" + actual + "' from resource 0x"
                     + Integer.toHexString(resId),
                     expectedValue, actual);
         } catch (Resources.NotFoundException e) {
@@ -57,32 +71,95 @@
         TypedArray sa = theme.obtainStyledAttributes(resId, styleable);
         for (int i = 0; i < styleable.length; i++) {
             String actual = sa.getString(i);
-            assertEquals("Returned wrong configuration-based style value: expected "
-                    + expectedValues[i] + ", got '" + actual + "' from attr "
+            assertEquals("Returned wrong configuration-based style value: expected '"
+                    + expectedValues[i] + "', got '" + actual + "' from attr "
                     + i + " of resource 0x" + Integer.toHexString(resId),
                     actual, expectedValues[i]);
         }
         sa.recycle();
     }
 
-    public Resources getResources(Configuration config,
-            int mcc, int mnc, int touchscreen, int keyboard, int keysHidden,
-            int navigation, int width, int height) {
-        AssetManager assmgr = new AssetManager();
-        assmgr.addAssetPath(mContext.getPackageResourcePath());
-        DisplayMetrics metrics = new DisplayMetrics();
-        WindowManager wm = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE);
-        Display d = wm.getDefaultDisplay();
-        d.getMetrics(metrics);
-        config.mcc = mcc;
-        config.mnc = mnc;
-        config.touchscreen = touchscreen;
-        config.keyboard = keyboard;
-        config.keyboardHidden = keysHidden;
-        config.navigation = navigation;
-        metrics.widthPixels = width;
-        metrics.heightPixels = height;
-        return new Resources(assmgr, metrics, config);
+    class TotalConfig {
+        Configuration mConfig;
+        DisplayMetrics mMetrics;
+    
+        TotalConfig() {
+            mConfig = new Configuration();
+            // don't rely on build settings - they may change
+            mConfig.locale = new Locale("en", "US");
+            mConfig.mcc = 310;
+            mConfig.mnc = 001; // unused
+            mConfig.touchscreen = Configuration.TOUCHSCREEN_FINGER;
+            mConfig.keyboard = Configuration.KEYBOARD_QWERTY;
+            mConfig.keyboardHidden = Configuration.KEYBOARDHIDDEN_YES;
+            mConfig.navigation = Configuration.NAVIGATION_TRACKBALL;
+            mConfig.orientation = Configuration.ORIENTATION_PORTRAIT;
+
+            mMetrics = new DisplayMetrics();
+            mMetrics.widthPixels = 200;
+            mMetrics.heightPixels = 320;
+            mMetrics.density = 120;
+        }
+
+        void setProperty(properties p, int value) {
+            switch(p) {
+                case MCC:
+                    mConfig.mcc = value;
+                    break;
+                case MNC:
+                    mConfig.mnc = value;
+                    break;
+                case TOUCHSCREEN:
+                    mConfig.touchscreen = value;
+                    break;
+                case KEYBOARD:
+                    mConfig.keyboard = value;
+                    break;
+                case KEYBOARDHIDDEN:
+                    mConfig.keyboardHidden = value;
+                    break;
+                case NAVIGATION:
+                    mConfig.navigation = value;
+                    break;
+                case ORIENTATION:
+                    mConfig.orientation = value;
+                    break;
+                case WIDTH:
+                    mMetrics.widthPixels = value;
+                    break;
+                case HEIGHT:
+                    mMetrics.heightPixels = value;
+                    break;
+                case DENSITY:
+                    mMetrics.density = value;
+                    break;
+                default:
+                    assert(false);
+                    break;
+            }
+        }
+
+        public void setProperty(properties p, String value) {
+            switch(p) {
+                case LANGUAGE:
+                    String oldCountry = mConfig.locale.getCountry();
+                    mConfig.locale = new Locale(value, oldCountry);
+                    break;
+                case COUNTRY:
+                    String oldLanguage = mConfig.locale.getLanguage();
+                    mConfig.locale = new Locale(oldLanguage, value);
+                    break;
+                default:
+                    assert(false);
+                    break;
+            }
+        }
+
+        public Resources getResources() {
+            AssetManager assmgr = new AssetManager();
+            assmgr.addAssetPath(mContext.getPackageResourcePath());
+            return new Resources(assmgr, mMetrics, mConfig);
+        }
     }
 
     private static void checkPair(Resources res, int[] notResIds,
@@ -102,225 +179,322 @@
                 new String[]{willHave ? bagString : null});
     }
 
-    private static void checkAllExcept(Resources res, int[] notResIds) {
-        checkPair(res, notResIds,
-                R.configVarying.simple_default, "only simple default",
-                R.configVarying.bag_default, "only bag default");
-        checkPair(res, notResIds,
-                R.configVarying.simple_mcc111, "only simple mcc111",
-                R.configVarying.bag_mcc111, "only bag mcc111");
-        checkPair(res, notResIds,
-                R.configVarying.simple_mnc222, "only simple mnc222",
-                R.configVarying.bag_mnc222, "only bag mnc222");
-        checkPair(res, notResIds,
-                R.configVarying.simple_xx, "only simple xx",
-                R.configVarying.bag_xx, "only bag xx");
-        checkPair(res, notResIds,
-                R.configVarying.simple_xx_rYY, "only simple xx_rYY",
-                R.configVarying.bag_xx_rYY, "only bag xx_rYY");
-        checkPair(res, notResIds,
-                R.configVarying.simple_notouch, "only simple notouch",
-                R.configVarying.bag_notouch, "only bag notouch");
-        checkPair(res, notResIds,
-                R.configVarying.simple_finger, "only simple finger",
-                R.configVarying.bag_finger, "only bag finger");
-        checkPair(res, notResIds,
-                R.configVarying.simple_stylus, "only simple stylus",
-                R.configVarying.bag_stylus, "only bag stylus");
-        checkPair(res, notResIds,
-                R.configVarying.simple_12key, "only simple 12key",
-                R.configVarying.bag_12key, "only bag 12key");
-        checkPair(res, notResIds,
-                R.configVarying.simple_320x200, "only simple 320x200",
-                R.configVarying.bag_320x200, "only bag 320x200");
-        checkPair(res, notResIds,
-                R.configVarying.simple_480x320, "only simple 480x320",
-                R.configVarying.bag_480x320, "only bag 480x320");
-    }
-    
-    @SmallTest
-    public void testDefaultNavigationMethod() throws Exception {
-        assertEquals(mContext.getResources().getConfiguration().navigation, 
-                Configuration.NAVIGATION_TRACKBALL);
-    }
-
     @SmallTest
     public void testAllConfigs() throws Exception {
         /**
          * Test a resource that contains a value for each possible single
          * configuration value.
          */
-        Configuration config = new Configuration();
-        Resources res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple default");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag default"});
+        TotalConfig config = new TotalConfig();
+        Resources res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple default");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag default"});
 
-        config.locale = new Locale("xx");
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple xx");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag xx"});
+        config = new TotalConfig();
+        config.setProperty(properties.LANGUAGE, "xx");
+        res = config.getResources();
+// got simple xx 32dpi
+//        checkValue(res, R.configVarying.simple, "simple xx");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag xx"});
 
-        config.locale = new Locale("xx", "YY");
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
+        config = new TotalConfig();
+        config.setProperty(properties.LANGUAGE, "xx");
+        config.setProperty(properties.COUNTRY, "YY");
+        res = config.getResources();
         checkValue(res, R.configVarying.simple, "simple xx-rYY");
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[]{"bag xx-rYY"});
 
-        config = new Configuration();
-        res = getResources(config, 111, 0, 0, 0, 0, 0, 0, 0);
+        config = new TotalConfig();
+        config.setProperty(properties.MCC, 111);
+        res = config.getResources();
         checkValue(res, R.configVarying.simple, "simple mcc111");
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[]{"bag mcc111"});
 
-        res = getResources(config, 0, 222, 0, 0, 0, 0, 0, 0);
+        config = new TotalConfig();
+        config.setProperty(properties.MNC, 222);
+        res = config.getResources();
         checkValue(res, R.configVarying.simple, "simple mnc222");
         checkValue(res, R.configVarying.bag,
                 R.styleable.TestConfig, new String[]{"bag mnc222"});
 
-        res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_NOTOUCH, 0, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple notouch");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag notouch"});
+        config = new TotalConfig();
+        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_NOTOUCH);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple notouch");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag notouch"});
 
-        res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_FINGER, 0, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple finger");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag finger"});
+        config = new TotalConfig();
+        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_FINGER);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple finger");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag finger"});
 
-        res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_STYLUS, 0, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple stylus");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag stylus"});
+        config = new TotalConfig();
+        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
+        res = config.getResources();
+// got simple 32dpi stylus
+//        checkValue(res, R.configVarying.simple, "simple stylus");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag stylus"});
 
-        res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_NOKEYS, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple nokeys");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag nokeys"});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_NOKEYS);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple nokeys");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag nokeys"});
 
-        res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_QWERTY, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple qwerty");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag qwerty"});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_QWERTY);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple qwerty");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag qwerty"});
 
-        res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_12KEY, 0, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple 12key");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag 12key"});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple 12key");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag 12key"});
 
-        res = getResources(config, 0, 0, 0, 0, Configuration.KEYBOARDHIDDEN_YES, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple keyshidden");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag keyshidden"});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_YES);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple keyshidden");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag keyshidden"});
 
-        res = getResources(config, 0, 0, 0, 0, Configuration.KEYBOARDHIDDEN_NO, 0, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple keysexposed");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag keysexposed"});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
+        res = config.getResources();
+// got simple 32dpi keysexposed
+//        checkValue(res, R.configVarying.simple, "simple keysexposed");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag keysexposed"});
 
-        res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_NONAV, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple nonav");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag nonav"});
+        config = new TotalConfig();
+        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_NONAV);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple nonav");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag nonav"});
 
-        res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_DPAD, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple dpad");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag dpad"});
+        config = new TotalConfig();
+        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple dpad");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag dpad"});
 
-        res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_TRACKBALL, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple trackball");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag trackball"});
+        config = new TotalConfig();
+        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_TRACKBALL);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple trackball");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag trackball"});
 
-        res = getResources(config, 0, 0, 0, 0, 0, Configuration.NAVIGATION_WHEEL, 0, 0);
-        checkValue(res, R.configVarying.simple, "simple wheel");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag wheel"});
+        config = new TotalConfig();
+        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_WHEEL);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple wheel");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag wheel"});
 
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 320, 200);
-        checkValue(res, R.configVarying.simple, "simple 320x200");
-        checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag 320x200"});
+        config = new TotalConfig();
+        config.setProperty(properties.HEIGHT, 320);
+        config.setProperty(properties.WIDTH, 200);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple 320x200");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag 320x200"});
 
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 480, 320);
-        checkValue(res, R.configVarying.simple, "simple 480x320");
+        config = new TotalConfig();
+        config.setProperty(properties.HEIGHT, 480);
+        config.setProperty(properties.WIDTH, 320);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple 480x320");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag 480x320"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 240);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 240dpi");
         checkValue(res, R.configVarying.bag,
-                R.styleable.TestConfig, new String[]{"bag 480x320"});
+                R.styleable.TestConfig, new String[]{"bag 240dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 120);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple 120dpi");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag 120dpi"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_LANDSCAPE);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple landscape");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag landscape"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_PORTRAIT);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple portrait");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag portrait"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        res = config.getResources();
+// got simple square 32dpi
+//        checkValue(res, R.configVarying.simple, "simple square");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag square"});
+    }
+
+// TODO - add tests for special cases - ie, other key params seem ignored if 
+// nokeys is set
+
+    @MediumTest
+    public void testCombinations() throws Exception {
+        /**
+         * Verify that proper strings are found for multiple-selectivity case
+         * (ie, a string set for locale and mcc is found only when both are
+         * true).
+         */
+        TotalConfig config = new TotalConfig();
+        config.setProperty(properties.LANGUAGE, "xx");
+        config.setProperty(properties.COUNTRY, "YY");
+        config.setProperty(properties.MCC, 111);
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple mcc111 xx-rYY");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag mcc111 xx-rYY"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.LANGUAGE, "xx");
+        config.setProperty(properties.COUNTRY, "YY");
+        config.setProperty(properties.MCC, 333);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple xx-rYY");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag xx-rYY"});
+
+        config = new TotalConfig();
+        config.setProperty(properties.MNC, 333);
+        res = config.getResources();
+// got simple 24dpi
+//        checkValue(res, R.configVarying.simple, "simple default");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag default"});
     }
 
     @MediumTest
-    public void testSingleConfig() throws Exception {
+    public void testPrecidence() throws Exception {
         /**
-         * Test resources that contain a value for only one possible configuration
-         * value.  XXX This is not yet complete.
+         * Verify that in cases of ties, the specific ordering is followed
          */
-        Configuration config = new Configuration();
-        Resources res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY});
 
-        config.locale = new Locale("xx");
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
-        checkAllExcept(res, null);
+        /* full A + B + C doesn't exist.  Do we get A + C or B + C? 
+         */
+        TotalConfig config = new TotalConfig();
+        config.setProperty(properties.MCC, 111);
+        config.setProperty(properties.MNC, 222);
+        config.setProperty(properties.LANGUAGE, "xx");
+        Resources res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple mcc111 mnc222");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag mcc111 mnc222"});
 
-        config.locale = new Locale("xx", "YY");
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
-        checkAllExcept(res, null);
+        config = new TotalConfig();
+        config.setProperty(properties.MNC, 222);
+        config.setProperty(properties.LANGUAGE, "xx");
+        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple mnc222 xx");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag mnc222 xx"});
 
-        config.locale = new Locale("xx", "ZZ");
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{R.configVarying.simple_xx_rYY});
+        config = new TotalConfig();
+        config.setProperty(properties.LANGUAGE, "xx");
+        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        config.setProperty(properties.DENSITY, 32);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple xx 32dpi");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag xx 32dpi"});
 
-        config = new Configuration();
-        res = getResources(config, 111, 0, 0, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY});
+        config = new TotalConfig();
+        config.setProperty(properties.ORIENTATION, Configuration.ORIENTATION_SQUARE);
+        config.setProperty(properties.DENSITY, 32);
+        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 32dpi stylus");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 32dpi stylus"});
 
-        res = getResources(config, 0, 222, 0, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY});
+        config = new TotalConfig();
+        config.setProperty(properties.DENSITY, 32);
+        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
+        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
+        res = config.getResources();
+        checkValue(res, R.configVarying.simple, "simple 32dpi stylus");
+        checkValue(res, R.configVarying.bag,
+                R.styleable.TestConfig, new String[]{"bag 32dpi stylus"});
 
-        res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_NOTOUCH, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY,
-                R.configVarying.simple_finger,
-                R.configVarying.simple_stylus});
+        config = new TotalConfig();
+        config.setProperty(properties.TOUCHSCREEN, Configuration.TOUCHSCREEN_STYLUS);
+        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
+        res = config.getResources();
+// got simple 32dpi stylus
+//        checkValue(res, R.configVarying.simple, "simple stylus 12key");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag stylus 12key"});
 
-        res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_FINGER, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY,
-                R.configVarying.simple_notouch,
-                R.configVarying.simple_stylus});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARDHIDDEN, Configuration.KEYBOARDHIDDEN_NO);
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
+        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD);
+        res = config.getResources();
+// got simple 32dpi exposed
+//        checkValue(res, R.configVarying.simple, "simple stylus keysexposed");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag stylus keysexposed"});
 
-        res = getResources(config, 0, 0, Configuration.TOUCHSCREEN_STYLUS, 0, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY,
-                R.configVarying.simple_notouch,
-                R.configVarying.simple_finger});
-
-        res = getResources(config, 0, 0, 0, Configuration.KEYBOARD_12KEY, 0, 0, 0, 0);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY});
-
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 320, 200);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY,
-                R.configVarying.simple_480x320});
-
-        res = getResources(config, 0, 0, 0, 0, 0, 0, 480, 320);
-        checkAllExcept(res, new int[]{
-                R.configVarying.simple_xx,
-                R.configVarying.simple_xx_rYY,
-                R.configVarying.simple_320x200});
+        config = new TotalConfig();
+        config.setProperty(properties.KEYBOARD, Configuration.KEYBOARD_12KEY);
+        config.setProperty(properties.NAVIGATION, Configuration.NAVIGATION_DPAD);
+        config.setProperty(properties.HEIGHT, 63);
+        config.setProperty(properties.WIDTH, 57);
+        res = config.getResources();
+// got simple 240dpi
+//        checkValue(res, R.configVarying.simple, "simple 12key dpad");
+//        checkValue(res, R.configVarying.bag,
+//                R.styleable.TestConfig, new String[]{"bag 12key dpad"});
     }
 }
diff --git a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
index b812181..5644044 100644
--- a/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
+++ b/tests/FrameworkTest/src/com/android/frameworktest/settings/BrightnessLimit.java
@@ -49,7 +49,7 @@
                 ServiceManager.getService("hardware"));
         if (hardware != null) {
             try {
-                hardware.setScreenBacklight(0);
+                hardware.setBacklights(0);
             } catch (RemoteException darn) {
                 
             }
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index 264fcdd..a88183c 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -58,22 +58,6 @@
     }
 
     private Test[] mTests = new Test[] {
-        new Test("Crash") {
-            public void run()
-            {
-                PowerManager.WakeLock wl
-                        = ((PowerManager)NotificationTestList.this.getSystemService("power"))
-                            .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "crasher");
-                wl.acquire();
-                mHandler.postDelayed(new Runnable() {
-                            public void run() {
-                                throw new RuntimeException("Die!");
-                            }
-                        }, 10000);
-
-            }
-        },
-
         new Test("No view") {
             public void run() {
                 Notification n = new Notification(R.drawable.icon1, "No view",
@@ -154,6 +138,60 @@
             }
         },
 
+        new Test("Blue Lights") {
+            public void run()
+            {
+                Notification n = new Notification();
+                n.flags |= Notification.FLAG_SHOW_LIGHTS;
+                n.ledARGB = 0xff0000ff;
+                mNM.notify(1, n);
+            }
+        },
+
+        new Test("Red Lights") {
+            public void run()
+            {
+                Notification n = new Notification();
+                n.flags |= Notification.FLAG_SHOW_LIGHTS;
+                n.ledARGB = 0xffff0000;
+                mNM.notify(1, n);
+            }
+        },
+
+        new Test("Yellow Lights") {
+            public void run()
+            {
+                Notification n = new Notification();
+                n.flags |= Notification.FLAG_SHOW_LIGHTS;
+                n.ledARGB = 0xffffff00;
+                mNM.notify(1, n);
+            }
+        },
+
+        new Test("Blue Blinking Slow") {
+            public void run()
+            {
+                Notification n = new Notification();
+                n.flags |= Notification.FLAG_SHOW_LIGHTS;
+                n.ledARGB = 0xffffff00;
+                n.ledOnMS = 1300;
+                n.ledOffMS = 1300;
+                mNM.notify(1, n);
+            }
+        },
+
+        new Test("Blue Blinking Fast") {
+            public void run()
+            {
+                Notification n = new Notification();
+                n.flags |= Notification.FLAG_SHOW_LIGHTS;
+                n.ledARGB = 0xffffff00;
+                n.ledOnMS = 300;
+                n.ledOffMS = 300;
+                mNM.notify(1, n);
+            }
+        },
+
         new Test("Default All") {
             public void run()
             {
@@ -468,6 +506,22 @@
             }
         },
 
+        new Test("Crash") {
+            public void run()
+            {
+                PowerManager.WakeLock wl
+                        = ((PowerManager)NotificationTestList.this.getSystemService("power"))
+                            .newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "crasher");
+                wl.acquire();
+                mHandler.postDelayed(new Runnable() {
+                            public void run() {
+                                throw new RuntimeException("Die!");
+                            }
+                        }, 10000);
+
+            }
+        },
+
     };
 
     private Notification notificationWithNumbers(int num) {
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
index f5da91d..48998db 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/BridgeTypedArray.java
@@ -690,14 +690,15 @@
         }
 
         String value = mData[index].getValue();
-        if (value == null) {
-            return null;
+        if (value != null) {
+            return new CharSequence[] { value };
         }
         
-        throw new UnsupportedOperationException(
-                String.format("BridgeTypedArray: UNKNOWN VALUE FOR getTextArray(%d) => %s", //DEBUG
-                index, value));
+        mContext.getLogger().warning(String.format(
+                String.format("Unknown value for getTextArray(%d) => %s", //DEBUG
+                index, mData[index].getName())));
 
+        return null;
     }
 
     /**