Merge change 24887 into eclair

* changes:
  Fix http://b/issue?id=2098873 (drawing glitch in SeekBar).
diff --git a/api/current.xml b/api/current.xml
index f8cf61f..38490f3 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -16089,6 +16089,17 @@
  visibility="public"
 >
 </method>
+<method name="onBackPressed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onChildTitleChanged"
  return="void"
  abstract="false"
@@ -16318,6 +16329,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyLongPress"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyMultiple"
  return="boolean"
  abstract="false"
@@ -20085,6 +20111,17 @@
  visibility="public"
 >
 </method>
+<method name="onBackPressed"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onContentChanged"
  return="void"
  abstract="false"
@@ -20219,6 +20256,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyLongPress"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyMultiple"
  return="boolean"
  abstract="false"
@@ -24714,6 +24766,17 @@
  visibility="public"
 >
 </method>
+<method name="getFastDrawable"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getInstance"
  return="android.app.WallpaperManager"
  abstract="false"
@@ -24738,6 +24801,17 @@
  visibility="public"
 >
 </method>
+<method name="peekFastDrawable"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="setBitmap"
  return="void"
  abstract="false"
@@ -63330,7 +63404,7 @@
  type="android.graphics.drawable.BitmapDrawable"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="filepath" type="java.lang.String">
@@ -63343,6 +63417,30 @@
  deprecated="not deprecated"
  visibility="public"
 >
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+<parameter name="filepath" type="java.lang.String">
+</parameter>
+</constructor>
+<constructor name="BitmapDrawable"
+ type="android.graphics.drawable.BitmapDrawable"
+ static="false"
+ final="false"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="is" type="java.io.InputStream">
+</parameter>
+</constructor>
+<constructor name="BitmapDrawable"
+ type="android.graphics.drawable.BitmapDrawable"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
 <parameter name="is" type="java.io.InputStream">
 </parameter>
 </constructor>
@@ -64521,6 +64619,19 @@
  visibility="public"
 >
 </method>
+<method name="newDrawable"
+ return="android.graphics.drawable.Drawable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="res" type="android.content.res.Resources">
+</parameter>
+</method>
 </class>
 <class name="DrawableContainer"
  extends="android.graphics.drawable.Drawable"
@@ -69511,6 +69622,17 @@
  visibility="public"
 >
 </constructor>
+<method name="getKeyDispatcherState"
+ return="android.view.KeyEvent.DispatcherState"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="onBind"
  return="android.os.IBinder"
  abstract="false"
@@ -70256,6 +70378,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyLongPress"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyMultiple"
  return="boolean"
  abstract="false"
@@ -101558,6 +101695,17 @@
  visibility="protected"
 >
 </method>
+<method name="quit"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 </class>
 <interface name="IBinder"
  abstract="true"
@@ -144753,7 +144901,7 @@
  type="android.view.KeyEvent"
  static="false"
  final="false"
- deprecated="not deprecated"
+ deprecated="deprecated"
  visibility="public"
 >
 <parameter name="origEvent" type="android.view.KeyEvent">
@@ -144810,6 +144958,25 @@
 <parameter name="newRepeat" 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>
+<parameter name="newFlags" type="int">
+</parameter>
+</method>
 <method name="describeContents"
  return="int"
  abstract="false"
@@ -144828,11 +144995,28 @@
  synchronized="false"
  static="false"
  final="true"
+ deprecated="deprecated"
+ visibility="public"
+>
+<parameter name="receiver" type="android.view.KeyEvent.Callback">
+</parameter>
+</method>
+<method name="dispatch"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
  deprecated="not deprecated"
  visibility="public"
 >
 <parameter name="receiver" type="android.view.KeyEvent.Callback">
 </parameter>
+<parameter name="state" type="android.view.KeyEvent.DispatcherState">
+</parameter>
+<parameter name="target" type="java.lang.Object">
+</parameter>
 </method>
 <method name="getAction"
  return="int"
@@ -145079,6 +145263,17 @@
  visibility="public"
 >
 </method>
+<method name="isLongPress"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="isModifierKey"
  return="boolean"
  abstract="false"
@@ -145136,6 +145331,28 @@
  visibility="public"
 >
 </method>
+<method name="isTracking"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="startTracking"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="writeToParcel"
  return="void"
  abstract="false"
@@ -145205,6 +145422,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_CANCELED_LONG_PRESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="256"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_EDITOR_ACTION"
  type="int"
  transient="false"
@@ -145238,6 +145466,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_LONG_PRESS"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="128"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_SOFT_KEYBOARD"
  type="int"
  transient="false"
@@ -145249,6 +145488,17 @@
  visibility="public"
 >
 </field>
+<field name="FLAG_TRACKING"
+ type="int"
+ transient="false"
+ volatile="false"
+ value="512"
+ static="true"
+ final="true"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</field>
 <field name="FLAG_VIRTUAL_HARD_KEY"
  type="int"
  transient="false"
@@ -146394,6 +146644,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyLongPress"
+ return="boolean"
+ abstract="true"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyMultiple"
  return="boolean"
  abstract="true"
@@ -146427,6 +146692,101 @@
 </parameter>
 </method>
 </interface>
+<class name="KeyEvent.DispatcherState"
+ extends="java.lang.Object"
+ abstract="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<constructor name="KeyEvent.DispatcherState"
+ type="android.view.KeyEvent.DispatcherState"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</constructor>
+<method name="handleUpEvent"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="isTracking"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="performedLongPress"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
+<method name="reset"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+</method>
+<method name="startTracking"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+<parameter name="target" type="java.lang.Object">
+</parameter>
+</method>
+</class>
 <class name="LayoutInflater"
  extends="java.lang.Object"
  abstract="true"
@@ -150801,6 +151161,17 @@
  visibility="public"
 >
 </method>
+<method name="getKeyDispatcherState"
+ return="android.view.KeyEvent.DispatcherState"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getLayoutParams"
  return="android.view.ViewGroup.LayoutParams"
  abstract="false"
@@ -151927,6 +152298,21 @@
 <parameter name="event" type="android.view.KeyEvent">
 </parameter>
 </method>
+<method name="onKeyLongPress"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="keyCode" type="int">
+</parameter>
+<parameter name="event" type="android.view.KeyEvent">
+</parameter>
+</method>
 <method name="onKeyMultiple"
  return="boolean"
  abstract="false"
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 8cfb758..6abed93 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1398,9 +1398,8 @@
             }
 
             if (!imsi.equals(storedImsi) && !TextUtils.isEmpty(storedImsi)) {
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "wiping all passwords and authtokens");
-                }
+                Log.w(TAG, "wiping all passwords and authtokens because IMSI changed ("
+                        + "stored=" + storedImsi + ", current=" + imsi + ")");
                 SQLiteDatabase db = mOpenHelper.getWritableDatabase();
                 db.beginTransaction();
                 try {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index 8c10091..be243a5 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -1752,8 +1752,9 @@
      * 
      * <p>If the focused view didn't want this event, this method is called.
      *
-     * <p>The default implementation handles KEYCODE_BACK to stop the activity
-     * and go back, and other default key handling if configured with {@link #setDefaultKeyMode}.
+     * <p>The default implementation sets up state to call
+     * {@link #onKeyLongPress}, and does other default key handling
+     * if configured with {@link #setDefaultKeyMode}.
      * 
      * @return Return <code>true</code> to prevent this event from being propagated
      * further, or <code>false</code> to indicate that you have not handled 
@@ -1762,16 +1763,19 @@
      * @see android.view.KeyEvent
      */
     public boolean onKeyDown(int keyCode, KeyEvent event)  {
-        if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
-            finish();
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            event.startTracking();
             return true;
         }
         
         if (mDefaultKeyMode == DEFAULT_KEYS_DISABLE) {
             return false;
         } else if (mDefaultKeyMode == DEFAULT_KEYS_SHORTCUT) {
-            return getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL, 
-                                                    keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE);
+            if (getWindow().performPanelShortcut(Window.FEATURE_OPTIONS_PANEL, 
+                    keyCode, event, Menu.FLAG_ALWAYS_PERFORM_CLOSE)) {
+                return true;
+            }
+            return false;
         } else {
             // Common code for DEFAULT_KEYS_DIALER & DEFAULT_KEYS_SEARCH_*
             boolean clearSpannable = false;
@@ -1780,8 +1784,8 @@
                 clearSpannable = true;
                 handled = false;
             } else {
-                handled = TextKeyListener.getInstance().onKeyDown(null, mDefaultKeySsb, 
-                                                                  keyCode, event);
+                handled = TextKeyListener.getInstance().onKeyDown(
+                        null, mDefaultKeySsb, keyCode, event);
                 if (handled && mDefaultKeySsb.length() > 0) {
                     // something useable has been typed - dispatch it now.
 
@@ -1813,11 +1817,23 @@
     }
 
     /**
+     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
+     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
+     * the event).
+     */
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    /**
      * Called when a key was released and not handled by any of the views
      * inside of the activity. So, for example, key presses while the cursor 
      * is inside a TextView will not trigger the event (unless it is a navigation
      * to another object) because TextView handles its own key presses.
      * 
+     * <p>The default implementation handles KEYCODE_BACK to stop the activity
+     * and go back.
+     * 
      * @return Return <code>true</code> to prevent this event from being propagated
      * further, or <code>false</code> to indicate that you have not handled 
      * this event and it should continue to be propagated. 
@@ -1825,6 +1841,11 @@
      * @see KeyEvent
      */
     public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
+                && !event.isCanceled()) {
+            onBackPressed();
+            return true;
+        }
         return false;
     }
 
@@ -1838,6 +1859,15 @@
     }
     
     /**
+     * Called when the activity has detected the user's press of the back
+     * key.  The default implementation simply finishes the current activity,
+     * but you can override this to do whatever you want.
+     */
+    public void onBackPressed() {
+        finish();
+    }
+    
+    /**
      * Called when a touch screen event was not handled by any of the views
      * under it.  This is most useful to process touch events that happen
      * outside of your window bounds, where there is no view to receive it.
@@ -1909,9 +1939,10 @@
     /**
      * Called when the current {@link Window} of the activity gains or loses
      * focus.  This is the best indicator of whether this activity is visible
-     * to the user.
+     * to the user.  The default implementation clears the key tracking
+     * state, so should always be called.
      * 
-     * <p>Note that this provides information what global focus state, which
+     * <p>Note that this provides information about global focus state, which
      * is managed independently of activity lifecycles.  As such, while focus
      * changes will generally have some relation to lifecycle changes (an
      * activity that is stopped will not generally get window focus), you
@@ -1988,7 +2019,8 @@
         if (getWindow().superDispatchKeyEvent(event)) {
             return true;
         }
-        return event.dispatch(this);
+        return event.dispatch(this, mDecor != null
+                ? mDecor.getKeyDispatcherState() : null, this);
     }
 
     /**
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 1b96af9..58e8b32 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -481,17 +481,15 @@
      * 
      * <p>If the focused view didn't want this event, this method is called.
      *
-     * <p>The default implementation handles KEYCODE_BACK to close the
-     * dialog.
+     * <p>The default implementation consumed the KEYCODE_BACK to later
+     * handle it in {@link #onKeyUp}.
      *
      * @see #onKeyUp
      * @see android.view.KeyEvent
      */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
         if (keyCode == KeyEvent.KEYCODE_BACK) {
-            if (mCancelable) {
-                cancel();
-            }
+            event.startTracking();
             return true;
         }
 
@@ -499,12 +497,29 @@
     }
 
     /**
+     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
+     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
+     * the event).
+     */
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    /**
      * A key was released.
      * 
+     * <p>The default implementation handles KEYCODE_BACK to close the
+     * dialog.
+     *
      * @see #onKeyDown
      * @see KeyEvent
      */
     public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (keyCode == KeyEvent.KEYCODE_BACK && event.isTracking()
+                && !event.isCanceled()) {
+            onBackPressed();
+            return true;
+        }
         return false;
     }
 
@@ -518,6 +533,17 @@
     }
     
     /**
+     * Called when the dialog has detected the user's press of the back
+     * key.  The default implementation simply cancels the dialog (only if
+     * it is cancelable), but you can override this to do whatever you want.
+     */
+    public void onBackPressed() {
+        if (mCancelable) {
+            cancel();
+        }
+    }
+    
+    /**
      * Called when a touch screen event was not handled by any of the views
      * under it. This is most useful to process touch events that happen outside
      * of your window bounds, where there is no view to receive it.
@@ -599,7 +625,8 @@
         if (mWindow.superDispatchKeyEvent(event)) {
             return true;
         }
-        return event.dispatch(this);
+        return event.dispatch(this, mDecor != null
+                ? mDecor.getKeyDispatcherState() : null, this);
     }
 
     /**
diff --git a/core/java/android/app/SearchDialog.java b/core/java/android/app/SearchDialog.java
index f474f06..62dc9b2 100644
--- a/core/java/android/app/SearchDialog.java
+++ b/core/java/android/app/SearchDialog.java
@@ -745,11 +745,9 @@
             return true;
         }
         
-        if (keyCode == KeyEvent.KEYCODE_SEARCH && event.getRepeatCount() < 1) {
-            // If the search key is pressed, toggle between global and in-app search. If we are
-            // currently doing global search and there is no in-app search context to toggle to,
-            // just don't do anything.
-            return toggleGlobalSearch();
+        if (keyCode == KeyEvent.KEYCODE_SEARCH) {
+            // Consume search key for later use.
+            return true;
         }
 
         // if it's an action specified by the searchable activity, launch the
@@ -763,6 +761,29 @@
         return false;
     }
     
+    @Override
+    public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (DBG) Log.d(LOG_TAG, "onKeyUp(" + keyCode + "," + event + ")");
+        if (mSearchable == null) {
+            return false;
+        }
+
+        // handle back key to go back to previous searchable, etc.
+        if (handleBackKey(keyCode, event)) {
+            return true;
+        }
+        
+        if (keyCode == KeyEvent.KEYCODE_SEARCH && event.isTracking()
+                && !event.isCanceled()) {
+            // If the search key is pressed, toggle between global and in-app search. If we are
+            // currently doing global search and there is no in-app search context to toggle to,
+            // just don't do anything.
+            return toggleGlobalSearch();
+        }
+        
+        return false;
+    }
+    
     /**
      * Callback to watch the textedit field for empty/non-empty
      */
@@ -1137,6 +1158,11 @@
         String action = mGlobalSearchMode ? Intent.ACTION_WEB_SEARCH : Intent.ACTION_SEARCH;
         Intent intent = createIntent(action, null, null, query, null,
                 actionKey, actionMsg);
+        // Allow GlobalSearch to log and create shortcut for searches launched by
+        // the search button, enter key or an action key.
+        if (mGlobalSearchMode) {
+            mSuggestionsAdapter.reportSearch(query);
+        }
         launchIntent(intent);
     }
     
@@ -1495,21 +1521,24 @@
      * 
      * @return <code>true</code> if there was a previous component that we could go back to.
      */
-    private boolean backToPreviousComponent() {
+    private boolean backToPreviousComponent(boolean doIt) {
         ComponentName previous = popPreviousComponent();
         if (previous == null) {
             return false;
         }
-        if (!show(previous, mAppSearchData, false)) {
-            Log.w(LOG_TAG, "Failed to switch to source " + previous);
-            return false;
-        }
         
-        // must touch text to trigger suggestions
-        // TODO: should this be the text as it was when the user left
-        // the source that we are now going back to?
-        String query = mSearchAutoComplete.getText().toString();
-        setUserQuery(query);
+        if (doIt) {
+            if (!show(previous, mAppSearchData, false)) {
+                Log.w(LOG_TAG, "Failed to switch to source " + previous);
+                return false;
+            }
+            
+            // must touch text to trigger suggestions
+            // TODO: should this be the text as it was when the user left
+            // the source that we are now going back to?
+            String query = mSearchAutoComplete.getText().toString();
+            setUserQuery(query);
+        }
         
         return true;
     }
@@ -1655,6 +1684,7 @@
     public static class SearchAutoComplete extends AutoCompleteTextView {
 
         private int mThreshold;
+        private int mLastKeyDown;
         private SearchDialog mSearchDialog;
         
         public SearchAutoComplete(Context context) {
@@ -1735,27 +1765,44 @@
          */
         @Override
         public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+            mLastKeyDown = keyCode;
             if (mSearchDialog.mSearchable == null) {
                 return false;
             }
-            if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
-                if (mSearchDialog.backToPreviousComponent()) {
-                    return true;
+            if (keyCode == KeyEvent.KEYCODE_BACK) {
+                if (event.getAction() == KeyEvent.ACTION_DOWN
+                        && event.getRepeatCount() == 0) {
+                    // We releae the back key, might we want to do
+                    // something before the IME?
+                    if (mSearchDialog.backToPreviousComponent(false)) {
+                        return true;
+                    }
+                    if (isInputMethodNotNeeded() ||
+                            (isEmpty() && getDropDownChildCount() >= getAdapterCount())) {
+                        return true;
+                    }
+                    mLastKeyDown = 0;
+                    return false; // will dismiss soft keyboard if necessary
+                } else if (event.getAction() == KeyEvent.ACTION_UP
+                        && mLastKeyDown == keyCode && !event.isCanceled()) {
+                    if (mSearchDialog.backToPreviousComponent(true)) {
+                        return true;
+                    }
+                    // If the drop-down obscures the keyboard, the user wouldn't see anything
+                    // happening when pressing back, so we dismiss the entire dialog instead.
+                    //
+                    // also: if there is no text entered, we also want to dismiss the whole dialog,
+                    // not just the soft keyboard.  the exception to this is if there are shortcuts
+                    // that aren't displayed (e.g are being obscured by the soft keyboard); in that
+                    // case we want to dismiss the soft keyboard so the user can see the rest of the
+                    // shortcuts.
+                    if (isInputMethodNotNeeded() ||
+                            (isEmpty() && getDropDownChildCount() >= getAdapterCount())) {
+                        mSearchDialog.cancel();
+                        return true;
+                    }
+                    return false; // will dismiss soft keyboard if necessary
                 }
-                // If the drop-down obscures the keyboard, the user wouldn't see anything
-                // happening when pressing back, so we dismiss the entire dialog instead.
-                //
-                // also: if there is no text entered, we also want to dismiss the whole dialog,
-                // not just the soft keyboard.  the exception to this is if there are shortcuts
-                // that aren't displayed (e.g are being obscured by the soft keyboard); in that
-                // case we want to dismiss the soft keyboard so the user can see the rest of the
-                // shortcuts.
-                if (isInputMethodNotNeeded() ||
-                        (isEmpty() && getDropDownChildCount() >= getAdapterCount())) {
-                    mSearchDialog.cancel();
-                    return true;
-                }
-                return false; // will dismiss soft keyboard if necessary
             }
             return false;
         }
@@ -1767,11 +1814,18 @@
     }
     
     protected boolean handleBackKey(int keyCode, KeyEvent event) {
-        if (keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN) {
-            if (backToPreviousComponent()) {
+        if (keyCode == KeyEvent.KEYCODE_BACK) {
+            if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                // Consume the event, to get an up at which point we execute.
                 return true;
             }
-            cancel();
+            if (event.getAction() == KeyEvent.ACTION_UP && event.isTracking()
+                    && !event.isCanceled()) {
+                if (backToPreviousComponent(true)) {
+                    return true;
+                }
+                cancel();
+            }
             return true;
         }
         return false;
diff --git a/core/java/android/app/SearchManager.java b/core/java/android/app/SearchManager.java
index 267d86a..3a14f6f 100644
--- a/core/java/android/app/SearchManager.java
+++ b/core/java/android/app/SearchManager.java
@@ -1350,6 +1350,14 @@
          * When the threshold received in {@link #POST_REFRESH_RECEIVE_DISPLAY_NOTIFY} is displayed.
          */
         public final static int THRESH_HIT = 3;
+
+        /**
+         * When a search is started without using a suggestion.
+         */
+        public final static int SEARCH = 4;
+        public final static String SEARCH_SEND_MAX_DISPLAY_POS
+                = "DialogCursorProtocol.SEARCH.sendDisplayPosition";
+        public final static String SEARCH_SEND_QUERY = "DialogCursorProtocol.SEARCH.query";
     }
 
     /**
diff --git a/core/java/android/app/SuggestionsAdapter.java b/core/java/android/app/SuggestionsAdapter.java
index 90f8c50..8f7e8ca 100644
--- a/core/java/android/app/SuggestionsAdapter.java
+++ b/core/java/android/app/SuggestionsAdapter.java
@@ -290,7 +290,7 @@
      */
     void callCursorOnClick(Cursor cursor, int position) {
         if (!mGlobalSearchMode) return;
-        final Bundle request = new Bundle(1);
+        final Bundle request = new Bundle(3);
         request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.CLICK);
         request.putInt(DialogCursorProtocol.CLICK_SEND_POSITION, position);
         request.putInt(DialogCursorProtocol.CLICK_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
@@ -301,6 +301,23 @@
     }
 
     /**
+     * Tell the cursor that a search was started without using a suggestion.
+     *
+     * @param query The search query.
+     */
+    void reportSearch(String query) {
+        if (!mGlobalSearchMode) return;
+        Cursor cursor = getCursor();
+        if (cursor == null) return;
+        final Bundle request = new Bundle(3);
+        request.putInt(DialogCursorProtocol.METHOD, DialogCursorProtocol.SEARCH);
+        request.putString(DialogCursorProtocol.SEARCH_SEND_QUERY, query);
+        request.putInt(DialogCursorProtocol.SEARCH_SEND_MAX_DISPLAY_POS, mMaxDisplayed);
+        // the response is always empty
+        cursor.respond(request);
+    }
+
+    /**
      * Tags the view with cached child view look-ups.
      */
     @Override
@@ -378,7 +395,7 @@
             Drawable.ConstantState cachedBg = mBackgroundsCache.get(backgroundColor);
             if (cachedBg != null) {
                 if (DBG) Log.d(LOG_TAG, "Background cache hit for color " + backgroundColor);
-                return cachedBg.newDrawable();
+                return cachedBg.newDrawable(mProviderContext.getResources());
             }
             if (DBG) Log.d(LOG_TAG, "Creating new background for color " + backgroundColor);
             ColorDrawable transparent = new ColorDrawable(0);
@@ -555,7 +572,7 @@
         Drawable.ConstantState cached = mOutsideDrawablesCache.get(drawableId);
         if (cached != null) {
             if (DBG) Log.d(LOG_TAG, "Found icon in cache: " + drawableId);
-            return cached.newDrawable();
+            return cached.newDrawable(mProviderContext.getResources());
         }
 
         Drawable drawable = null;
@@ -646,7 +663,7 @@
         // Using containsKey() since we also store null values.
         if (mOutsideDrawablesCache.containsKey(componentIconKey)) {
             Drawable.ConstantState cached = mOutsideDrawablesCache.get(componentIconKey);
-            return cached == null ? null : cached.newDrawable();
+            return cached == null ? null : cached.newDrawable(mProviderContext.getResources());
         }
         // Then try the activity or application icon
         Drawable drawable = getActivityIcon(component);
diff --git a/core/java/android/app/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index da40c8a..38cac87 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -22,7 +22,9 @@
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
 import android.graphics.Canvas;
+import android.graphics.ColorFilter;
 import android.graphics.Paint;
+import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.drawable.BitmapDrawable;
 import android.graphics.drawable.Drawable;
@@ -56,9 +58,96 @@
     
     private final Context mContext;
     
+    /**
+     * Special drawable that draws a wallpaper as fast as possible.  Assumes
+     * no scaling or placement off (0,0) of the wallpaper (this should be done
+     * at the time the bitmap is loaded).
+     */
+    static class FastBitmapDrawable extends Drawable {
+        private final Bitmap mBitmap;
+        private final int mWidth;
+        private final int mHeight;
+        private int mDrawLeft;
+        private int mDrawTop;
+
+        private FastBitmapDrawable(Bitmap bitmap) {
+            mBitmap = bitmap;
+            mWidth = bitmap.getWidth();
+            mHeight = bitmap.getHeight();
+            setBounds(0, 0, mWidth, mHeight);
+        }
+
+        @Override
+        public void draw(Canvas canvas) {
+            canvas.drawBitmap(mBitmap, mDrawLeft, mDrawTop, null);
+        }
+
+        @Override
+        public int getOpacity() {
+            return PixelFormat.OPAQUE;
+        }
+
+        @Override
+        public void setBounds(int left, int top, int right, int bottom) {
+            mDrawLeft = left + (right-left - mWidth) / 2;
+            mDrawTop = top + (bottom-top - mHeight) / 2;
+        }
+
+        @Override
+        public void setBounds(Rect bounds) {
+            // TODO Auto-generated method stub
+            super.setBounds(bounds);
+        }
+
+        @Override
+        public void setAlpha(int alpha) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public void setColorFilter(ColorFilter cf) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public void setDither(boolean dither) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public void setFilterBitmap(boolean filter) {
+            throw new UnsupportedOperationException(
+                    "Not supported with this drawable");
+        }
+
+        @Override
+        public int getIntrinsicWidth() {
+            return mWidth;
+        }
+
+        @Override
+        public int getIntrinsicHeight() {
+            return mHeight;
+        }
+
+        @Override
+        public int getMinimumWidth() {
+            return mWidth;
+        }
+
+        @Override
+        public int getMinimumHeight() {
+            return mHeight;
+        }
+    }
+    
     static class Globals extends IWallpaperManagerCallback.Stub {
         private IWallpaperManager mService;
         private Bitmap mWallpaper;
+        private Bitmap mDefaultWallpaper;
         
         private static final int MSG_CLEAR_WALLPAPER = 1;
         
@@ -74,6 +163,7 @@
                         case MSG_CLEAR_WALLPAPER:
                             synchronized (this) {
                                 mWallpaper = null;
+                                mDefaultWallpaper = null;
                             }
                             break;
                     }
@@ -90,12 +180,19 @@
             mHandler.sendEmptyMessage(MSG_CLEAR_WALLPAPER);
         }
         
-        public Bitmap peekWallpaperBitmap(Context context) {
+        public Bitmap peekWallpaperBitmap(Context context, boolean returnDefault) {
             synchronized (this) {
                 if (mWallpaper != null) {
                     return mWallpaper;
                 }
+                if (mDefaultWallpaper != null) {
+                    return mDefaultWallpaper;
+                }
                 mWallpaper = getCurrentWallpaperLocked(context);
+                if (mWallpaper == null && returnDefault) {
+                    mDefaultWallpaper = getDefaultWallpaperLocked(context);
+                    return mDefaultWallpaper;
+                }
                 return mWallpaper;
             }
         }
@@ -134,48 +231,48 @@
                         fd.close();
                     } catch (IOException e) {
                     }
-                    if (bm == null) {
+                    
+                    return generateBitmap(context, bm, width, height);
+                }
+            } catch (RemoteException e) {
+            }
+            return null;
+        }
+        
+        private Bitmap getDefaultWallpaperLocked(Context context) {
+            try {
+                InputStream is = context.getResources().openRawResource(
+                        com.android.internal.R.drawable.default_wallpaper);
+                if (is != null) {
+                    int width = mService.getWidthHint();
+                    int height = mService.getHeightHint();
+                    
+                    if (width <= 0 || height <= 0) {
+                        // Degenerate case: no size requested, just load
+                        // bitmap as-is.
+                        Bitmap bm = BitmapFactory.decodeStream(is, null, null);
+                        try {
+                            is.close();
+                        } catch (IOException e) {
+                        }
+                        if (bm != null) {
+                            bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+                        }
                         return bm;
                     }
-                    bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
                     
-                    // This is the final bitmap we want to return.
-                    Bitmap newbm = Bitmap.createBitmap(width, height,
-                            bm.getConfig());
-                    newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
-                    Canvas c = new Canvas(newbm);
-                    c.setDensity(DisplayMetrics.DENSITY_DEVICE);
-                    Rect targetRect = new Rect();
-                    targetRect.left = targetRect.top = 0;
-                    targetRect.right = bm.getWidth();
-                    targetRect.bottom = bm.getHeight();
-                    
-                    int deltaw = width - targetRect.right;
-                    int deltah = height - targetRect.bottom;
-                    
-                    if (deltaw > 0 || deltah > 0) {
-                        // We need to scale up so it covers the entire
-                        // area.
-                        float scale = 1.0f;
-                        if (deltaw > deltah) {
-                            scale = width / (float)targetRect.right;
-                        } else {
-                            scale = height / (float)targetRect.bottom;
-                        }
-                        targetRect.right = (int)(targetRect.right*scale);
-                        targetRect.bottom = (int)(targetRect.bottom*scale);
-                        deltaw = width - targetRect.right;
-                        deltah = height - targetRect.bottom;
+                    // Load the bitmap with full color depth, to preserve
+                    // quality for later processing.
+                    BitmapFactory.Options options = new BitmapFactory.Options();
+                    options.inDither = false;
+                    options.inPreferredConfig = Bitmap.Config.ARGB_8888;
+                    Bitmap bm = BitmapFactory.decodeStream(is, null, options);
+                    try {
+                        is.close();
+                    } catch (IOException e) {
                     }
                     
-                    targetRect.offset(deltaw/2, deltah/2);
-                    Paint paint = new Paint();
-                    paint.setFilterBitmap(true);
-                    paint.setDither(true);
-                    c.drawBitmap(bm, null, targetRect, paint);
-                    
-                    bm.recycle();
-                    return newbm;
+                    return generateBitmap(context, bm, width, height);
                 }
             } catch (RemoteException e) {
             }
@@ -219,9 +316,13 @@
      * @return Returns a Drawable object that will draw the wallpaper.
      */
     public Drawable getDrawable() {
-        Drawable dr = peekDrawable();
-        return dr != null ? dr : Resources.getSystem().getDrawable(
-                com.android.internal.R.drawable.default_wallpaper);
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
+        if (bm != null) {
+            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
+            dr.setDither(false);
+            return dr;
+        }
+        return null;
     }
 
     /**
@@ -234,8 +335,51 @@
      * null pointer if these is none.
      */
     public Drawable peekDrawable() {
-        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext);
-        return bm != null ? new BitmapDrawable(mContext.getResources(), bm) : null;
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
+        if (bm != null) {
+            Drawable dr = new BitmapDrawable(mContext.getResources(), bm);
+            dr.setDither(false);
+            return dr;
+        }
+        return null;
+    }
+
+    /**
+     * Like {@link #peekFastDrawable}, but always returns a valid Drawable.  If
+     * no wallpaper is set, the system default wallpaper is returned.
+     *
+     * @return Returns a Drawable object that will draw the wallpaper.
+     */
+    public Drawable getFastDrawable() {
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, true);
+        if (bm != null) {
+            Drawable dr = new FastBitmapDrawable(bm);
+            return dr;
+        }
+        return null;
+    }
+
+    /**
+     * Like {@link #peekDrawable()}, but the returned Drawable has a number
+     * of limitations to reduce its overhead as much as possible: it will
+     * never scale the wallpaper (only centering it if the requested bounds
+     * do match the bitmap bounds, which should not be typical), doesn't
+     * allow setting an alpha, color filter, or other attributes, etc.  The
+     * bounds of the returned drawable will be initialized to the same bounds
+     * as the wallpaper, so normally you will not need to touch it.  The
+     * drawable also assumes that it will be used in a context running in
+     * the same density as the screen (not in density compatibility mode).
+     *
+     * @return Returns an optimized Drawable object that will draw the
+     * wallpaper or a null pointer if these is none.
+     */
+    public Drawable peekFastDrawable() {
+        Bitmap bm = sGlobals.peekWallpaperBitmap(mContext, false);
+        if (bm != null) {
+            Drawable dr = new FastBitmapDrawable(bm);
+            return dr;
+        }
+        return null;
     }
 
     /**
@@ -429,8 +573,10 @@
      */
     public void setWallpaperOffsets(IBinder windowToken, float xOffset, float yOffset) {
         try {
+            //Log.v(TAG, "Sending new wallpaper offsets from app...");
             ViewRoot.getWindowSession(mContext.getMainLooper()).setWallpaperPosition(
                     windowToken, xOffset, yOffset);
+            //Log.v(TAG, "...app returning after sending offsets!");
         } catch (RemoteException e) {
             // Ignore.
         }
@@ -466,4 +612,51 @@
     public void clear() throws IOException {
         setResource(com.android.internal.R.drawable.default_wallpaper);
     }
+    
+    static Bitmap generateBitmap(Context context, Bitmap bm, int width, int height) {
+        if (bm == null) {
+            return bm;
+        }
+        bm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        
+        // This is the final bitmap we want to return.
+        // XXX We should get the pixel depth from the system (to match the
+        // physical display depth), when there is a way.
+        Bitmap newbm = Bitmap.createBitmap(width, height,
+                Bitmap.Config.RGB_565);
+        newbm.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        Canvas c = new Canvas(newbm);
+        c.setDensity(DisplayMetrics.DENSITY_DEVICE);
+        Rect targetRect = new Rect();
+        targetRect.left = targetRect.top = 0;
+        targetRect.right = bm.getWidth();
+        targetRect.bottom = bm.getHeight();
+        
+        int deltaw = width - targetRect.right;
+        int deltah = height - targetRect.bottom;
+        
+        if (deltaw > 0 || deltah > 0) {
+            // We need to scale up so it covers the entire
+            // area.
+            float scale = 1.0f;
+            if (deltaw > deltah) {
+                scale = width / (float)targetRect.right;
+            } else {
+                scale = height / (float)targetRect.bottom;
+            }
+            targetRect.right = (int)(targetRect.right*scale);
+            targetRect.bottom = (int)(targetRect.bottom*scale);
+            deltaw = width - targetRect.right;
+            deltah = height - targetRect.bottom;
+        }
+        
+        targetRect.offset(deltaw/2, deltah/2);
+        Paint paint = new Paint();
+        paint.setFilterBitmap(true);
+        paint.setDither(true);
+        c.drawBitmap(bm, null, targetRect, paint);
+        
+        bm.recycle();
+        return newbm;
+    }
 }
diff --git a/core/java/android/content/SyncManager.java b/core/java/android/content/SyncManager.java
index 6d27bc7..1e590f0 100644
--- a/core/java/android/content/SyncManager.java
+++ b/core/java/android/content/SyncManager.java
@@ -87,13 +87,37 @@
     private static final long MILLIS_IN_4WEEKS = MILLIS_IN_WEEK * 4;
 
     /** Delay a sync due to local changes this long. In milliseconds */
-    private static final long LOCAL_SYNC_DELAY = 30 * 1000; // 30 seconds
+    private static final long LOCAL_SYNC_DELAY;
 
     /**
      * If a sync takes longer than this and the sync queue is not empty then we will
      * cancel it and add it back to the end of the sync queue. In milliseconds.
      */
-    private static final long MAX_TIME_PER_SYNC = 5 * 60 * 1000; // 5 minutes
+    private static final long MAX_TIME_PER_SYNC;
+
+    static {
+        String localSyncDelayString = SystemProperties.get("sync.local_sync_delay");
+        long localSyncDelay = 30 * 1000; // 30 seconds
+        if (localSyncDelayString != null) {
+            try {
+                localSyncDelay = Long.parseLong(localSyncDelayString);
+            } catch (NumberFormatException nfe) {
+                // ignore, use default
+            }
+        }
+        LOCAL_SYNC_DELAY = localSyncDelay;
+
+        String maxTimePerSyncString = SystemProperties.get("sync.max_time_per_sync");
+        long maxTimePerSync = 5 * 60 * 1000; // 5 minutes
+        if (maxTimePerSyncString != null) {
+            try {
+                maxTimePerSync = Long.parseLong(maxTimePerSyncString);
+            } catch (NumberFormatException nfe) {
+                // ignore, use default
+            }
+        }
+        MAX_TIME_PER_SYNC = maxTimePerSync;
+    }
 
     private static final long SYNC_NOTIFICATION_DELAY = 30 * 1000; // 30 seconds
 
diff --git a/core/java/android/content/res/Resources.java b/core/java/android/content/res/Resources.java
index ba5c9ed..3796201 100644
--- a/core/java/android/content/res/Resources.java
+++ b/core/java/android/content/res/Resources.java
@@ -22,8 +22,6 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import android.content.pm.ApplicationInfo;
-import android.graphics.BitmapFactory;
 import android.graphics.Movie;
 import android.graphics.drawable.Drawable;
 import android.graphics.drawable.ColorDrawable;
@@ -1664,7 +1662,7 @@
 
         Drawable.ConstantState cs = sPreloadedDrawables.get(key);
         if (cs != null) {
-            dr = cs.newDrawable();
+            dr = cs.newDrawable(this);
         } else {
             if (value.type >= TypedValue.TYPE_FIRST_COLOR_INT &&
                     value.type <= TypedValue.TYPE_LAST_COLOR_INT) {
@@ -1699,7 +1697,7 @@
                 } else {
                     try {
                         InputStream is = mAssets.openNonAsset(
-                                value.assetCookie, file, AssetManager.ACCESS_BUFFER);
+                                value.assetCookie, file, AssetManager.ACCESS_STREAMING);
         //                System.out.println("Opened file " + file + ": " + is);
                         dr = Drawable.createFromResourceStream(this, value, is,
                                 file, null);
@@ -1745,7 +1743,7 @@
                     //Log.i(TAG, "Returning cached drawable @ #" +
                     //        Integer.toHexString(((Integer)key).intValue())
                     //        + " in " + this + ": " + entry);
-                    return entry.newDrawable();
+                    return entry.newDrawable(this);
                 }
                 else {  // our entry has been purged
                     mDrawableCache.delete(key);
diff --git a/core/java/android/inputmethodservice/AbstractInputMethodService.java b/core/java/android/inputmethodservice/AbstractInputMethodService.java
index eedcc35..3619653 100644
--- a/core/java/android/inputmethodservice/AbstractInputMethodService.java
+++ b/core/java/android/inputmethodservice/AbstractInputMethodService.java
@@ -45,6 +45,9 @@
         implements KeyEvent.Callback {
     private InputMethod mInputMethod;
     
+    final KeyEvent.DispatcherState mDispatcherState
+            = new KeyEvent.DispatcherState();
+
     /**
      * Base class for derived classes to implement their {@link InputMethod}
      * interface.  This takes care of basic maintenance of the input method,
@@ -129,7 +132,8 @@
          * callbacks on the service, and tell the client when this is done.
          */
         public void dispatchKeyEvent(int seq, KeyEvent event, EventCallback callback) {
-            boolean handled = event.dispatch(AbstractInputMethodService.this);
+            boolean handled = event.dispatch(AbstractInputMethodService.this,
+                    mDispatcherState, this);
             if (callback != null) {
                 callback.finishedEvent(seq, handled);
             }
@@ -148,6 +152,16 @@
     }
     
     /**
+     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
+     * for used for processing events from the target application.
+     * Normally you will not need to use this directly, but
+     * just use the standard high-level event callbacks like {@link #onKeyDown}.
+     */
+    public KeyEvent.DispatcherState getKeyDispatcherState() {
+        return mDispatcherState;
+    }
+    
+    /**
      * Called by the framework during initialization, when the InputMethod
      * interface for this service needs to be created.
      */
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index 1f640ea..5499bba 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -554,7 +554,7 @@
         mImm = (InputMethodManager)getSystemService(INPUT_METHOD_SERVICE);
         mInflater = (LayoutInflater)getSystemService(
                 Context.LAYOUT_INFLATER_SERVICE);
-        mWindow = new SoftInputWindow(this, mTheme);
+        mWindow = new SoftInputWindow(this, mTheme, mDispatcherState);
         initViews();
         mWindow.getWindow().setLayout(FILL_PARENT, WRAP_CONTENT);
     }
@@ -1557,6 +1557,28 @@
         mImm.showSoftInputFromInputMethod(mToken, flags);
     }
     
+    private boolean handleBack(boolean doIt) {
+        if (mShowInputRequested) {
+            // If the soft input area is shown, back closes it and we
+            // consume the back key.
+            if (doIt) requestHideSelf(0);
+            return true;
+        } else if (mWindowVisible) {
+            if (mCandidatesVisibility == View.VISIBLE) {
+                // If we are showing candidates even if no input area, then
+                // hide them.
+                if (doIt) setCandidatesViewShown(false);
+            } else {
+                // If we have the window visible for some other reason --
+                // most likely to show candidates -- then just get rid
+                // of it.  This really shouldn't happen, but just in case...
+                if (doIt) hideWindow();
+            }
+            return true;
+        }
+        return false;
+    }
+    
     /**
      * Override this to intercept key down events before they are processed by the
      * application.  If you return true, the application will not itself
@@ -1564,38 +1586,33 @@
      * will occur as if the IME had not seen the event at all.
      * 
      * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
-     * KeyEvent.KEYCODE_BACK} to hide the current IME UI if it is shown.  In
-     * additional, in fullscreen mode only, it will consume DPAD movement
+     * KeyEvent.KEYCODE_BACK} if the IME is currently shown, to
+     * possibly hide it when the key goes up (if not canceled or long pressed).  In
+     * addition, in fullscreen mode only, it will consume DPAD movement
      * events to move the cursor in the extracted text view, not allowing
      * them to perform navigation in the underlying application.
      */
     public boolean onKeyDown(int keyCode, KeyEvent event) {
-        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK
-                && event.getRepeatCount() == 0) {
-            if (mShowInputRequested) {
-                // If the soft input area is shown, back closes it and we
-                // consume the back key.
-                requestHideSelf(0);
+        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
+            if (handleBack(false)) {
+                event.startTracking();
                 return true;
-            } else if (mWindowVisible) {
-                if (mCandidatesVisibility == View.VISIBLE) {
-                    // If we are showing candidates even if no input area, then
-                    // hide them.
-                    setCandidatesViewShown(false);
-                    return true;
-                } else {
-                    // If we have the window visible for some other reason --
-                    // most likely to show candidates -- then just get rid
-                    // of it.  This really shouldn't happen, but just in case...
-                    hideWindow();
-                    return true;
-                }
             }
+            return false;
         }
         return doMovementKey(keyCode, event, MOVEMENT_DOWN);
     }
 
     /**
+     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
+     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
+     * the event).
+     */
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    /**
      * Override this to intercept special key multiple events before they are
      * processed by the
      * application.  If you return true, the application will not itself
@@ -1617,12 +1634,18 @@
      * process the event.  If you return true, the normal application processing
      * will occur as if the IME had not seen the event at all.
      * 
-     * <p>The default implementation always returns false, except when
-     * in fullscreen mode, where it will consume DPAD movement
+     * <p>The default implementation intercepts {@link KeyEvent#KEYCODE_BACK
+     * KeyEvent.KEYCODE_BACK} to hide the current IME UI if it is shown.  In
+     * addition, in fullscreen mode only, it will consume DPAD movement
      * events to move the cursor in the extracted text view, not allowing
      * them to perform navigation in the underlying application.
      */
     public boolean onKeyUp(int keyCode, KeyEvent event) {
+        if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.isTracking()
+                && !event.isCanceled()) {
+            return handleBack(true);
+        }
+        
         return doMovementKey(keyCode, event, MOVEMENT_UP);
     }
 
diff --git a/core/java/android/inputmethodservice/SoftInputWindow.java b/core/java/android/inputmethodservice/SoftInputWindow.java
index d91ace6..6a54846 100644
--- a/core/java/android/inputmethodservice/SoftInputWindow.java
+++ b/core/java/android/inputmethodservice/SoftInputWindow.java
@@ -21,6 +21,7 @@
 import android.content.pm.ActivityInfo;
 import android.os.IBinder;
 import android.view.Gravity;
+import android.view.KeyEvent;
 import android.view.WindowManager;
 
 /**
@@ -30,7 +31,8 @@
  * always visible.
  */
 class SoftInputWindow extends Dialog {
-
+    final KeyEvent.DispatcherState mDispatcherState;
+    
     public void setToken(IBinder token) {
         WindowManager.LayoutParams lp = getWindow().getAttributes();
         lp.token = token;
@@ -49,11 +51,19 @@
      *        using styles. This theme is applied on top of the current theme in
      *        <var>context</var>. If 0, the default dialog theme will be used.
      */
-    public SoftInputWindow(Context context, int theme) {
+    public SoftInputWindow(Context context, int theme,
+            KeyEvent.DispatcherState dispatcherState) {
         super(context, theme);
+        mDispatcherState = dispatcherState;
         initDockWindow();
     }
 
+    @Override
+    public void onWindowFocusChanged(boolean hasFocus) {
+        super.onWindowFocusChanged(hasFocus);
+        mDispatcherState.reset();
+    }
+
     /**
      * Get the size of the DockWindow.
      * 
diff --git a/core/java/android/os/HandlerThread.java b/core/java/android/os/HandlerThread.java
index 0ce86db..65301e4 100644
--- a/core/java/android/os/HandlerThread.java
+++ b/core/java/android/os/HandlerThread.java
@@ -64,7 +64,7 @@
     /**
      * This method returns the Looper associated with this thread. If this thread not been started
      * or for any reason is isAlive() returns false, this method will return null. If this thread 
-     * has been started, this method will blocked until the looper has been initialized.  
+     * has been started, this method will block until the looper has been initialized.  
      * @return The looper.
      */
     public Looper getLooper() {
@@ -85,6 +85,21 @@
     }
     
     /**
+     * Ask the currently running looper to quit.  If the thread has not
+     * been started or has finished (that is if {@link #getLooper} returns
+     * null), then false is returned.  Otherwise the looper is asked to
+     * quit and true is returned.
+     */
+    public boolean quit() {
+        Looper looper = getLooper();
+        if (looper != null) {
+            looper.quit();
+            return true;
+        }
+        return false;
+    }
+    
+    /**
      * Returns the identifier of this thread. See Process.myTid().
      */
     public int getThreadId() {
diff --git a/core/java/android/server/BluetoothService.java b/core/java/android/server/BluetoothService.java
index 6ce0f5f..78e2c27 100644
--- a/core/java/android/server/BluetoothService.java
+++ b/core/java/android/server/BluetoothService.java
@@ -399,7 +399,7 @@
         // Electronics, Flaircomm Electronics, Jatty Electronics, Delphi,
         // Clarion, Novero, Denso (Lexus, Toyota), Johnson Controls (Acura),
         // Continental Automotive, Harman/Becker
-        private final ArrayList<String>  mAutoPairingBlacklisted =
+        private final ArrayList<String>  mAutoPairingAddressBlacklist =
                 new ArrayList<String>(Arrays.asList(
                         "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",
@@ -408,6 +408,12 @@
                         "00:0A:30", "00:1E:AE", "00:1C:D7"
                         ));
 
+        // List of names of Bluetooth devices for which auto pairing should be
+        // disabled.
+        private final ArrayList<String> mAutoPairingNameBlacklist =
+                new ArrayList<String>(Arrays.asList(
+                        "Motorola IHF1000", "i.TechBlueBAND", "X5 Stereo v1.3"));
+
         public synchronized void loadBondState() {
             if (mBluetoothState != BluetoothAdapter.STATE_TURNING_ON) {
                 return;
@@ -460,9 +466,16 @@
         }
 
         public boolean isAutoPairingBlacklisted(String address) {
-            for (String blacklistAddress : mAutoPairingBlacklisted) {
+            for (String blacklistAddress : mAutoPairingAddressBlacklist) {
                 if (address.startsWith(blacklistAddress)) return true;
             }
+
+            String name = getRemoteName(address);
+            if (name != null) {
+                for (String blacklistName : mAutoPairingNameBlacklist) {
+                    if (name.equals(blacklistName)) return true;
+                }
+            }
             return false;
         }
 
diff --git a/core/java/android/service/wallpaper/WallpaperService.java b/core/java/android/service/wallpaper/WallpaperService.java
index e5659d5..cd5cf10 100644
--- a/core/java/android/service/wallpaper/WallpaperService.java
+++ b/core/java/android/service/wallpaper/WallpaperService.java
@@ -28,9 +28,11 @@
 import android.content.IntentFilter;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.os.Looper;
 import android.os.Message;
 import android.os.RemoteException;
 import android.util.Log;
+import android.util.LogPrinter;
 import android.view.Gravity;
 import android.view.IWindowSession;
 import android.view.MotionEvent;
@@ -74,6 +76,8 @@
     private static final int MSG_WINDOW_RESIZED = 10030;
     private static final int MSG_TOUCH_EVENT = 10040;
     
+    private Looper mCallbackLooper;
+    
     /**
      * The actual implementation of a wallpaper.  A wallpaper service may
      * have multiple instances running (for example as a real wallpaper
@@ -120,6 +124,7 @@
         boolean mOffsetMessageEnqueued;
         float mPendingXOffset;
         float mPendingYOffset;
+        boolean mPendingSync;
         MotionEvent mPendingMove;
         
         final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@@ -212,10 +217,14 @@
             }
 
             @Override
-            public void dispatchWallpaperOffsets(float x, float y) {
+            public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
                 synchronized (mLock) {
+                    if (DEBUG) Log.v(TAG, "Dispatch wallpaper offsets: " + x + ", " + y);
                     mPendingXOffset = x;
                     mPendingYOffset = y;
+                    if (sync) {
+                        mPendingSync = true;
+                    }
                     if (!mOffsetMessageEnqueued) {
                         mOffsetMessageEnqueued = true;
                         Message msg = mCaller.obtainMessage(MSG_WALLPAPER_OFFSETS);
@@ -551,9 +560,12 @@
             
             float xOffset;
             float yOffset;
+            boolean sync;
             synchronized (mLock) {
                 xOffset = mPendingXOffset;
                 yOffset = mPendingYOffset;
+                sync = mPendingSync;
+                mPendingSync = false;
                 mOffsetMessageEnqueued = false;
             }
             if (DEBUG) Log.v(TAG, "Offsets change in " + this
@@ -563,6 +575,14 @@
             final int availh = mIWallpaperEngine.mReqHeight-mCurHeight;
             final int yPixels = availh > 0 ? -(int)(availh*yOffset+.5f) : 0;
             onOffsetsChanged(xOffset, yOffset, xPixels, yPixels);
+            
+            if (sync) {
+                try {
+                    if (DEBUG) Log.v(TAG, "Reporting offsets change complete");
+                    mSession.wallpaperOffsetsComplete(mWindow.asBinder());
+                } catch (RemoteException e) {
+                }
+            }
         }
         
         void detach() {
@@ -622,7 +642,13 @@
         IWallpaperEngineWrapper(WallpaperService context,
                 IWallpaperConnection conn, IBinder windowToken,
                 int windowType, boolean isPreview, int reqWidth, int reqHeight) {
-            mCaller = new HandlerCaller(context, this);
+            if (DEBUG && mCallbackLooper != null) {
+                mCallbackLooper.setMessageLogging(new LogPrinter(Log.VERBOSE, TAG));
+            }
+            mCaller = new HandlerCaller(context,
+                    mCallbackLooper != null
+                            ? mCallbackLooper : context.getMainLooper(),
+                    this);
             mConnection = conn;
             mWindowToken = windowToken;
             mWindowType = windowType;
@@ -736,5 +762,18 @@
         return new IWallpaperServiceWrapper(this);
     }
     
+    /**
+     * This allows subclasses to change the thread that most callbacks
+     * occur on.  Currently hidden because it is mostly needed for the
+     * image wallpaper (which runs in the system process and doesn't want
+     * to get stuck running on that seriously in use main thread).  Not
+     * exposed right now because the semantics of this are not totally
+     * well defined and some callbacks can still happen on the main thread).
+     * @hide
+     */
+    public void setCallbackLooper(Looper looper) {
+        mCallbackLooper = looper;
+    }
+    
     public abstract Engine onCreateEngine();
 }
diff --git a/core/java/android/text/util/Linkify.java b/core/java/android/text/util/Linkify.java
index d61e888..ce25c47 100644
--- a/core/java/android/text/util/Linkify.java
+++ b/core/java/android/text/util/Linkify.java
@@ -208,7 +208,7 @@
 
         if ((mask & WEB_URLS) != 0) {
             gatherLinks(links, text, Regex.WEB_URL_PATTERN,
-                new String[] { "http://", "https://" },
+                new String[] { "http://", "https://", "rtsp://" },
                 sUrlMatchFilter, null);
         }
 
diff --git a/core/java/android/text/util/Regex.java b/core/java/android/text/util/Regex.java
index a349b82..a6844a4 100644
--- a/core/java/android/text/util/Regex.java
+++ b/core/java/android/text/util/Regex.java
@@ -65,7 +65,7 @@
      */
     public static final Pattern WEB_URL_PATTERN
         = Pattern.compile(
-            "((?:(http|https|Http|Https):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
+            "((?:(http|https|Http|Https|rtsp|Rtsp):\\/\\/(?:(?:[a-zA-Z0-9\\$\\-\\_\\.\\+\\!\\*\\'\\(\\)"
             + "\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,64}(?:\\:(?:[a-zA-Z0-9\\$\\-\\_"
             + "\\.\\+\\!\\*\\'\\(\\)\\,\\;\\?\\&\\=]|(?:\\%[a-fA-F0-9]{2})){1,25})?\\@)?)?"
             + "((?:(?:[a-zA-Z0-9][a-zA-Z0-9\\-]{0,64}\\.)+"   // named host
diff --git a/core/java/android/view/IWindow.aidl b/core/java/android/view/IWindow.aidl
index ebc5f7b..b7953af 100644
--- a/core/java/android/view/IWindow.aidl
+++ b/core/java/android/view/IWindow.aidl
@@ -60,5 +60,5 @@
     /**
      * Called for wallpaper windows when their offsets change.
      */
-    void dispatchWallpaperOffsets(float x, float y);
+    void dispatchWallpaperOffsets(float x, float y, boolean sync);
 }
diff --git a/core/java/android/view/IWindowSession.aidl b/core/java/android/view/IWindowSession.aidl
index 4d662d2..9b8b6d4 100644
--- a/core/java/android/view/IWindowSession.aidl
+++ b/core/java/android/view/IWindowSession.aidl
@@ -114,4 +114,6 @@
      * larger than the screen, set the offset within the screen.
      */
     void setWallpaperPosition(IBinder windowToken, float x, float y);
+    
+    void wallpaperOffsetsComplete(IBinder window);
 }
diff --git a/core/java/android/view/KeyEvent.java b/core/java/android/view/KeyEvent.java
index f9b16fc..daa4b29 100644
--- a/core/java/android/view/KeyEvent.java
+++ b/core/java/android/view/KeyEvent.java
@@ -18,6 +18,7 @@
 
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.util.SparseIntArray;
 import android.view.KeyCharacterMap;
 import android.view.KeyCharacterMap.KeyData;
 
@@ -277,6 +278,32 @@
     public static final int FLAG_VIRTUAL_HARD_KEY = 0x40;
     
     /**
+     * This flag is set for the first key repeat that occurs after the
+     * long press timeout.
+     */
+    public static final int FLAG_LONG_PRESS = 0x80;
+    
+    /**
+     * Set when a key event has {@link #FLAG_CANCELED} set because a long
+     * press action was executed while it was down. 
+     */
+    public static final int FLAG_CANCELED_LONG_PRESS = 0x100;
+    
+    /**
+     * Set for {@link #ACTION_UP} when this event's key code is still being
+     * tracked from its initial down.  That is, somebody requested that tracking
+     * started on the key down and a long press has not caused
+     * the tracking to be canceled.
+     */
+    public static final int FLAG_TRACKING = 0x200;
+    
+    /**
+     * Private control to determine when an app is tracking a key sequence.
+     * @hide
+     */
+    public static final int FLAG_START_TRACKING = 0x40000000;
+    
+    /**
      * Returns the maximum keycode.
      */
     public static int getMaxKeyCode() {
@@ -305,7 +332,11 @@
 
     public interface Callback {
         /**
-         * Called when a key down event has occurred.
+         * Called when a key down event has occurred.  If you return true,
+         * you can first call {@link KeyEvent#startTracking()
+         * KeyEvent.startTracking()} to have the framework track the event
+         * through its {@link #onKeyUp(int, KeyEvent)} and also call your
+         * {@link #onKeyLongPress(int, KeyEvent)} if it occurs.
          * 
          * @param keyCode The value in event.getKeyCode().
          * @param event Description of the key event.
@@ -316,6 +347,22 @@
         boolean onKeyDown(int keyCode, KeyEvent event);
 
         /**
+         * Called when a long press has occurred.  If you return true,
+         * the final key up will have {@link KeyEvent#FLAG_CANCELED} and
+         * {@link KeyEvent#FLAG_CANCELED_LONG_PRESS} set.  Note that in
+         * order to receive this callback, someone in the event change
+         * <em>must</em> return true from {@link #onKeyDown} <em>and</em>
+         * call {@link KeyEvent#startTracking()} on the event.
+         * 
+         * @param keyCode The value in event.getKeyCode().
+         * @param event Description of the key event.
+         * 
+         * @return If you handled the event, return true.  If you want to allow
+         *         the event to be handled by the next receiver, return false.
+         */
+        boolean onKeyLongPress(int keyCode, KeyEvent event);
+
+        /**
          * Called when a key up event has occurred.
          * 
          * @param keyCode The value in event.getKeyCode().
@@ -500,11 +547,15 @@
     /**
      * Copy an existing key event, modifying its time and repeat count.
      * 
+     * @deprecated Use {@link #changeTimeRepeat(KeyEvent, long, int)}
+     * instead.
+     * 
      * @param origEvent The existing event to be copied.
      * @param eventTime The new event time
      * (in {@link android.os.SystemClock#uptimeMillis}) of the event.
      * @param newRepeat The new repeat count of the event.
      */
+    @Deprecated
     public KeyEvent(KeyEvent origEvent, long eventTime, int newRepeat) {
         mDownTime = origEvent.mDownTime;
         mEventTime = eventTime;
@@ -533,6 +584,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.
+     * @param newFlags New flags for the event, replacing the entire value
+     * in the original event.
+     */
+    public static KeyEvent changeTimeRepeat(KeyEvent event, long eventTime,
+            int newRepeat, int newFlags) {
+        KeyEvent ret = new KeyEvent(event);
+        ret.mEventTime = eventTime;
+        ret.mRepeatCount = newRepeat;
+        ret.mFlags = newFlags;
+        return ret;
+    }
+    
+    /**
      * Copy an existing key event, modifying its action.
      * 
      * @param origEvent The existing event to be copied.
@@ -721,6 +792,34 @@
     }
     
     /**
+     * Call this during {@link Callback#onKeyDown} to have the system track
+     * the key through its final up (possibly including a long press).  Note
+     * that only one key can be tracked at a time -- if another key down
+     * event is received while a previous one is being tracked, tracking is
+     * stopped on the previous event.
+     */
+    public final void startTracking() {
+        mFlags |= FLAG_START_TRACKING;
+    }
+    
+    /**
+     * For {@link #ACTION_UP} events, indicates that the event is still being
+     * tracked from its initial down event as per
+     * {@link #FLAG_TRACKING}.
+     */
+    public final boolean isTracking() {
+        return (mFlags&FLAG_TRACKING) != 0;
+    }
+    
+    /**
+     * For {@link #ACTION_DOWN} events, indicates that the event has been
+     * canceled as per {@link #FLAG_LONG_PRESS}.
+     */
+    public final boolean isLongPress() {
+        return (mFlags&FLAG_LONG_PRESS) != 0;
+    }
+    
+    /**
      * Retrieve the key code of the key event.  This is the physical key that
      * was pressed, <em>not</em> the Unicode character.
      * 
@@ -906,19 +1005,49 @@
     }
     
     /**
+     * @deprecated Use {@link #dispatch(Callback, DispatcherState, Object)} instead.
+     */
+    @Deprecated
+    public final boolean dispatch(Callback receiver) {
+        return dispatch(receiver, null, null);
+    }
+    
+    /**
      * Deliver this key event to a {@link Callback} interface.  If this is
      * an ACTION_MULTIPLE event and it is not handled, then an attempt will
      * be made to deliver a single normal event.
      * 
      * @param receiver The Callback that will be given the event.
+     * @param state State information retained across events.
+     * @param target The target of the dispatch, for use in tracking.
      * 
      * @return The return value from the Callback method that was called.
      */
-    public final boolean dispatch(Callback receiver) {
+    public final boolean dispatch(Callback receiver, DispatcherState state,
+            Object target) {
         switch (mAction) {
-            case ACTION_DOWN:
-                return receiver.onKeyDown(mKeyCode, this);
+            case ACTION_DOWN: {
+                mFlags &= ~FLAG_START_TRACKING;
+                boolean res = receiver.onKeyDown(mKeyCode, this);
+                if (state != null) {
+                    if (res && mRepeatCount == 0 && (mFlags&FLAG_START_TRACKING) != 0) {
+                        state.startTracking(this, target);
+                    } else if (isLongPress() && state.isTracking(this)) {
+                        try {
+                            if (receiver.onKeyLongPress(mKeyCode, this)) {
+                                state.performedLongPress(this);
+                                res = true;
+                            }
+                        } catch (AbstractMethodError e) {
+                        }
+                    }
+                }
+                return res;
+            }
             case ACTION_UP:
+                if (state != null) {
+                    state.handleUpEvent(this);
+                }
                 return receiver.onKeyUp(mKeyCode, this);
             case ACTION_MULTIPLE:
                 final int count = mRepeatCount;
@@ -938,10 +1067,97 @@
                     mRepeatCount = count;
                     return handled;
                 }
+                return false;
         }
         return false;
     }
 
+    /**
+     * Use with {@link KeyEvent#dispatch(Callback, DispatcherState, Object)}
+     * for more advanced key dispatching, such as long presses.
+     */
+    public static class DispatcherState {
+        int mDownKeyCode;
+        Object mDownTarget;
+        SparseIntArray mActiveLongPresses = new SparseIntArray();
+        
+        /**
+         * Reset back to initial state.
+         */
+        public void reset() {
+            mDownKeyCode = 0;
+            mDownTarget = null;
+            mActiveLongPresses.clear();
+        }
+        
+        /**
+         * Stop any tracking associated with this target.
+         */
+        public void reset(Object target) {
+            if (mDownTarget == target) {
+                mDownKeyCode = 0;
+                mDownTarget = null;
+            }
+        }
+        
+        /**
+         * Start tracking the key code associated with the given event.  This
+         * can only be called on a key down.  It will allow you to see any
+         * long press associated with the key, and will result in
+         * {@link KeyEvent#isTracking} return true on the long press and up
+         * events.
+         * 
+         * <p>This is only needed if you are directly dispatching events, rather
+         * than handling them in {@link Callback#onKeyDown}.
+         */
+        public void startTracking(KeyEvent event, Object target) {
+            if (event.getAction() != ACTION_DOWN) {
+                throw new IllegalArgumentException(
+                        "Can only start tracking on a down event");
+            }
+            mDownKeyCode = event.getKeyCode();
+            mDownTarget = target;
+        }
+        
+        /**
+         * Return true if the key event is for a key code that is currently
+         * being tracked by the dispatcher.
+         */
+        public boolean isTracking(KeyEvent event) {
+            return mDownKeyCode == event.getKeyCode();
+        }
+        
+        /**
+         * Keep track of the given event's key code as having performed an
+         * action with a long press, so no action should occur on the up.
+         * <p>This is only needed if you are directly dispatching events, rather
+         * than handling them in {@link Callback#onKeyLongPress}.
+         */
+        public void performedLongPress(KeyEvent event) {
+            mActiveLongPresses.put(event.getKeyCode(), 1);
+        }
+        
+        /**
+         * Handle key up event to stop tracking.  This resets the dispatcher state,
+         * and updates the key event state based on it.
+         * <p>This is only needed if you are directly dispatching events, rather
+         * than handling them in {@link Callback#onKeyUp}.
+         */
+        public void handleUpEvent(KeyEvent event) {
+            final int keyCode = event.getKeyCode();
+            int index = mActiveLongPresses.indexOfKey(keyCode);
+            if (index >= 0) {
+                event.mFlags |= FLAG_CANCELED | FLAG_CANCELED_LONG_PRESS;
+                mActiveLongPresses.removeAt(index);
+            }
+            if (mDownKeyCode == keyCode) {
+                event.mFlags |= FLAG_TRACKING;
+                mDownKeyCode = 0;
+                mDownTarget = null;
+            }
+        }
+    }
+    
     public String toString() {
         return "KeyEvent{action=" + mAction + " code=" + mKeyCode
             + " repeat=" + mRepeatCount
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index f63c2f1..6ff0fc8 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -2600,6 +2600,10 @@
         if (mOnFocusChangeListener != null) {
             mOnFocusChangeListener.onFocusChange(this, gainFocus);
         }
+        
+        if (mAttachInfo != null) {
+            mAttachInfo.mKeyDispatchState.reset(this);
+        }
     }
 
     /**
@@ -3609,6 +3613,16 @@
     }
 
     /**
+     * Return the global {@link KeyEvent.DispatcherState KeyEvent.DispatcherState}
+     * for this view's window.  Returns null if the view is not currently attached
+     * to the window.  Normally you will not need to use this directly, but
+     * just use the standard high-level event callbacks like {@link #onKeyDown}.
+     */
+    public KeyEvent.DispatcherState getKeyDispatcherState() {
+        return mAttachInfo != null ? mAttachInfo.mKeyDispatchState : null;
+    }
+    
+    /**
      * Dispatch a key event before it is processed by any input method
      * associated with the view hierarchy.  This can be used to intercept
      * key events in special situations before the IME consumes them; a
@@ -3645,7 +3659,8 @@
             return true;
         }
 
-        return event.dispatch(this);
+        return event.dispatch(this, mAttachInfo != null
+                ? mAttachInfo.mKeyDispatchState : null, this);
     }
 
     /**
@@ -3910,6 +3925,15 @@
     }
 
     /**
+     * Default implementation of {@link KeyEvent.Callback#onKeyLongPress(int, KeyEvent)
+     * KeyEvent.Callback.onKeyLongPress()}: always returns false (doesn't handle
+     * the event).
+     */
+    public boolean onKeyLongPress(int keyCode, KeyEvent event) {
+        return false;
+    }
+
+    /**
      * Default implementation of {@link KeyEvent.Callback#onKeyMultiple(int, int, KeyEvent)
      * KeyEvent.Callback.onKeyMultiple()}: perform clicking of the view
      * when {@link KeyEvent#KEYCODE_DPAD_CENTER} or
@@ -6042,12 +6066,11 @@
         int height = mBottom - mTop;
 
         final AttachInfo attachInfo = mAttachInfo;
-        final float scale = attachInfo.mApplicationScale;
+        final float scale = attachInfo != null ? attachInfo.mApplicationScale : 1.0f;
         width = (int) ((width * scale) + 0.5f);
         height = (int) ((height * scale) + 0.5f);
         
-        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1,
-                height > 0 ? height : 1, quality);
+        Bitmap bitmap = Bitmap.createBitmap(width > 0 ? width : 1, height > 0 ? height : 1, quality);
         if (bitmap == null) {
             throw new OutOfMemoryError();
         }
@@ -8573,6 +8596,9 @@
          */
         final ArrayList<View> mScrollContainers = new ArrayList<View>();
 
+        final KeyEvent.DispatcherState mKeyDispatchState
+                = new KeyEvent.DispatcherState();
+
         /**
          * Indicates whether the view's window currently has the focus.
          */
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index b61465a..c6937a3 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -1812,6 +1812,7 @@
                     if (hasWindowFocus && imm != null && mLastWasImTarget) {
                         imm.startGettingWindowFocus(mView);
                     }
+                    mAttachInfo.mKeyDispatchState.reset();
                     mView.dispatchWindowFocusChanged(hasWindowFocus);
                 }
 
@@ -2868,7 +2869,13 @@
             }
         }
         
-        public void dispatchWallpaperOffsets(float x, float y) {
+        public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
+            if (sync) {
+                try {
+                    sWindowSession.wallpaperOffsetsComplete(asBinder());
+                } catch (RemoteException e) {
+                }
+            }
         }
     }
 
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 8446475..2329e21 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -458,8 +458,7 @@
     private static final int SWITCH_TO_LONGPRESS        = 4;
     private static final int RELEASE_SINGLE_TAP         = 5;
     private static final int REQUEST_FORM_DATA          = 6;
-    private static final int SWITCH_TO_CLICK            = 7;
-    private static final int RESUME_WEBCORE_UPDATE      = 8;
+    private static final int RESUME_WEBCORE_UPDATE      = 7;
 
     //! arg1=x, arg2=y
     static final int SCROLL_TO_MSG_ID                   = 10;
@@ -1395,6 +1394,7 @@
      * Reload the current url.
      */
     public void reload() {
+        clearTextEntry();
         switchOutDrawHistory();
         mWebViewCore.sendMessage(EventHub.RELOAD);
     }
@@ -2049,12 +2049,9 @@
     protected int computeHorizontalScrollRange() {
         if (mDrawHistory) {
             return mHistoryWidth;
-        } else if (mLastWidthSent == mContentWidth) {
-            // special case to avoid rounding error. Otherwise we may get a
-            // faked scrollbar sometimes.
-            return getViewWidth();
         } else {
-            return contentToViewDimension(mContentWidth);
+            // to avoid rounding error caused unnecessary scrollbar, use floor
+            return (int) Math.floor(mContentWidth * mActualScale);
         }
     }
 
@@ -2066,18 +2063,8 @@
         if (mDrawHistory) {
             return mHistoryHeight;
         } else {
-            int height;
-            // special case to avoid rounding error. Otherwise we may get a
-            // faked scrollbar sometimes.
-            if (mLastHeightSent == mContentHeight) {
-                height = getViewHeight();
-            } else {
-                height = contentToViewDimension(mContentHeight);
-            }
-            if (mFindIsUp) {
-                height += FIND_HEIGHT;
-            }
-            return height;
+            // to avoid rounding error caused unnecessary scrollbar, use floor
+            return (int) Math.floor(mContentHeight * mActualScale);
         }
     }
 
@@ -3677,16 +3664,27 @@
             if (mShiftIsPressed) {
                 return false;
             }
-            if (getSettings().supportZoom()
-                    && mTouchMode == TOUCH_DOUBLECLICK_MODE) {
-                zoomScrollOut();
-            } else {
-                mPrivateHandler.sendMessageDelayed(mPrivateHandler
-                        .obtainMessage(SWITCH_TO_CLICK), TAP_TIMEOUT);
-                if (DebugFlags.WEB_VIEW) {
-                    Log.v(LOGTAG, "TOUCH_DOUBLECLICK_MODE");
-                }
-                mTouchMode = TOUCH_DOUBLECLICK_MODE;
+
+            // perform the single click
+            Rect visibleRect = sendOurVisibleRect();
+            // Note that sendOurVisibleRect calls viewToContent, so the
+            // coordinates should be in content coordinates.
+            if (!nativeCursorIntersects(visibleRect)) {
+                return false;
+            }
+            nativeSetFollowedLink(true);
+            nativeUpdatePluginReceivesEvents();
+            WebViewCore.CursorData data = cursorData();
+            mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
+            playSoundEffect(SoundEffectConstants.CLICK);
+            boolean isTextInput = nativeCursorIsTextInput();
+            if (isTextInput || !mCallbackProxy.uiOverrideUrlLoading(
+                        nativeCursorText())) {
+                mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
+                        nativeCursorNodePointer());
+            }
+            if (isTextInput) {
+                rebuildWebTextView();
             }
             return true;
         }
@@ -4334,7 +4332,6 @@
             return true;
         }
         if (ev.getAction() == MotionEvent.ACTION_DOWN) {
-            mPrivateHandler.removeMessages(SWITCH_TO_CLICK);
             mTrackballDown = true;
             if (mNativeClass == 0) {
                 return false;
@@ -4582,9 +4579,8 @@
     }
 
     private int computeMaxScrollY() {
-        int maxContentH = contentToViewDimension(mContentHeight)
-                          + getTitleHeight();
-        return Math.max(maxContentH - getHeight(), 0);
+        int maxContentH = computeVerticalScrollRange() + getTitleHeight();
+        return Math.max(maxContentH - getHeight(), getTitleHeight());
     }
 
     public void flingScroll(int vx, int vy) {
@@ -4890,6 +4886,9 @@
         }
         int x = viewToContentX((int) event.getX() + mWebTextView.getLeft());
         int y = viewToContentY((int) event.getY() + mWebTextView.getTop());
+        // In case the soft keyboard has been dismissed, bring it back up.
+        InputMethodManager.getInstance(getContext()).showSoftInput(mWebTextView,
+                0);
         nativeTextInputMotionUp(x, y);
     }
 
@@ -5023,8 +5022,8 @@
         int measuredWidth = widthSize;
 
         // Grab the content size from WebViewCore.
-        int contentHeight = Math.round(mContentHeight * mActualScale);
-        int contentWidth = Math.round(mContentWidth * mActualScale);
+        int contentHeight = contentToViewDimension(mContentHeight);
+        int contentWidth = contentToViewDimension(mContentWidth);
 
 //        Log.d(LOGTAG, "------- measure " + heightMode);
 
@@ -5198,32 +5197,6 @@
                     }
                     break;
                 }
-                case SWITCH_TO_CLICK:
-                    // The user clicked with the trackball, and did not click a
-                    // second time, so perform the action of a trackball single
-                    // click
-                    mTouchMode = TOUCH_DONE_MODE;
-                    Rect visibleRect = sendOurVisibleRect();
-                    // Note that sendOurVisibleRect calls viewToContent, so the
-                    // coordinates should be in content coordinates.
-                    if (!nativeCursorIntersects(visibleRect)) {
-                        break;
-                    }
-                    nativeSetFollowedLink(true);
-                    nativeUpdatePluginReceivesEvents();
-                    WebViewCore.CursorData data = cursorData();
-                    mWebViewCore.sendMessage(EventHub.SET_MOVE_MOUSE, data);
-                    playSoundEffect(SoundEffectConstants.CLICK);
-                    boolean isTextInput = nativeCursorIsTextInput();
-                    if (isTextInput || !mCallbackProxy.uiOverrideUrlLoading(
-                                nativeCursorText())) {
-                        mWebViewCore.sendMessage(EventHub.CLICK, data.mFrame,
-                                nativeCursorNodePointer());
-                    }
-                    if (isTextInput) {
-                        rebuildWebTextView();
-                    }
-                    break;
                 case SCROLL_BY_MSG_ID:
                     setContentScrollBy(msg.arg1, msg.arg2, (Boolean) msg.obj);
                     break;
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 4e76254..6e10811 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -39,7 +39,7 @@
     // log tag
     protected static final String LOGTAG = "webviewdatabase";
 
-    private static final int DATABASE_VERSION = 9;
+    private static final int DATABASE_VERSION = 10;
     // 2 -> 3 Modified Cache table to allow cache of redirects
     // 3 -> 4 Added Oma-Downloads table
     // 4 -> 5 Modified Cache table to support persistent contentLength
@@ -48,6 +48,7 @@
     // 6 -> 7 Change cache localPath from int to String
     // 7 -> 8 Move cache to its own db
     // 8 -> 9 Store both scheme and host when storing passwords
+    // 9 -> 10 Update httpauth table UNIQUE
     private static final int CACHE_DATABASE_VERSION = 3;
     // 1 -> 2 Add expires String
     // 2 -> 3 Add content-disposition
@@ -256,6 +257,20 @@
                     + DATABASE_VERSION + ", which will destroy old data");
         }
         boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
+        boolean justAuth = 9 == oldVersion && 10 == DATABASE_VERSION;
+        if (justAuth) {
+            mDatabase.execSQL("DROP TABLE IF EXISTS "
+                    + mTableNames[TABLE_HTTPAUTH_ID]);
+            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
+                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+                    + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+                    + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+                    + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
+                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+                    + ") ON CONFLICT REPLACE);");
+            return;
+        }
+
         if (!justPasswords) {
             mDatabase.execSQL("DROP TABLE IF EXISTS "
                     + mTableNames[TABLE_COOKIES_ID]);
@@ -302,8 +317,8 @@
                     + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
                     + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
                     + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
-                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL + ", "
-                    + HTTPAUTH_USERNAME_COL + ") ON CONFLICT REPLACE);");
+                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+                    + ") ON CONFLICT REPLACE);");
         }
         // passwords
         mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 2f292d5..bed2a7a 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -2945,10 +2945,14 @@
             okToSend = false;
             break;
         case KeyEvent.KEYCODE_BACK:
-            if (mFiltered && mPopup != null && mPopup.isShowing() &&
-                    event.getAction() == KeyEvent.ACTION_DOWN) {
-                handled = true;
-                mTextFilter.setText("");
+            if (mFiltered && mPopup != null && mPopup.isShowing()) {
+                if (event.getAction() == KeyEvent.ACTION_DOWN) {
+                    handled = true;
+                } else if (event.getAction() == KeyEvent.ACTION_UP
+                        && event.isTracking() && !event.isCanceled()) {
+                    handled = true;
+                    mTextFilter.setText("");
+                }
             }
             okToSend = false;
             break;
diff --git a/core/java/android/widget/AutoCompleteTextView.java b/core/java/android/widget/AutoCompleteTextView.java
index d821a7d..7891d3c 100644
--- a/core/java/android/widget/AutoCompleteTextView.java
+++ b/core/java/android/widget/AutoCompleteTextView.java
@@ -132,6 +132,8 @@
 
     private AutoCompleteTextView.PassThroughClickListener mPassThroughClickListener;
 
+    private int mDownKeyCode;
+    
     public AutoCompleteTextView(Context context) {
         this(context, null);
     }
@@ -603,12 +605,19 @@
 
     @Override
     public boolean onKeyPreIme(int keyCode, KeyEvent event) {
+        if (event.getAction() == KeyEvent.ACTION_DOWN
+                && event.getRepeatCount() == 0) {
+            mDownKeyCode = keyCode;
+        }
         if (isPopupShowing()) {
             // special case for the back key, we do not even try to send it
             // to the drop down list but instead, consume it immediately
             if (keyCode == KeyEvent.KEYCODE_BACK && !mDropDownAlwaysVisible) {
-                dismissDropDown();
-                return true;
+                if (event.getAction() == KeyEvent.ACTION_UP
+                        && mDownKeyCode == keyCode && !event.isCanceled()) {
+                    dismissDropDown();
+                    return true;
+                }
             }
         }
         return super.onKeyPreIme(keyCode, event);
@@ -1017,6 +1026,7 @@
     @Override
     public void onWindowFocusChanged(boolean hasWindowFocus) {
         super.onWindowFocusChanged(hasWindowFocus);
+        mDownKeyCode = 0;
         performValidation();
         if (!hasWindowFocus && !mDropDownAlwaysVisible) {
             dismissDropDown();
@@ -1026,6 +1036,7 @@
     @Override
     protected void onFocusChanged(boolean focused, int direction, Rect previouslyFocusedRect) {
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
+        mDownKeyCode = 0;
         performValidation();
         if (!focused && !mDropDownAlwaysVisible) {
             dismissDropDown();
diff --git a/core/java/android/widget/Gallery.java b/core/java/android/widget/Gallery.java
index e7b303a..f34823c 100644
--- a/core/java/android/widget/Gallery.java
+++ b/core/java/android/widget/Gallery.java
@@ -23,7 +23,6 @@
 import android.content.res.TypedArray;
 import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Config;
 import android.util.Log;
 import android.view.GestureDetector;
 import android.view.Gravity;
@@ -36,8 +35,6 @@
 import android.view.SoundEffectConstants;
 import android.view.ContextMenu.ContextMenuInfo;
 import android.view.animation.Transformation;
-import android.widget.AbsSpinner;
-import android.widget.Scroller;
 
 /**
  * A view that shows items in a center-locked, horizontally scrolling list.
@@ -59,7 +56,7 @@
 
     private static final String TAG = "Gallery";
 
-    private static final boolean localLOGV = Config.LOGV;
+    private static final boolean localLOGV = false;
 
     /**
      * Duration in milliseconds from the start of a scroll during which we're
@@ -514,6 +511,7 @@
             // We haven't been callbacking during the fling, so do it now
             super.selectionChanged();
         }
+        invalidate();
     }
     
     @Override
@@ -534,12 +532,9 @@
         
         int galleryCenter = getCenterOfGallery();
         
-        if (selView != null) {
-
-            // Common case where the current selected position is correct
-            if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
-                return;
-            }
+        // Common case where the current selected position is correct
+        if (selView.getLeft() <= galleryCenter && selView.getRight() >= galleryCenter) {
+            return;
         }
         
         // TODO better search
@@ -627,7 +622,6 @@
         View sel = makeAndAddView(mSelectedPosition, 0, 0, true);
         
         // Put the selected child in the center
-        Gallery.LayoutParams lp = (Gallery.LayoutParams) sel.getLayoutParams();
         int selectedOffset = childrenLeft + (childrenWidth / 2) - (sel.getWidth() / 2);
         sel.offsetLeftAndRight(selectedOffset);
 
@@ -733,9 +727,6 @@
             child = mRecycler.get(position);
             if (child != null) {
                 // Can reuse an existing view
-                Gallery.LayoutParams lp = (Gallery.LayoutParams) 
-                    child.getLayoutParams();
-
                 int childLeft = child.getLeft();
                 
                 // Remember left and right edges of where views have been placed
@@ -798,7 +789,7 @@
         int childRight;
 
         // Position vertically based on gravity setting
-        int childTop = calculateTop(child, lp, true);
+        int childTop = calculateTop(child, true);
         int childBottom = childTop + child.getMeasuredHeight();
 
         int width = child.getMeasuredWidth();
@@ -817,11 +808,9 @@
      * Figure out vertical placement based on mGravity
      * 
      * @param child Child to place
-     * @param lp LayoutParams for this view (just so we don't keep looking them
-     *        up)
      * @return Where the top of the child should be
      */
-    private int calculateTop(View child, Gallery.LayoutParams lp, boolean duringLayout) {
+    private int calculateTop(View child, boolean duringLayout) {
         int myHeight = duringLayout ? mMeasuredHeight : getHeight();
         int childHeight = duringLayout ? child.getMeasuredHeight() : child.getHeight(); 
         
diff --git a/core/java/com/android/internal/os/HandlerCaller.java b/core/java/com/android/internal/os/HandlerCaller.java
index 5825024..35b9251 100644
--- a/core/java/com/android/internal/os/HandlerCaller.java
+++ b/core/java/com/android/internal/os/HandlerCaller.java
@@ -57,6 +57,13 @@
         mCallback = callback;
     }
 
+    public HandlerCaller(Context context, Looper looper, Callback callback) {
+        mContext = context;
+        mMainLooper = looper;
+        mH = new MyHandler(mMainLooper);
+        mCallback = callback;
+    }
+
     public SomeArgs obtainArgs() {
         synchronized (mH) {
             SomeArgs args = mArgsPool;
diff --git a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
index 5357469..0bc70de 100644
--- a/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
+++ b/core/java/com/android/internal/service/wallpaper/ImageWallpaper.java
@@ -20,6 +20,8 @@
 import android.graphics.Canvas;
 import android.graphics.Rect;
 import android.graphics.drawable.Drawable;
+import android.os.HandlerThread;
+import android.os.Process;
 import android.service.wallpaper.WallpaperService;
 import android.view.MotionEvent;
 import android.view.SurfaceHolder;
@@ -33,20 +35,29 @@
  */
 public class ImageWallpaper extends WallpaperService {
     WallpaperManager mWallpaperManager;
+    private HandlerThread mThread;
 
     @Override
     public void onCreate() {
         super.onCreate();
         mWallpaperManager = (WallpaperManager) getSystemService(WALLPAPER_SERVICE);
+        mThread = new HandlerThread("Wallpaper", Process.THREAD_PRIORITY_FOREGROUND);
+        mThread.start();
+        setCallbackLooper(mThread.getLooper());
     }
 
     public Engine onCreateEngine() {
         return new DrawableEngine();
     }
 
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        mThread.quit();
+    }
+
     class DrawableEngine extends Engine {
         private final Object mLock = new Object();
-        private final Rect mBounds = new Rect();
         private WallpaperObserver mReceiver;
         Drawable mBackground;
         float mXOffset;
@@ -56,6 +67,9 @@
             public void onReceive(Context context, Intent intent) {
                 updateWallpaper();
                 drawFrame();
+                // Assume we are the only one using the wallpaper in this
+                // process, and force a GC now to release the old wallpaper.
+                System.gc();
             }
         }
 
@@ -67,7 +81,6 @@
             registerReceiver(mReceiver, filter);
             updateWallpaper();
             surfaceHolder.setSizeFromLayout();
-            //setTouchEventsEnabled(true);
         }
 
         @Override
@@ -137,11 +150,7 @@
 
         void updateWallpaper() {
             synchronized (mLock) {
-                mBackground = mWallpaperManager.getDrawable();
-                mBounds.left = mBounds.top = 0;
-                mBounds.right = mBackground.getIntrinsicWidth();
-                mBounds.bottom = mBackground.getIntrinsicHeight();
-                mBackground.setBounds(mBounds);
+                mBackground = mWallpaperManager.getFastDrawable();
             }
         }
     }
diff --git a/core/java/com/android/internal/view/BaseIWindow.java b/core/java/com/android/internal/view/BaseIWindow.java
index f4f6297..b8d19ac 100644
--- a/core/java/com/android/internal/view/BaseIWindow.java
+++ b/core/java/com/android/internal/view/BaseIWindow.java
@@ -90,6 +90,12 @@
     public void executeCommand(String command, String parameters, ParcelFileDescriptor out) {
     }
     
-    public void dispatchWallpaperOffsets(float x, float y) {
+    public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
+        if (sync) {
+            try {
+                mSession.wallpaperOffsetsComplete(asBinder());
+            } catch (RemoteException e) {
+            }
+        }
     }
 }
diff --git a/core/java/com/android/internal/view/menu/IconMenuView.java b/core/java/com/android/internal/view/menu/IconMenuView.java
index b81c2b3..bba2ee2 100644
--- a/core/java/com/android/internal/view/menu/IconMenuView.java
+++ b/core/java/com/android/internal/view/menu/IconMenuView.java
@@ -282,7 +282,9 @@
         itemView.setIconMenuView(this);
         
         // Apply the background to the item view
-        itemView.setBackgroundDrawable(mItemBackground.getConstantState().newDrawable());
+        itemView.setBackgroundDrawable(
+                mItemBackground.getConstantState().newDrawable(
+                        getContext().getResources()));
 
         // This class is the invoker for all its item views 
         itemView.setItemInvoker(this);
diff --git a/core/jni/android_util_Process.cpp b/core/jni/android_util_Process.cpp
index 7748aba..5b6c7ea 100644
--- a/core/jni/android_util_Process.cpp
+++ b/core/jni/android_util_Process.cpp
@@ -32,6 +32,7 @@
 #include <sys/errno.h>
 #include <sys/resource.h>
 #include <sys/types.h>
+#include <cutils/sched_policy.h>
 #include <dirent.h>
 #include <fcntl.h>
 #include <grp.h>
@@ -186,58 +187,6 @@
     return -1;
 }
 
-static int add_pid_to_cgroup(int pid, const char *grp_name)
-{
-    int fd;
-    char path[255];
-    char text[64];
-
-    sprintf(path, "/dev/cpuctl/%s/tasks", grp_name);
-
-    if ((fd = open(path, O_WRONLY)) < 0)
-        return -1;
-
-    sprintf(text, "%d", pid);
-    if (write(fd, text, strlen(text)) < 0) {
-        close(fd);
-        return -1;
-    }
-
-    close(fd);
-    return 0;
-}
-
-void setSchedPolicy(JNIEnv* env, jobject clazz, int pid, SchedPolicy policy)
-{
-    static int __sys_supports_schedgroups = -1;
-
-    if (__sys_supports_schedgroups < 0) {
-        if (!access("/dev/cpuctl/tasks", F_OK)) {
-            __sys_supports_schedgroups = 1;
-        } else {
-            __sys_supports_schedgroups = 0;
-        }
-    }
-
-    if (__sys_supports_schedgroups) {
-        const char *grp = NULL;
-
-        if (policy == SP_BACKGROUND) {
-            grp = "bg_non_interactive";
-        }
-
-        if (add_pid_to_cgroup(pid, grp)) {
-            if (errno != ESRCH && errno != ENOENT)
-                signalExceptionForGroupError(env, clazz, errno);
-        }
-    } else {
-        struct sched_param param;
-
-        param.sched_priority = 0;
-        sched_setscheduler(pid, (policy == SP_BACKGROUND) ? 5 : 0, &param);
-    }
-}
-
 void android_os_Process_setThreadGroup(JNIEnv* env, jobject clazz, int pid, jint grp)
 {
     if (grp > ANDROID_TGROUP_MAX || grp < 0) { 
@@ -245,9 +194,10 @@
         return;
     }
 
-    setSchedPolicy(env, clazz, pid,
-                   (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
-                           SP_BACKGROUND : SP_FOREGROUND);
+    if (set_sched_policy(pid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                                      SP_BACKGROUND : SP_FOREGROUND)) {
+        signalExceptionForGroupError(env, clazz, errno);
+    }
 }
 
 void android_os_Process_setProcessGroup(JNIEnv* env, jobject clazz, int pid, jint grp) 
@@ -291,9 +241,10 @@
             continue;
         }
      
-        setSchedPolicy(env, clazz, t_pid,
-                       (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
-                               SP_BACKGROUND : SP_FOREGROUND);
+        if (set_sched_policy(t_pid, (grp == ANDROID_TGROUP_BG_NONINTERACT) ?
+                                            SP_BACKGROUND : SP_FOREGROUND)) {
+            signalExceptionForGroupError(env, clazz, errno);
+        }
     }
     closedir(d);
 }
@@ -301,10 +252,16 @@
 void android_os_Process_setThreadPriority(JNIEnv* env, jobject clazz,
                                               jint pid, jint pri)
 {
+    int rc = 0;
+
     if (pri >= ANDROID_PRIORITY_BACKGROUND) {
-        setSchedPolicy(env, clazz, pid, SP_BACKGROUND);
+        rc = set_sched_policy(pid, SP_BACKGROUND);
     } else if (getpriority(PRIO_PROCESS, pid) >= ANDROID_PRIORITY_BACKGROUND) {
-        setSchedPolicy(env, clazz, pid, SP_FOREGROUND);
+        rc = set_sched_policy(pid, SP_FOREGROUND);
+    }
+
+    if (rc) {
+        signalExceptionForGroupError(env, clazz, errno);
     }
 
     if (setpriority(PRIO_PROCESS, pid, pri) < 0) {
diff --git a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
index ac96f20..58206d4 100644
--- a/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimatedRotateDrawable.java
@@ -45,11 +45,11 @@
     private boolean mRunning;
 
     public AnimatedRotateDrawable() {
-        this(null);
+        this(null, null);
     }
 
-    private AnimatedRotateDrawable(AnimatedRotateState rotateState) {
-        mState = new AnimatedRotateState(rotateState, this);
+    private AnimatedRotateDrawable(AnimatedRotateState rotateState, Resources res) {
+        mState = new AnimatedRotateState(rotateState, this, res);
         init();
     }
 
@@ -296,9 +296,14 @@
         private boolean mCanConstantState;
         private boolean mCheckedConstantState;        
 
-        public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner) {
+        public AnimatedRotateState(AnimatedRotateState source, AnimatedRotateDrawable owner,
+                Resources res) {
             if (source != null) {
-                mDrawable = source.mDrawable.getConstantState().newDrawable();
+                if (res != null) {
+                    mDrawable = source.mDrawable.getConstantState().newDrawable(res);
+                } else {
+                    mDrawable = source.mDrawable.getConstantState().newDrawable();
+                }
                 mDrawable.setCallback(owner);
                 mPivotXRel = source.mPivotXRel;
                 mPivotX = source.mPivotX;
@@ -312,7 +317,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new AnimatedRotateDrawable(this);
+            return new AnimatedRotateDrawable(this, null);
+        }
+        
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new AnimatedRotateDrawable(this, res);
         }
         
         @Override
diff --git a/graphics/java/android/graphics/drawable/AnimationDrawable.java b/graphics/java/android/graphics/drawable/AnimationDrawable.java
index 68718c9..fdc4c92 100644
--- a/graphics/java/android/graphics/drawable/AnimationDrawable.java
+++ b/graphics/java/android/graphics/drawable/AnimationDrawable.java
@@ -77,7 +77,7 @@
     private boolean mMutated;
 
     public AnimationDrawable() {
-        this(null);
+        this(null, null);
     }
 
     @Override
@@ -297,8 +297,9 @@
         private int[] mDurations;
         private boolean mOneShot;
 
-        AnimationState(AnimationState orig, AnimationDrawable owner) {
-            super(orig, owner);
+        AnimationState(AnimationState orig, AnimationDrawable owner,
+                Resources res) {
+            super(orig, owner, res);
 
             if (orig != null) {
                 mDurations = orig.mDurations;
@@ -311,7 +312,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new AnimationDrawable(this);
+            return new AnimationDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new AnimationDrawable(this, res);
         }
 
         public void addFrame(Drawable dr, int dur) {
@@ -330,8 +336,8 @@
         }
     }
 
-    private AnimationDrawable(AnimationState state) {
-        AnimationState as = new AnimationState(state, this);
+    private AnimationDrawable(AnimationState state, Resources res) {
+        AnimationState as = new AnimationState(state, this, res);
         mAnimationState = as;
         setConstantState(as);
         if (state != null) {
diff --git a/graphics/java/android/graphics/drawable/BitmapDrawable.java b/graphics/java/android/graphics/drawable/BitmapDrawable.java
index 30cef67..e82f297 100644
--- a/graphics/java/android/graphics/drawable/BitmapDrawable.java
+++ b/graphics/java/android/graphics/drawable/BitmapDrawable.java
@@ -60,15 +60,15 @@
             Paint.FILTER_BITMAP_FLAG | Paint.DITHER_FLAG;
     private BitmapState mBitmapState;
     private Bitmap mBitmap;
+    private int mTargetDensity;
+
     private final Rect mDstRect = new Rect();   // Gravity.apply() sets this
 
     private boolean mApplyGravity;
     private boolean mRebuildShader;
     private boolean mMutated;
     
-    private int mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
-
-    // These are scaled to match the target density.
+     // These are scaled to match the target density.
     private int mBitmapWidth;
     private int mBitmapHeight;
     
@@ -88,10 +88,7 @@
      */
     public BitmapDrawable(Resources res) {
         mBitmapState = new BitmapState((Bitmap) null);
-        if (res != null) {
-            setTargetDensity(res.getDisplayMetrics());
-            mBitmapState.mTargetDensity = mTargetDensity;
-        }
+        mBitmapState.mTargetDensity = mTargetDensity;
     }
 
     /**
@@ -101,7 +98,7 @@
      */
     @Deprecated
     public BitmapDrawable(Bitmap bitmap) {
-        this(new BitmapState(bitmap));
+        this(new BitmapState(bitmap), null);
     }
 
     /**
@@ -109,22 +106,51 @@
      * the display metrics of the resources.
      */
     public BitmapDrawable(Resources res, Bitmap bitmap) {
-        this(new BitmapState(bitmap));
-        if (res != null) {
-            setTargetDensity(res.getDisplayMetrics());
-            mBitmapState.mTargetDensity = mTargetDensity;
-        }
+        this(new BitmapState(bitmap), res);
+        mBitmapState.mTargetDensity = mTargetDensity;
     }
 
+    /**
+     * Create a drawable by opening a given file path and decoding the bitmap.
+     * @deprecated Use {@link #BitmapDrawable(Resources, String)} to ensure
+     * that the drawable has correctly set its target density.
+     */
     public BitmapDrawable(String filepath) {
-        this(new BitmapState(BitmapFactory.decodeFile(filepath)));
+        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
         if (mBitmap == null) {
             android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
         }
     }
 
+    /**
+     * Create a drawable by opening a given file path and decoding the bitmap.
+     */
+    public BitmapDrawable(Resources res, String filepath) {
+        this(new BitmapState(BitmapFactory.decodeFile(filepath)), null);
+        mBitmapState.mTargetDensity = mTargetDensity;
+        if (mBitmap == null) {
+            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + filepath);
+        }
+    }
+
+    /**
+     * Create a drawable by decoding a bitmap from the given input stream.
+     * @deprecated Use {@link #BitmapDrawable(Resources, java.io.InputStream)} to ensure
+     * that the drawable has correctly set its target density.
+     */
     public BitmapDrawable(java.io.InputStream is) {
-        this(new BitmapState(BitmapFactory.decodeStream(is)));
+        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
+        if (mBitmap == null) {
+            android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
+        }
+    }
+
+    /**
+     * Create a drawable by decoding a bitmap from the given input stream.
+     */
+    public BitmapDrawable(Resources res, java.io.InputStream is) {
+        this(new BitmapState(BitmapFactory.decodeStream(is)), null);
+        mBitmapState.mTargetDensity = mTargetDensity;
         if (mBitmap == null) {
             android.util.Log.w("BitmapDrawable", "BitmapDrawable cannot decode " + is);
         }
@@ -425,7 +451,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new BitmapDrawable(this);
+            return new BitmapDrawable(this, null);
+        }
+        
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new BitmapDrawable(this, res);
         }
         
         @Override
@@ -434,9 +465,15 @@
         }
     }
 
-    private BitmapDrawable(BitmapState state) {
+    private BitmapDrawable(BitmapState state, Resources res) {
         mBitmapState = state;
-        mTargetDensity = state.mTargetDensity;
+        if (res != null) {
+            mTargetDensity = res.getDisplayMetrics().densityDpi;
+        } else if (state != null) {
+            mTargetDensity = state.mTargetDensity;
+        } else {
+            mTargetDensity = DisplayMetrics.DENSITY_DEFAULT;
+        }
         setBitmap(state.mBitmap);
     }
 }
diff --git a/graphics/java/android/graphics/drawable/ClipDrawable.java b/graphics/java/android/graphics/drawable/ClipDrawable.java
index 95d4dd0..c387a9b 100644
--- a/graphics/java/android/graphics/drawable/ClipDrawable.java
+++ b/graphics/java/android/graphics/drawable/ClipDrawable.java
@@ -48,14 +48,14 @@
     public static final int VERTICAL = 2;
     
     ClipDrawable() {
-        this(null);
+        this(null, null);
     }
 
     /**
      * @param orientation Bitwise-or of {@link #HORIZONTAL} and/or {@link #VERTICAL}
      */
     public ClipDrawable(Drawable drawable, int gravity, int orientation) {
-        this(null);
+        this(null, null);
 
         mClipState.mDrawable = drawable;
         mClipState.mGravity = gravity;
@@ -241,9 +241,13 @@
         private boolean mCheckedConstantState;
         private boolean mCanConstantState;
 
-        ClipState(ClipState orig, ClipDrawable owner) {
+        ClipState(ClipState orig, ClipDrawable owner, Resources res) {
             if (orig != null) {
-                mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                if (res != null) {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
+                } else {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                }
                 mDrawable.setCallback(owner);
                 mOrientation = orig.mOrientation;
                 mGravity = orig.mGravity;
@@ -253,7 +257,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new ClipDrawable(this);
+            return new ClipDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new ClipDrawable(this, res);
         }
 
         @Override
@@ -271,8 +280,8 @@
         }
     }
 
-    private ClipDrawable(ClipState state) {
-        mClipState = new ClipState(state, this);
+    private ClipDrawable(ClipState state, Resources res) {
+        mClipState = new ClipState(state, this, res);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/ColorDrawable.java b/graphics/java/android/graphics/drawable/ColorDrawable.java
index 226cc04..604c602 100644
--- a/graphics/java/android/graphics/drawable/ColorDrawable.java
+++ b/graphics/java/android/graphics/drawable/ColorDrawable.java
@@ -146,6 +146,11 @@
         }
 
         @Override
+        public Drawable newDrawable(Resources res) {
+            return new ColorDrawable(this);
+        }
+
+        @Override
         public int getChangingConfigurations() {
             return mChangingConfigurations;
         }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index 21b5e39..6a7b2d1 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -822,7 +822,26 @@
     }
 
     public static abstract class ConstantState {
+        /**
+         * Create a new drawable without supplying resources the caller
+         * is running in.  Note that using this means the density-dependent
+         * drawables (like bitmaps) will not be able to update their target
+         * density correctly.
+         */
         public abstract Drawable newDrawable();
+        /**
+         * Create a new Drawable instance from its constant state.  This
+         * must be implemented for drawables that change based on the target
+         * density of their caller (that is depending on whether it is
+         * in compatibility mode).
+         */
+        public Drawable newDrawable(Resources res) {
+            return newDrawable();
+        }
+        /**
+         * Return a bit mask of configuration changes that will impact
+         * this drawable (and thus require completely reloading it).
+         */
         public abstract int getChangingConfigurations();
     }
 
diff --git a/graphics/java/android/graphics/drawable/DrawableContainer.java b/graphics/java/android/graphics/drawable/DrawableContainer.java
index af1a289..3266f1e 100644
--- a/graphics/java/android/graphics/drawable/DrawableContainer.java
+++ b/graphics/java/android/graphics/drawable/DrawableContainer.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.content.res.Resources;
 import android.graphics.*;
 
 public class DrawableContainer extends Drawable implements Drawable.Callback {
@@ -285,7 +286,8 @@
 
         boolean     mPaddingChecked = false;
 
-        DrawableContainerState(DrawableContainerState orig, DrawableContainer owner) {
+        DrawableContainerState(DrawableContainerState orig, DrawableContainer owner,
+                Resources res) {
             mOwner = owner;
 
             if (orig != null) {
@@ -299,7 +301,11 @@
 
                 final int N = mNumChildren;
                 for (int i=0; i<N; i++) {
-                    mDrawables[i] = origDr[i].getConstantState().newDrawable();
+                    if (res != null) {
+                        mDrawables[i] = origDr[i].getConstantState().newDrawable(res);
+                    } else {
+                        mDrawables[i] = origDr[i].getConstantState().newDrawable();
+                    }
                     mDrawables[i].setCallback(owner);
                 }
 
diff --git a/graphics/java/android/graphics/drawable/GradientDrawable.java b/graphics/java/android/graphics/drawable/GradientDrawable.java
index a7a8708..ddbbaf1 100644
--- a/graphics/java/android/graphics/drawable/GradientDrawable.java
+++ b/graphics/java/android/graphics/drawable/GradientDrawable.java
@@ -917,6 +917,11 @@
         }
         
         @Override
+        public Drawable newDrawable(Resources res) {
+            return new GradientDrawable(this);
+        }
+        
+        @Override
         public int getChangingConfigurations() {
             return mChangingConfigurations;
         }
diff --git a/graphics/java/android/graphics/drawable/InsetDrawable.java b/graphics/java/android/graphics/drawable/InsetDrawable.java
index 6047726..4fa9d44 100644
--- a/graphics/java/android/graphics/drawable/InsetDrawable.java
+++ b/graphics/java/android/graphics/drawable/InsetDrawable.java
@@ -49,7 +49,7 @@
     private boolean mMutated;
 
     /*package*/ InsetDrawable() {
-        this(null);
+        this(null, null);
     }
 
     public InsetDrawable(Drawable drawable, int inset) {
@@ -58,7 +58,7 @@
 
     public InsetDrawable(Drawable drawable, int insetLeft, int insetTop,
                          int insetRight, int insetBottom) {
-        this(null);
+        this(null, null);
         
         mInsetState.mDrawable = drawable;
         mInsetState.mInsetLeft = insetLeft;
@@ -263,9 +263,13 @@
         boolean mCheckedConstantState;
         boolean mCanConstantState;
 
-        InsetState(InsetState orig, InsetDrawable owner) {
+        InsetState(InsetState orig, InsetDrawable owner, Resources res) {
             if (orig != null) {
-                mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                if (res != null) {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
+                } else {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                }
                 mDrawable.setCallback(owner);
                 mInsetLeft = orig.mInsetLeft;
                 mInsetTop = orig.mInsetTop;
@@ -277,7 +281,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new InsetDrawable(this);
+            return new InsetDrawable(this, null);
+        }
+        
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new InsetDrawable(this, res);
         }
         
         @Override
@@ -295,8 +304,8 @@
         }
     }
 
-    private InsetDrawable(InsetState state) {
-        mInsetState = new InsetState(state, this);
+    private InsetDrawable(InsetState state, Resources res) {
+        mInsetState = new InsetState(state, this, res);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/LayerDrawable.java b/graphics/java/android/graphics/drawable/LayerDrawable.java
index c777205..389fd40 100644
--- a/graphics/java/android/graphics/drawable/LayerDrawable.java
+++ b/graphics/java/android/graphics/drawable/LayerDrawable.java
@@ -70,7 +70,7 @@
      * @param state The constant drawable state.
      */
     LayerDrawable(Drawable[] layers, LayerState state) {
-        this(state);
+        this(state, null);
         int length = layers.length;
         ChildDrawable[] r = new ChildDrawable[length];
 
@@ -87,19 +87,19 @@
     }
     
     LayerDrawable() {
-        this((LayerState) null);
+        this((LayerState) null, null);
     }
 
-    LayerDrawable(LayerState state) {
-        LayerState as = createConstantState(state);
+    LayerDrawable(LayerState state, Resources res) {
+        LayerState as = createConstantState(state, res);
         mLayerState = as;
         if (as.mNum > 0) {
             ensurePadding();
         }
     }
 
-    LayerState createConstantState(LayerState state) {
-        return new LayerState(state, this);
+    LayerState createConstantState(LayerState state, Resources res) {
+        return new LayerState(state, this, res);
     }
 
     @Override
@@ -563,7 +563,7 @@
         private boolean mCheckedConstantState;
         private boolean mCanConstantState;
 
-        LayerState(LayerState orig, LayerDrawable owner) {
+        LayerState(LayerState orig, LayerDrawable owner, Resources res) {
             if (orig != null) {
                 final ChildDrawable[] origChildDrawable = orig.mChildren;
                 final int N = orig.mNum;
@@ -577,7 +577,11 @@
                 for (int i = 0; i < N; i++) {
                     final ChildDrawable r = mChildren[i] = new ChildDrawable();
                     final ChildDrawable or = origChildDrawable[i];
-                    r.mDrawable = or.mDrawable.getConstantState().newDrawable();
+                    if (res != null) {
+                        r.mDrawable = or.mDrawable.getConstantState().newDrawable(res);
+                    } else {
+                        r.mDrawable = or.mDrawable.getConstantState().newDrawable();
+                    }
                     r.mDrawable.setCallback(owner);
                     r.mInsetL = or.mInsetL;
                     r.mInsetT = or.mInsetT;
@@ -599,7 +603,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new LayerDrawable(this);
+            return new LayerDrawable(this, null);
+        }
+        
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new LayerDrawable(this, res);
         }
         
         @Override
diff --git a/graphics/java/android/graphics/drawable/LevelListDrawable.java b/graphics/java/android/graphics/drawable/LevelListDrawable.java
index 7ae649f..ae8f224 100644
--- a/graphics/java/android/graphics/drawable/LevelListDrawable.java
+++ b/graphics/java/android/graphics/drawable/LevelListDrawable.java
@@ -57,7 +57,7 @@
     private boolean mMutated;
 
     public LevelListDrawable() {
-        this(null);
+        this(null, null);
     }
 
     public void addLevel(int low, int high, Drawable drawable) {
@@ -154,8 +154,8 @@
         private int[] mLows;
         private int[] mHighs;
 
-        LevelListState(LevelListState orig, LevelListDrawable owner) {
-            super(orig, owner);
+        LevelListState(LevelListState orig, LevelListDrawable owner, Resources res) {
+            super(orig, owner, res);
 
             if (orig != null) {
                 mLows = orig.mLows;
@@ -186,7 +186,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new LevelListDrawable(this);
+            return new LevelListDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new LevelListDrawable(this, res);
         }
 
         @Override
@@ -201,8 +206,8 @@
         }
     }
 
-    private LevelListDrawable(LevelListState state) {
-        LevelListState as = new LevelListState(state, this);
+    private LevelListDrawable(LevelListState state, Resources res) {
+        LevelListState as = new LevelListState(state, this, res);
         mLevelListState = as;
         setConstantState(as);
         onLevelChange(getLevel());
diff --git a/graphics/java/android/graphics/drawable/NinePatchDrawable.java b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
index 997efb8..803e7b1 100644
--- a/graphics/java/android/graphics/drawable/NinePatchDrawable.java
+++ b/graphics/java/android/graphics/drawable/NinePatchDrawable.java
@@ -61,7 +61,7 @@
      */
     @Deprecated
     public NinePatchDrawable(Bitmap bitmap, byte[] chunk, Rect padding, String srcName) {
-        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding));
+        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), null);
     }
     
     /**
@@ -70,11 +70,8 @@
      */
     public NinePatchDrawable(Resources res, Bitmap bitmap, byte[] chunk,
             Rect padding, String srcName) {
-        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding));
-        if (res != null) {
-            setTargetDensity(res.getDisplayMetrics());
-            mNinePatchState.mTargetDensity = mTargetDensity;
-        }
+        this(new NinePatchState(new NinePatch(bitmap, chunk, srcName), padding), res);
+        mNinePatchState.mTargetDensity = mTargetDensity;
     }
     
     /**
@@ -84,7 +81,7 @@
      */
     @Deprecated
     public NinePatchDrawable(NinePatch patch) {
-        this(new NinePatchState(patch, null));
+        this(new NinePatchState(patch, null), null);
     }
 
     /**
@@ -92,18 +89,16 @@
      * based on the display metrics of the resources.
      */
     public NinePatchDrawable(Resources res, NinePatch patch) {
-        this(new NinePatchState(patch, null));
-        if (res != null) {
-            setTargetDensity(res.getDisplayMetrics());
-            mNinePatchState.mTargetDensity = mTargetDensity;
-        }
+        this(new NinePatchState(patch, null), res);
+        mNinePatchState.mTargetDensity = mTargetDensity;
     }
 
-    private void setNinePatchState(NinePatchState state) {
+    private void setNinePatchState(NinePatchState state, Resources res) {
         mNinePatchState = state;
         mNinePatch = state.mNinePatch;
         mPadding = state.mPadding;
-        mTargetDensity = state.mTargetDensity;
+        mTargetDensity = res != null ? res.getDisplayMetrics().densityDpi
+                : state.mTargetDensity;
         if (DEFAULT_DITHER != state.mDither) {
             // avoid calling the setter unless we need to, since it does a
             // lazy allocation of a paint
@@ -258,7 +253,8 @@
         }
 
         setNinePatchState(new NinePatchState(
-                new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"), padding, dither));
+                new NinePatch(bitmap, bitmap.getNinePatchChunk(), "XML 9-patch"),
+                padding, dither), r);
         mNinePatchState.mTargetDensity = mTargetDensity;
 
         a.recycle();
@@ -357,7 +353,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new NinePatchDrawable(this);
+            return new NinePatchDrawable(this, null);
+        }
+        
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new NinePatchDrawable(this, res);
         }
         
         @Override
@@ -366,8 +367,7 @@
         }
     }
 
-    private NinePatchDrawable(NinePatchState state) {
-        setNinePatchState(state);
+    private NinePatchDrawable(NinePatchState state, Resources res) {
+        setNinePatchState(state, res);
     }
 }
-
diff --git a/graphics/java/android/graphics/drawable/RotateDrawable.java b/graphics/java/android/graphics/drawable/RotateDrawable.java
index cb16cb7..c4a7822 100644
--- a/graphics/java/android/graphics/drawable/RotateDrawable.java
+++ b/graphics/java/android/graphics/drawable/RotateDrawable.java
@@ -54,7 +54,7 @@
      * <p>Create a new rotating drawable with an empty state.</p>
      */
     public RotateDrawable() {
-        this(null);
+        this(null, null);
     }
 
     /**
@@ -64,8 +64,8 @@
      *
      * @param rotateState the state for this drawable
      */
-    private RotateDrawable(RotateState rotateState) {
-        mState = new RotateState(rotateState, this);
+    private RotateDrawable(RotateState rotateState, Resources res) {
+        mState = new RotateState(rotateState, this, res);
     }
 
     public void draw(Canvas canvas) {
@@ -291,9 +291,13 @@
         private boolean mCanConstantState;
         private boolean mCheckedConstantState;        
 
-        public RotateState(RotateState source, RotateDrawable owner) {
+        public RotateState(RotateState source, RotateDrawable owner, Resources res) {
             if (source != null) {
-                mDrawable = source.mDrawable.getConstantState().newDrawable();
+                if (res != null) {
+                    mDrawable = source.mDrawable.getConstantState().newDrawable(res);
+                } else {
+                    mDrawable = source.mDrawable.getConstantState().newDrawable();
+                }
                 mDrawable.setCallback(owner);
                 mPivotXRel = source.mPivotXRel;
                 mPivotX = source.mPivotX;
@@ -307,7 +311,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new RotateDrawable(this);
+            return new RotateDrawable(this, null);
+        }
+        
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new RotateDrawable(this, res);
         }
         
         @Override
diff --git a/graphics/java/android/graphics/drawable/ScaleDrawable.java b/graphics/java/android/graphics/drawable/ScaleDrawable.java
index 7125ab1..275e36f 100644
--- a/graphics/java/android/graphics/drawable/ScaleDrawable.java
+++ b/graphics/java/android/graphics/drawable/ScaleDrawable.java
@@ -47,11 +47,11 @@
     private final Rect mTmpRect = new Rect();
 
     ScaleDrawable() {
-        this(null);
+        this(null, null);
     }
 
     public ScaleDrawable(Drawable drawable, int gravity, float scaleWidth, float scaleHeight) {
-        this(null);
+        this(null, null);
 
         mScaleState.mDrawable = drawable;
         mScaleState.mGravity = gravity;
@@ -260,9 +260,13 @@
         private boolean mCheckedConstantState;
         private boolean mCanConstantState;
 
-        ScaleState(ScaleState orig, ScaleDrawable owner) {
+        ScaleState(ScaleState orig, ScaleDrawable owner, Resources res) {
             if (orig != null) {
-                mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                if (res != null) {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable(res);
+                } else {
+                    mDrawable = orig.mDrawable.getConstantState().newDrawable();
+                }
                 mDrawable.setCallback(owner);
                 mScaleWidth = orig.mScaleWidth;
                 mScaleHeight = orig.mScaleHeight;
@@ -273,7 +277,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new ScaleDrawable(this);
+            return new ScaleDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new ScaleDrawable(this, res);
         }
 
         @Override
@@ -291,8 +300,8 @@
         }
     }
 
-    private ScaleDrawable(ScaleState state) {
-        mScaleState = new ScaleState(state, this);
+    private ScaleDrawable(ScaleState state, Resources res) {
+        mScaleState = new ScaleState(state, this, res);
     }
 }
 
diff --git a/graphics/java/android/graphics/drawable/ShapeDrawable.java b/graphics/java/android/graphics/drawable/ShapeDrawable.java
index 6677a35..c699a82 100644
--- a/graphics/java/android/graphics/drawable/ShapeDrawable.java
+++ b/graphics/java/android/graphics/drawable/ShapeDrawable.java
@@ -396,6 +396,11 @@
         }
         
         @Override
+        public Drawable newDrawable(Resources res) {
+            return new ShapeDrawable(this);
+        }
+        
+        @Override
         public int getChangingConfigurations() {
             return mChangingConfigurations;
         }
diff --git a/graphics/java/android/graphics/drawable/StateListDrawable.java b/graphics/java/android/graphics/drawable/StateListDrawable.java
index 59cb226..b1d588e 100644
--- a/graphics/java/android/graphics/drawable/StateListDrawable.java
+++ b/graphics/java/android/graphics/drawable/StateListDrawable.java
@@ -65,7 +65,7 @@
     private boolean mMutated;
 
     public StateListDrawable() {
-        this(null);
+        this(null, null);
     }
 
     /**
@@ -248,8 +248,8 @@
     static final class StateListState extends DrawableContainerState {
         private int[][] mStateSets;
 
-        StateListState(StateListState orig, StateListDrawable owner) {
-            super(orig, owner);
+        StateListState(StateListState orig, StateListDrawable owner, Resources res) {
+            super(orig, owner, res);
 
             if (orig != null) {
                 mStateSets = orig.mStateSets;
@@ -277,7 +277,12 @@
 
         @Override
         public Drawable newDrawable() {
-            return new StateListDrawable(this);
+            return new StateListDrawable(this, null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new StateListDrawable(this, res);
         }
 
         @Override
@@ -289,8 +294,8 @@
         }
     }
 
-    private StateListDrawable(StateListState state) {
-        StateListState as = new StateListState(state, this);
+    private StateListDrawable(StateListState state, Resources res) {
+        StateListState as = new StateListState(state, this, res);
         mStateListState = as;
         setConstantState(as);
         onStateChange(getState());
diff --git a/graphics/java/android/graphics/drawable/TransitionDrawable.java b/graphics/java/android/graphics/drawable/TransitionDrawable.java
index 358f889..97b45d8 100644
--- a/graphics/java/android/graphics/drawable/TransitionDrawable.java
+++ b/graphics/java/android/graphics/drawable/TransitionDrawable.java
@@ -16,6 +16,7 @@
 
 package android.graphics.drawable;
 
+import android.content.res.Resources;
 import android.graphics.Canvas;
 import android.os.SystemClock;
 
@@ -72,7 +73,7 @@
      * 2 layers are required for this drawable to work properly.
      */
     public TransitionDrawable(Drawable[] layers) {
-        this(new TransitionState(null, null), layers);
+        this(new TransitionState(null, null, null), layers);
     }
 
     /**
@@ -82,11 +83,11 @@
      * @see #TransitionDrawable(Drawable[])
      */
     TransitionDrawable() {
-        this(new TransitionState(null, null));
+        this(new TransitionState(null, null, null), (Resources)null);
     }
 
-    private TransitionDrawable(TransitionState state) {
-        super(state);
+    private TransitionDrawable(TransitionState state, Resources res) {
+        super(state, res);
     }
 
     private TransitionDrawable(TransitionState state, Drawable[] layers) {
@@ -94,8 +95,8 @@
     }
 
     @Override
-    LayerState createConstantState(LayerState state) {
-        return new TransitionState((TransitionState) state, this);
+    LayerState createConstantState(LayerState state, Resources res) {
+        return new TransitionState((TransitionState) state, this, res);
     }
     
     /**
@@ -229,13 +230,19 @@
     }
 
     static class TransitionState extends LayerState {
-        TransitionState(TransitionState orig, TransitionDrawable owner) {
-            super(orig, owner);
+        TransitionState(TransitionState orig, TransitionDrawable owner,
+                Resources res) {
+            super(orig, owner, res);
         }
 
         @Override
         public Drawable newDrawable() {
-            return new TransitionDrawable(this);
+            return new TransitionDrawable(this, (Resources)null);
+        }
+
+        @Override
+        public Drawable newDrawable(Resources res) {
+            return new TransitionDrawable(this, res);
         }
 
         @Override
diff --git a/include/private/ui/SharedBufferStack.h b/include/private/ui/SharedBufferStack.h
index 6181f55..8b0f154 100644
--- a/include/private/ui/SharedBufferStack.h
+++ b/include/private/ui/SharedBufferStack.h
@@ -228,6 +228,8 @@
     friend struct Condition;
     friend struct DequeueCondition;
     friend struct LockCondition;
+    
+    int32_t computeTail() const;
 
     struct QueueUpdate : public UpdateBase {
         inline QueueUpdate(SharedBufferBase* sbb);
diff --git a/include/utils/threads.h b/include/utils/threads.h
index f5304f7..0fc533f 100644
--- a/include/utils/threads.h
+++ b/include/utils/threads.h
@@ -90,11 +90,6 @@
     ANDROID_TGROUP_MAX              = ANDROID_TGROUP_FG_BOOST,
 };
 
-typedef enum {
-    SP_BACKGROUND = 0,
-    SP_FOREGROUND = 1,
-} SchedPolicy;
-
 // Create and run a new thread.
 extern int androidCreateThread(android_thread_func_t, void *);
 
diff --git a/libs/rs/java/Fountain/res/raw/fountain.c b/libs/rs/java/Fountain/res/raw/fountain.c
index 36516c2..57e10cf 100644
--- a/libs/rs/java/Fountain/res/raw/fountain.c
+++ b/libs/rs/java/Fountain/res/raw/fountain.c
@@ -20,20 +20,21 @@
         char r = Control->r * 255.f;
         char g = Control->g * 255.f;
         char b = Control->b * 255.f;
-        char a = 0xf0;
+        struct point_s * np = &p[newPart];
 
         while (rate--) {
-            vec2Rand((float *)(p + newPart), rMax);
-            p[newPart].x = x;
-            p[newPart].y = y;
-            p[newPart].r = r;
-            p[newPart].g = g;
-            p[newPart].b = b;
-            p[newPart].a = a;
+            vec2Rand((float *)np, rMax);
+            np->x = x;
+            np->y = y;
+            np->r = r;
+            np->g = g;
+            np->b = b;
+            np->a = 0xf0;
             newPart++;
             if (newPart >= count) {
                 newPart = 0;
             }
+            np++;
         }
     }
 
diff --git a/libs/surfaceflinger/SurfaceFlinger.cpp b/libs/surfaceflinger/SurfaceFlinger.cpp
index 8685f99..a352431 100644
--- a/libs/surfaceflinger/SurfaceFlinger.cpp
+++ b/libs/surfaceflinger/SurfaceFlinger.cpp
@@ -1524,13 +1524,24 @@
                 result.append( l->lcblk->dump("      ") );
                 sp<const Buffer> buf0(l->getBuffer(0));
                 sp<const Buffer> buf1(l->getBuffer(1));
+                uint32_t w0=0, h0=0, s0=0;
+                uint32_t w1=0, h1=0, s1=0;
+                if (buf0 != 0) {
+                    w0 = buf0->getWidth();
+                    h0 = buf0->getHeight();
+                    s0 = buf0->getStride();
+                }
+                if (buf1 != 0) {
+                    w1 = buf1->getWidth();
+                    h1 = buf1->getHeight();
+                    s1 = buf1->getStride();
+                }
                 snprintf(buffer, SIZE,
                         "      "
                         "format=%2d, [%3ux%3u:%3u] [%3ux%3u:%3u],"
                         " freezeLock=%p\n",
                         l->pixelFormat(),
-                        buf0->getWidth(), buf0->getHeight(), buf0->getStride(),
-                        buf1->getWidth(), buf1->getHeight(), buf1->getStride(),
+                        w0, h0, s0, w1, h1, s1,
                         l->getFreezeLock().get());
                 result.append(buffer);
                 buffer[0] = 0;
diff --git a/libs/ui/SharedBufferStack.cpp b/libs/ui/SharedBufferStack.cpp
index 436d793..7789a3f 100644
--- a/libs/ui/SharedBufferStack.cpp
+++ b/libs/ui/SharedBufferStack.cpp
@@ -246,19 +246,26 @@
         int surface, int num)
     : SharedBufferBase(sharedClient, surface, num), tail(0)
 {
+    tail = computeTail();
+}
+
+int32_t SharedBufferClient::computeTail() const
+{
     SharedBufferStack& stack( *mSharedStack );
-    int32_t avail;
-    int32_t head;
     // we need to make sure we read available and head coherently,
     // w.r.t RetireUpdate.
+    int32_t newTail;
+    int32_t avail;
+    int32_t head;
     do {
         avail = stack.available;
         head = stack.head;
     } while (stack.available != avail);
-    tail = head - avail + 1;
-    if (tail < 0) {
-        tail += num;
+    newTail = head - avail + 1;
+    if (newTail < 0) {
+        newTail += mNumBuffers;
     }
+    return newTail;
 }
 
 ssize_t SharedBufferClient::dequeue()
@@ -296,6 +303,9 @@
 {
     UndoDequeueUpdate update(this);
     status_t err = updateCondition( update );
+    if (err == NO_ERROR) {
+        tail = computeTail();
+    }
     return err;
 }
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index a964d17..22c2f39 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -232,6 +232,16 @@
         quirks |= kRequiresAllocateBufferOnOutputPorts;
     }
 
+    if (!strncmp(componentName, "OMX.TI.", 7)) {
+        // Apparently I must not use OMX_UseBuffer on either input or
+        // output ports on any of the TI components or quote:
+        // "(I) may have unexpected problem (sic) which can be timing related
+        //  and hard to reproduce."
+
+        quirks |= kRequiresAllocateBufferOnInputPorts;
+        quirks |= kRequiresAllocateBufferOnOutputPorts;
+    }
+
     sp<OMXCodec> codec = new OMXCodec(
             omx, node, quirks, createEncoder, mime, componentName,
             source);
@@ -840,8 +850,8 @@
                     mNode, portIndex, mem, &buffer);
         } else if (portIndex == kPortIndexOutput
                 && (mQuirks & kRequiresAllocateBufferOnOutputPorts)) {
-            err = mOMX->allocate_buffer(
-                    mNode, portIndex, def.nBufferSize, &buffer);
+            err = mOMX->allocate_buffer_with_backup(
+                    mNode, portIndex, mem, &buffer);
         } else {
             err = mOMX->use_buffer(mNode, portIndex, mem, &buffer);
         }
@@ -1256,6 +1266,8 @@
 
         CHECK_EQ(info->mOwnedByComponent, false);
 
+        CODEC_LOGV("freeing buffer %p on port %ld", info->mBuffer, portIndex);
+
         status_t err =
             mOMX->free_buffer(mNode, portIndex, info->mBuffer);
 
diff --git a/services/java/com/android/server/KeyInputQueue.java b/services/java/com/android/server/KeyInputQueue.java
index 244e136..d9f4c9c 100644
--- a/services/java/com/android/server/KeyInputQueue.java
+++ b/services/java/com/android/server/KeyInputQueue.java
@@ -981,6 +981,29 @@
         }
     }
 
+    /**
+     * Return true if the queue has an up event pending that corresponds
+     * to the same key as the given key event.
+     */
+    boolean hasKeyUpEvent(KeyEvent origEvent) {
+        synchronized (mFirst) {
+            final int keyCode = origEvent.getKeyCode();
+            QueuedEvent cur = mLast.prev;
+            while (cur.prev != null) {
+                if (cur.classType == RawInputEvent.CLASS_KEYBOARD) {
+                    KeyEvent ke = (KeyEvent)cur.event;
+                    if (ke.getAction() == KeyEvent.ACTION_UP
+                            && ke.getKeyCode() == keyCode) {
+                        return true;
+                    }
+                }
+                cur = cur.prev;
+            }
+        }
+        
+        return false;
+    }
+    
     void recycleEvent(QueuedEvent ev) {
         synchronized (mFirst) {
             //Log.i(TAG, "Recycle event: " + ev);
diff --git a/services/java/com/android/server/PowerManagerService.java b/services/java/com/android/server/PowerManagerService.java
index 38df47b..ba65f01 100644
--- a/services/java/com/android/server/PowerManagerService.java
+++ b/services/java/com/android/server/PowerManagerService.java
@@ -63,7 +63,7 @@
 import java.util.Observer;
 
 class PowerManagerService extends IPowerManager.Stub
-        implements LocalPowerManager,Watchdog.Monitor, SensorEventListener {
+        implements LocalPowerManager, Watchdog.Monitor, SensorEventListener {
 
     private static final String TAG = "PowerManagerService";
     static final String PARTIAL_NAME = "PowerManagerService";
@@ -1848,7 +1848,17 @@
     }
     
     public void setKeyboardVisibility(boolean visible) {
-        mKeyboardVisible = visible;
+        synchronized (mLocks) {
+            if (mSpew) {
+                Log.d(TAG, "setKeyboardVisibility: " + visible);
+            }
+            mKeyboardVisible = visible;
+            // don't signal user activity when closing keyboard if the screen is off.
+            // otherwise, we want to make sure the backlights are adjusted.
+            if (visible || (mPowerState & SCREEN_ON_BIT) != 0) {
+                userActivity(SystemClock.uptimeMillis(), false, BUTTON_EVENT, true);
+            }
+        }
     }
 
     /**
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index b0e4038..8e85a6a 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -99,6 +99,7 @@
 import android.view.Surface;
 import android.view.SurfaceSession;
 import android.view.View;
+import android.view.ViewConfiguration;
 import android.view.ViewTreeObserver;
 import android.view.WindowManager;
 import android.view.WindowManagerImpl;
@@ -151,9 +152,6 @@
 
     static final int LOG_WM_NO_SURFACE_MEMORY = 31000;
 
-    /** How long to wait for first key repeat, in milliseconds */
-    static final int KEY_REPEAT_FIRST_DELAY = 750;
-
     /** How long to wait for subsequent key repeats, in milliseconds */
     static final int KEY_REPEAT_DELAY = 50;
 
@@ -418,6 +416,17 @@
     int mWallpaperAnimLayerAdjustment;
     float mLastWallpaperX;
     float mLastWallpaperY;
+    // Lock for waiting for the wallpaper.
+    final Object mWaitingOnWallpaperLock = new Object();
+    // This is set when we are waiting for a wallpaper to tell us it is done
+    // changing its scroll position.
+    WindowState mWaitingOnWallpaper;
+    // The last time we had a timeout when waiting for a wallpaper.
+    long mLastWallpaperTimeoutTime;
+    // We give a wallpaper up to 150ms to finish scrolling.
+    static final long WALLPAPER_TIMEOUT = 150;
+    // Time we wait after a timeout before trying to wait again.
+    static final long WALLPAPER_TIMEOUT_RECOVERY = 10000;
     
     AppWindowToken mFocusedApp = null;
 
@@ -1427,7 +1436,7 @@
                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
                 
                 if (visible) {
-                    updateWallpaperOffsetLocked(wallpaper, dw, dh);                        
+                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
                 }
                 
                 // First, make sure the client has the current visibility
@@ -1498,7 +1507,8 @@
         }
     }
 
-    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh) {
+    boolean updateWallpaperOffsetLocked(WindowState wallpaperWin, int dw, int dh,
+            boolean sync) {
         boolean changed = false;
         boolean rawChanged = false;
         if (mLastWallpaperX >= 0) {
@@ -1536,8 +1546,37 @@
                 if (DEBUG_WALLPAPER) Log.v(TAG, "Report new wp offset "
                         + wallpaperWin + " x=" + wallpaperWin.mWallpaperX
                         + " y=" + wallpaperWin.mWallpaperY);
+                if (sync) {
+                    synchronized (mWaitingOnWallpaperLock) {
+                        mWaitingOnWallpaper = wallpaperWin;
+                    }
+                }
                 wallpaperWin.mClient.dispatchWallpaperOffsets(
-                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY);
+                        wallpaperWin.mWallpaperX, wallpaperWin.mWallpaperY, sync);
+                if (sync) {
+                    synchronized (mWaitingOnWallpaperLock) {
+                        if (mWaitingOnWallpaper != null) {
+                            long start = SystemClock.uptimeMillis();
+                            if ((mLastWallpaperTimeoutTime+WALLPAPER_TIMEOUT_RECOVERY)
+                                    < start) {
+                                try {
+                                    if (DEBUG_WALLPAPER) Log.v(TAG,
+                                            "Waiting for offset complete...");
+                                    mWaitingOnWallpaperLock.wait(WALLPAPER_TIMEOUT);
+                                } catch (InterruptedException e) {
+                                }
+                                if (DEBUG_WALLPAPER) Log.v(TAG, "Offset complete!");
+                                if ((start+WALLPAPER_TIMEOUT)
+                                        < SystemClock.uptimeMillis()) {
+                                    Log.i(TAG, "Timeout waiting for wallpaper to offset: "
+                                            + wallpaperWin);
+                                    mLastWallpaperTimeoutTime = start;
+                                }
+                            }
+                            mWaitingOnWallpaper = null;
+                        }
+                    }
+                }
             } catch (RemoteException e) {
             }
         }
@@ -1545,7 +1584,17 @@
         return changed;
     }
     
-    boolean updateWallpaperOffsetLocked() {
+    void wallpaperOffsetsComplete(IBinder window) {
+        synchronized (mWaitingOnWallpaperLock) {
+            if (mWaitingOnWallpaper != null &&
+                    mWaitingOnWallpaper.mClient.asBinder() == window) {
+                mWaitingOnWallpaper = null;
+                mWaitingOnWallpaperLock.notifyAll();
+            }
+        }
+    }
+    
+    boolean updateWallpaperOffsetLocked(boolean sync) {
         final int dw = mDisplay.getWidth();
         final int dh = mDisplay.getHeight();
         
@@ -1563,9 +1612,11 @@
                 while (curWallpaperIndex > 0) {
                     curWallpaperIndex--;
                     WindowState wallpaper = token.windows.get(curWallpaperIndex);
-                    if (updateWallpaperOffsetLocked(wallpaper, dw, dh)) {
+                    if (updateWallpaperOffsetLocked(wallpaper, dw, dh, sync)) {
                         wallpaper.computeShownFrameLocked();
                         changed = true;
+                        // We only want to be synchronous with one wallpaper.
+                        sync = false;
                     }
                 }
             }
@@ -1595,7 +1646,7 @@
                 curWallpaperIndex--;
                 WindowState wallpaper = token.windows.get(curWallpaperIndex);
                 if (visible) {
-                    updateWallpaperOffsetLocked(wallpaper, dw, dh);                        
+                    updateWallpaperOffsetLocked(wallpaper, dw, dh, false);
                 }
                 
                 if (wallpaper.mWallpaperVisible != visible) {
@@ -1782,8 +1833,10 @@
                 imMayMove = false;
             } else {
                 addWindowToListInOrderLocked(win, true);
-                if (attrs.type == TYPE_WALLPAPER ||
-                        (attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
+                if (attrs.type == TYPE_WALLPAPER) {
+                    mLastWallpaperTimeoutTime = 0;
+                    adjustWallpaperWindowsLocked();
+                } else if ((attrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
                     adjustWallpaperWindowsLocked();
                 }
             }
@@ -1992,8 +2045,10 @@
             }
         }
 
-        if (win.mAttrs.type == TYPE_WALLPAPER ||
-                (win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
+        if (win.mAttrs.type == TYPE_WALLPAPER) {
+            mLastWallpaperTimeoutTime = 0;
+            adjustWallpaperWindowsLocked();
+        } else if ((win.mAttrs.flags&FLAG_SHOW_WALLPAPER) != 0) {
             adjustWallpaperWindowsLocked();
         }
         
@@ -2070,7 +2125,7 @@
             window.mWallpaperY = y;
             
             if (mWallpaperTarget == window) {
-                if (updateWallpaperOffsetLocked()) {
+                if (updateWallpaperOffsetLocked(true)) {
                     performLayoutAndPlaceSurfacesLocked();
                 }
             }
@@ -2258,7 +2313,7 @@
             performLayoutAndPlaceSurfacesLocked();
             if (displayed && win.mIsWallpaper) {
                 updateWallpaperOffsetLocked(win, mDisplay.getWidth(),
-                        mDisplay.getHeight());
+                        mDisplay.getHeight(), false);
             }
             if (win.mAppToken != null) {
                 win.mAppToken.updateReportedVisibilityLocked();
@@ -4843,6 +4898,16 @@
             return INJECT_SUCCEEDED;
         }
 
+        // Okay we have finished waiting for the last event to be processed.
+        // First off, if this is a repeat event, check to see if there is
+        // a corresponding up event in the queue.  If there is, we will
+        // just drop the repeat, because it makes no sense to repeat after
+        // the user has released a key.  (This is especially important for
+        // long presses.)
+        if (event.getRepeatCount() > 0 && mQueue.hasKeyUpEvent(event)) {
+            return INJECT_SUCCEEDED;
+        }
+        
         WindowState focus = (WindowState)focusObj;
 
         if (DEBUG_INPUT) Log.v(
@@ -5961,6 +6026,7 @@
             // Last keydown time for auto-repeating keys
             long lastKeyTime = SystemClock.uptimeMillis();
             long nextKeyTime = lastKeyTime+LONG_WAIT;
+            long downTime = 0;
 
             // How many successive repeats we generated
             int keyRepeatCount = 0;
@@ -6031,15 +6097,17 @@
                                 KeyEvent ke = (KeyEvent)ev.event;
                                 if (ke.isDown()) {
                                     lastKey = ke;
+                                    downTime = curTime;
                                     keyRepeatCount = 0;
                                     lastKeyTime = curTime;
                                     nextKeyTime = lastKeyTime
-                                            + KEY_REPEAT_FIRST_DELAY;
+                                            + ViewConfiguration.getLongPressTimeout();
                                     if (DEBUG_INPUT) Log.v(
                                         TAG, "Received key down: first repeat @ "
                                         + nextKeyTime);
                                 } else {
                                     lastKey = null;
+                                    downTime = 0;
                                     // Arbitrary long timeout.
                                     lastKeyTime = curTime;
                                     nextKeyTime = curTime + LONG_WAIT;
@@ -6087,7 +6155,19 @@
                         if (DEBUG_INPUT) Log.v(
                             TAG, "Key repeat: count=" + keyRepeatCount
                             + ", next @ " + nextKeyTime);
-                        dispatchKey(KeyEvent.changeTimeRepeat(lastKey, curTime, keyRepeatCount), 0, 0);
+                        KeyEvent newEvent;
+                        if (downTime != 0 && (downTime
+                                + ViewConfiguration.getLongPressTimeout())
+                                <= curTime) {
+                            newEvent = KeyEvent.changeTimeRepeat(lastKey,
+                                    curTime, keyRepeatCount,
+                                    lastKey.getFlags() | KeyEvent.FLAG_LONG_PRESS);
+                            downTime = 0;
+                        } else {
+                            newEvent = KeyEvent.changeTimeRepeat(lastKey,
+                                    curTime, keyRepeatCount);
+                        }
+                        dispatchKey(newEvent, 0, 0);
 
                     } else {
                         curTime = SystemClock.uptimeMillis();
@@ -6303,6 +6383,10 @@
             }
         }
         
+        public void wallpaperOffsetsComplete(IBinder window) {
+            WindowManagerService.this.wallpaperOffsetsComplete(window);
+        }
+        
         void windowAddedLocked() {
             if (mSurfaceSession == null) {
                 if (localLOGV) Log.v(
@@ -6698,7 +6782,7 @@
 
             if (mIsWallpaper && (fw != frame.width() || fh != frame.height())) {
                 updateWallpaperOffsetLocked(this, mDisplay.getWidth(),
-                        mDisplay.getHeight());
+                        mDisplay.getHeight(), false);
             }
             
             if (localLOGV) {
diff --git a/telephony/java/com/android/internal/telephony/IccProvider.java b/telephony/java/com/android/internal/telephony/IccProvider.java
index ffcfe6f..8b54ca8 100644
--- a/telephony/java/com/android/internal/telephony/IccProvider.java
+++ b/telephony/java/com/android/internal/telephony/IccProvider.java
@@ -181,7 +181,7 @@
             return null;
         }
 
-        StringBuilder buf = new StringBuilder("content://im/");
+        StringBuilder buf = new StringBuilder("content://icc/");
         switch (match) {
             case ADN:
                 buf.append("adn/");
diff --git a/tests/DumpRenderTree/assets/run_layout_tests.py b/tests/DumpRenderTree/assets/run_layout_tests.py
index c3e6b5b..c3627bb 100755
--- a/tests/DumpRenderTree/assets/run_layout_tests.py
+++ b/tests/DumpRenderTree/assets/run_layout_tests.py
@@ -197,7 +197,17 @@
     logging.error("DumpRenderTree crashed, output:\n" + adb_output)
 
     shell_cmd_str = adb_cmd + " shell cat /sdcard/android/running_test.txt"
-    crashed_test = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE).communicate()[0]
+    crashed_test = ""
+    while not crashed_test:
+      (crashed_test, err) = subprocess.Popen(
+          shell_cmd_str, shell=True, stdout=subprocess.PIPE,
+          stderr=subprocess.PIPE).communicate()
+      crashed_test = crashed_test.strip()
+      if not crashed_test:
+        logging.error('Cannot get crashed test name, device offline?')
+        logging.error('stderr: ' + err)
+        logging.error('retrying in 10s...')
+        time.sleep(10)
 
     logging.info(crashed_test + " CRASHED");
     crashed_tests.append(crashed_test);
diff --git a/tests/DumpRenderTree/assets/run_page_cycler.py b/tests/DumpRenderTree/assets/run_page_cycler.py
index 2325047..4a68d72 100755
--- a/tests/DumpRenderTree/assets/run_page_cycler.py
+++ b/tests/DumpRenderTree/assets/run_page_cycler.py
@@ -59,8 +59,18 @@
   run_load_test_cmd = run_load_test_cmd_prefix + " -e class com.android.dumprendertree.LoadTestsAutoTest#runPageCyclerTest -e path \"" + path + "\" -e timeout " + timeout_ms + run_load_test_cmd_postfix
 
   (adb_output, adb_error) = subprocess.Popen(run_load_test_cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()
-  if adb_output.find('INSTRUMENTATION_FAILED') != -1 or \
-      adb_output.find('Process crashed.') != -1:
+  fail_flag = False
+  for line in adb_output.splitlines():
+    line = line.strip()
+    if line.find('INSTRUMENTATION_CODE') == 0:
+      if not line[22:] == '-1':
+        fail_flag = True
+        break
+    if (line.find('INSTRUMENTATION_FAILED') != -1 or
+        line.find('Process crashed.') != -1):
+      fail_flag = True
+      break
+  if fail_flag:
     logging.error("Error happened : " + adb_output)
     sys.exit(1)
 
@@ -80,7 +90,6 @@
   shell_cmd_str = adb_cmd + " pull " + result_file + " " + results_dir
   adb_output = subprocess.Popen(shell_cmd_str, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE).communicate()[0]
   logging.info(adb_output)
-    
   logging.info("Results are stored under: " + results_dir + "/load_test_result.txt\n")
 
 if '__main__' == __name__:
diff --git a/tests/DumpRenderTree/assets/run_reliability_tests.py b/tests/DumpRenderTree/assets/run_reliability_tests.py
index 23f93df..59ac4a3 100755
--- a/tests/DumpRenderTree/assets/run_reliability_tests.py
+++ b/tests/DumpRenderTree/assets/run_reliability_tests.py
@@ -195,8 +195,18 @@
   while not DumpRenderTreeFinished(adb_cmd):
     logging.error("DumpRenderTree exited before all URLs are visited.")
     shell_cmd_str = adb_cmd + " shell cat " + TEST_STATUS_FILE
-    crashed_test = subprocess.Popen(shell_cmd_str, shell=True,
-                                    stdout=subprocess.PIPE).communicate()[0]
+    crashed_test = ""
+    while not crashed_test:
+      (crashed_test, err) = subprocess.Popen(
+          shell_cmd_str, shell=True, stdout=subprocess.PIPE,
+          stderr=subprocess.PIPE).communicate()
+      crashed_test = crashed_test.strip()
+      if not crashed_test:
+        logging.error('Cannot get crashed test name, device offline?')
+        logging.error('stderr: ' + err)
+        logging.error('retrying in 10s...')
+        time.sleep(10)
+
     logging.info(crashed_test + " CRASHED")
     crashed_tests.append(crashed_test)
     Bugreport(crashed_test, bugreport_dir, adb_cmd)
diff --git a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
index c562650..4dbcfdc 100644
--- a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
+++ b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutBridge.java
@@ -88,7 +88,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @since 4
      */
     ILayoutResult computeLayout(IXmlPullParser layoutDescription,
@@ -123,7 +123,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @since 3
      */
     @Deprecated
@@ -155,7 +155,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @deprecated Use {@link #computeLayout(IXmlPullParser, Object, int, int, int, float, float, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}
      * @since 2
      */
@@ -187,7 +187,7 @@
      * @param projectCallback The {@link IProjectCallback} object to get information from
      * the project.
      * @param logger the object responsible for displaying warning/errors to the user.
-     * @return an {@link ILayoutResult} object that contains the result of the layout.
+     * @return a new {@link ILayoutResult} object that contains the result of the layout.
      * @deprecated Use {@link #computeLayout(IXmlPullParser, Object, int, int, int, float, float, String, boolean, Map, Map, IProjectCallback, ILayoutLog)}
      * @since 1
      */
@@ -205,7 +205,7 @@
      * until this method is called.
      * <p/>The cache is not configuration dependent and should only be cleared when a
      * resource changes (at this time only bitmaps and 9 patches go into the cache).
-     * @param objectKey the key for the project.
+     * @param projectKey the key for the project.
      * @since 1
      */
     void clearCaches(Object projectKey);
diff --git a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
index 5a06349..2d8a210 100644
--- a/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
+++ b/tools/layoutlib/api/src/com/android/layoutlib/api/ILayoutResult.java
@@ -23,13 +23,17 @@
  * {@link ILayoutLibBridge#computeLayout(IXmlPullParser, int, int, String, java.util.Map, java.util.Map, java.util.Map, IFontLoader, ILayoutLibLog, ICustomViewLoader)}
  */
 public interface ILayoutResult {
-    /** Sucess return code */
+    /**
+     * Success return code
+     */
     final static int SUCCESS = 0;
-    /** Error return code.
-     *  <p/>See {@link #getErrorMessage()}
-     */ 
+
+    /**
+     * Error return code, in which case an error message is guaranteed to be defined.
+     * @See {@link #getErrorMessage()}
+     */
     final static int ERROR = 1;
-    
+
     /**
      * Returns the result code.
      * @see #SUCCESS
@@ -62,18 +66,18 @@
          * Returns the list of children views.
          */
         ILayoutViewInfo[] getChildren();
-        
+
         /**
          * Returns the key associated with the node.
          * @see IXmlPullParser#getViewKey()
          */
         Object getViewKey();
-        
+
         /**
          * Returns the name of the view.
          */
         String getName();
-        
+
         /**
          * Returns the left of the view bounds.
          */
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
index 55fe4ac..0888fd8 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/Bridge.java
@@ -1051,15 +1051,22 @@
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
         public void setInsets(IWindow window, int touchable, Rect contentInsets,
                 Rect visibleInsets) {
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
         public void setWallpaperPosition(IBinder window, float x, float y) {
             // pass for now.
         }
 
+        @SuppressWarnings("unused")
+        public void wallpaperOffsetsComplete(IBinder window) {
+            // pass for now.
+        }
+        
         public IBinder asBinder() {
             // pass for now.
             return null;
@@ -1114,7 +1121,7 @@
         }
 
         @SuppressWarnings("unused")
-        public void dispatchWallpaperOffsets(float x, float y) {
+        public void dispatchWallpaperOffsets(float x, float y, boolean sync) {
             // pass for now.
         }