Merge "Fix bug 3374792 - Default holo dark activity background is badly dithered at full size" into honeycomb
diff --git a/api/current.xml b/api/current.xml
index 8655ad3..9520f19 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -234861,6 +234861,17 @@
  visibility="public"
 >
 </method>
+<method name="getDisplayZoomControls"
+ return="boolean"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+</method>
 <method name="getDomStorageEnabled"
  return="boolean"
  abstract="false"
@@ -235355,6 +235366,19 @@
 <parameter name="zoom" type="android.webkit.WebSettings.ZoomDensity">
 </parameter>
 </method>
+<method name="setDisplayZoomControls"
+ return="void"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="false"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="enabled" type="boolean">
+</parameter>
+</method>
 <method name="setDomStorageEnabled"
  return="void"
  abstract="false"
diff --git a/core/java/android/accounts/ChooseAccountActivity.java b/core/java/android/accounts/ChooseAccountActivity.java
index 0bbb6fc..293df78 100644
--- a/core/java/android/accounts/ChooseAccountActivity.java
+++ b/core/java/android/accounts/ChooseAccountActivity.java
@@ -15,23 +15,39 @@
  */
 package android.accounts;
 
-import android.app.ListActivity;
+import android.app.Activity;
+import android.content.Context;
+import android.content.pm.PackageManager;
+import android.graphics.drawable.Drawable;
 import android.os.Bundle;
 import android.os.Parcelable;
-import android.widget.ArrayAdapter;
-import android.widget.ListView;
-import android.view.View;
 import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.AdapterView;
+import android.widget.ArrayAdapter;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+import com.android.internal.R;
+
+import java.util.HashMap;
 
 /**
  * @hide
  */
-public class ChooseAccountActivity extends ListActivity {
+public class ChooseAccountActivity extends Activity {
+
     private static final String TAG = "AccountManager";
+
     private Parcelable[] mAccounts = null;
     private AccountManagerResponse mAccountManagerResponse = null;
     private Bundle mResult;
 
+    private HashMap<String, AuthenticatorDescription> mTypeToAuthDescription
+            = new HashMap<String, AuthenticatorDescription>();
+
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
@@ -47,16 +63,51 @@
             return;
         }
 
-        String[] mAccountNames = new String[mAccounts.length];
+        getAuthDescriptions();
+
+        AccountInfo[] mAccountInfos = new AccountInfo[mAccounts.length];
         for (int i = 0; i < mAccounts.length; i++) {
-            mAccountNames[i] = ((Account) mAccounts[i]).name;
+            mAccountInfos[i] = new AccountInfo(((Account) mAccounts[i]).name,
+                    getDrawableForType(((Account) mAccounts[i]).type));
         }
 
-        // Use an existing ListAdapter that will map an array
-        // of strings to TextViews
-        setListAdapter(new ArrayAdapter<String>(this,
-                android.R.layout.simple_list_item_1, mAccountNames));
-        getListView().setTextFilterEnabled(true);
+        setContentView(R.layout.choose_account);
+
+        // Setup the list
+        ListView list = (ListView) findViewById(android.R.id.list);
+        // Use an existing ListAdapter that will map an array of strings to TextViews
+        list.setAdapter(new AccountArrayAdapter(this,
+                android.R.layout.simple_list_item_1, mAccountInfos));
+        list.setChoiceMode(ListView.CHOICE_MODE_SINGLE);
+        list.setTextFilterEnabled(true);
+        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
+            public void onItemClick(AdapterView<?> parent, View v, int position, long id) {
+                onListItemClick((ListView)parent, v, position, id);
+            }
+        });
+    }
+
+    private void getAuthDescriptions() {
+        for(AuthenticatorDescription desc : AccountManager.get(this).getAuthenticatorTypes()) {
+            mTypeToAuthDescription.put(desc.type, desc);
+        }
+    }
+
+    private Drawable getDrawableForType(String accountType) {
+        Drawable icon = null;
+        if(mTypeToAuthDescription.containsKey(accountType)) {
+            try {
+                AuthenticatorDescription desc = mTypeToAuthDescription.get(accountType);
+                Context authContext = createPackageContext(desc.packageName, 0);
+                icon = authContext.getResources().getDrawable(desc.iconId);
+            } catch (PackageManager.NameNotFoundException e) {
+                // Nothing we can do much here, just log
+                if (Log.isLoggable(TAG, Log.WARN)) {
+                    Log.w(TAG, "No icon for account type " + accountType);
+                }
+            }
+        }
+        return icon;
     }
 
     protected void onListItemClick(ListView l, View v, int position, long id) {
@@ -79,4 +130,51 @@
         }
         super.finish();
     }
+
+    private static class AccountInfo {
+        final String name;
+        final Drawable drawable;
+
+        AccountInfo(String name, Drawable drawable) {
+            this.name = name;
+            this.drawable = drawable;
+        }
+    }
+
+    private static class ViewHolder {
+        ImageView icon;
+        TextView text;
+    }
+
+    private static class AccountArrayAdapter extends ArrayAdapter<AccountInfo> {
+        private LayoutInflater mLayoutInflater;
+        private AccountInfo[] mInfos;
+
+        public AccountArrayAdapter(Context context, int textViewResourceId, AccountInfo[] infos) {
+            super(context, textViewResourceId, infos);
+            mInfos = infos;
+            mLayoutInflater = (LayoutInflater) context.getSystemService(
+                    Context.LAYOUT_INFLATER_SERVICE);
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            ViewHolder holder;
+
+            if (convertView == null) {
+                convertView = mLayoutInflater.inflate(R.layout.choose_account_row, null);
+                holder = new ViewHolder();
+                holder.text = (TextView) convertView.findViewById(R.id.account_row_text);
+                holder.icon = (ImageView) convertView.findViewById(R.id.account_row_icon);
+                convertView.setTag(holder);
+            } else {
+                holder = (ViewHolder) convertView.getTag();
+            }
+
+            holder.text.setText(mInfos[position].name);
+            holder.icon.setImageDrawable(mInfos[position].drawable);
+
+            return convertView;
+        }
+    }
 }
diff --git a/core/java/android/bluetooth/BluetoothHeadset.java b/core/java/android/bluetooth/BluetoothHeadset.java
index d5b0042..2959fc0 100644
--- a/core/java/android/bluetooth/BluetoothHeadset.java
+++ b/core/java/android/bluetooth/BluetoothHeadset.java
@@ -670,6 +670,26 @@
         return false;
     }
 
+    /**
+     * Send a AT command message to the headset.
+     * @param device Remote Bluetooth Device
+     * @param cmd The String to send.
+     * @hide
+     */
+    public void sendAtCommand(BluetoothDevice device, String command) {
+        if (DBG) log("sendAtCommand()");
+        if (mService != null && isEnabled() && isValidDevice(device)) {
+            try {
+                mService.sendAtCommand(device, command);
+            } catch (RemoteException e) {
+                Log.e(TAG, e.toString());
+            }
+        } else {
+            Log.w(TAG, "Proxy not attached to service");
+            if (DBG) Log.d(TAG, Log.getStackTraceString(new Throwable()));
+        }
+    }
+
     private ServiceConnection mConnection = new ServiceConnection() {
         public void onServiceConnected(ComponentName className, IBinder service) {
             if (DBG) Log.d(TAG, "Proxy object connected");
diff --git a/core/java/android/bluetooth/IBluetoothHeadset.aidl b/core/java/android/bluetooth/IBluetoothHeadset.aidl
index e952193..3c6cf77 100644
--- a/core/java/android/bluetooth/IBluetoothHeadset.aidl
+++ b/core/java/android/bluetooth/IBluetoothHeadset.aidl
@@ -50,4 +50,6 @@
 
     boolean startVirtualVoiceCall(in BluetoothDevice device);
     boolean stopVirtualVoiceCall(in BluetoothDevice device);
+
+    void sendAtCommand(in BluetoothDevice device, String urc);
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6f23215..4f21265 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1801,7 +1801,6 @@
             SCREEN_BRIGHTNESS,
             SCREEN_BRIGHTNESS_MODE,
             VIBRATE_ON,
-            NOTIFICATIONS_USE_RING_VOLUME,
             MODE_RINGER,
             MODE_RINGER_STREAMS_AFFECTED,
             MUTE_STREAMS_AFFECTED,
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 811a633..b41687e 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -5117,7 +5117,16 @@
           removeCallbacks(mPendingCheckForLongPress);
         }
     }
-    
+
+    /**
+     * Remove the pending click action
+     */
+    private void removePerformClickCallback() {
+        if (mPerformClick != null) {
+            removeCallbacks(mPerformClick);
+        }
+    }
+
     /**
      * Remove the prepress detection timer.
      */
@@ -7579,6 +7588,7 @@
 
         removeUnsetPressCallback();
         removeLongPressCallback();
+        removePerformClickCallback();
 
         destroyDrawingCache();
 
diff --git a/core/java/android/webkit/WebSettings.java b/core/java/android/webkit/WebSettings.java
index 518ba69..0bf0eab 100644
--- a/core/java/android/webkit/WebSettings.java
+++ b/core/java/android/webkit/WebSettings.java
@@ -571,7 +571,6 @@
      * A combination of built in zoom controls enabled
      * and on screen zoom controls disabled allows for pinch to zoom
      * to work without the on screen controls
-     * @hide
      */
     public void setDisplayZoomControls(boolean enabled) {
         mDisplayZoomControls = enabled;
@@ -580,7 +579,6 @@
 
     /**
      * Returns true if the on screen zoom buttons are being used.
-     * @hide
      */
     public boolean getDisplayZoomControls() {
         return mDisplayZoomControls;
diff --git a/core/java/android/webkit/WebTextView.java b/core/java/android/webkit/WebTextView.java
index 59a239a..6e1a6fc 100644
--- a/core/java/android/webkit/WebTextView.java
+++ b/core/java/android/webkit/WebTextView.java
@@ -1087,7 +1087,7 @@
      */
     /* package */ void setTextAndKeepSelection(String text) {
         mPreChange = text.toString();
-        Editable edit = (Editable) getText();
+        Editable edit = getText();
         int selStart = Selection.getSelectionStart(edit);
         int selEnd = Selection.getSelectionEnd(edit);
         mInSetTextAndKeepSelection = true;
@@ -1097,6 +1097,12 @@
         if (selEnd > newLength) selEnd = newLength;
         Selection.setSelection(edit, selStart, selEnd);
         mInSetTextAndKeepSelection = false;
+        InputMethodManager imm = InputMethodManager.peekInstance();
+        if (imm != null && imm.isActive(this)) {
+            // Since the text has changed, do not allow the IME to replace the
+            // existing text as though it were a completion.
+            imm.restartInput(this);
+        }
         updateCachedTextfield();
     }
 
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index fad0a4f..aac57ed 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -4791,8 +4791,6 @@
             return super.onKeyUp(keyCode, event);
         }
 
-        hideControllers();
-
         switch (keyCode) {
             case KeyEvent.KEYCODE_DPAD_CENTER:
                 mDPadCenterIsDown = false;
@@ -7126,6 +7124,13 @@
         }
 
         super.onFocusChanged(focused, direction, previouslyFocusedRect);
+
+        // After super.onFocusChanged so that this TextView is registered and can ask for the IME
+        // Showing the IME while focus is moved using the D-Pad is a bad idea, however this does
+        // not happen in that case (using the arrows on a bluetooth keyboard).
+        if (focused) {
+            onTouchFinished(null);
+        }
     }
 
     private int getLastTapPosition() {
@@ -7268,6 +7273,9 @@
             return superResult;
         }
 
+        final boolean touchIsFinished = action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent &&
+                isFocused();
+
         if ((mMovement != null || onCheckIsTextEditor()) && isEnabled()
                 && mText instanceof Spannable && mLayout != null) {
             boolean handled = false;
@@ -7283,8 +7291,7 @@
                 handled |= mMovement.onTouchEvent(this, (Spannable) mText, event);
             }
 
-            if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable &&
-                    action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) {
+            if (mLinksClickable && mAutoLinkMask != 0 && mTextIsSelectable && touchIsFinished) {
                 // The LinkMovementMethod which should handle taps on links has not been installed
                 // to support text selection. We reproduce its behavior here to open links.
                 ClickableSpan[] links = ((Spannable) mText).getSpans(getSelectionStart(),
@@ -7306,26 +7313,15 @@
                         mSelectionModifierCursorController.updatePosition();
                     }
                 }
-                if (action == MotionEvent.ACTION_UP && !mIgnoreActionUpEvent && isFocused()) {
-                    InputMethodManager imm = (InputMethodManager)
-                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
 
+                if (touchIsFinished) {
                     CommitSelectionReceiver csr = null;
                     if (getSelectionStart() != oldSelStart || getSelectionEnd() != oldSelEnd ||
                             didTouchFocusSelect()) {
                         csr = new CommitSelectionReceiver(oldSelStart, oldSelEnd);
                     }
 
-                    if (!mTextIsSelectable) {
-                        // Show the IME, except when selecting in read-only text.
-                        handled |= imm.showSoftInput(this, 0, csr) && (csr != null);
-                    }
-
-                    stopSelectionActionMode();
-                    boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected;
-                    if (hasInsertionController() && !selectAllGotFocus) {
-                        getInsertionController().show();
-                    }
+                    handled = onTouchFinished(csr);
                 }
             }
 
@@ -7337,6 +7333,35 @@
         return superResult;
     }
 
+    /** Shows the IME if applicable, ends selection mode and displays the selection controller.
+     *
+     * This method is called at the end of a touch event, when the finger is lifted up.
+     * It is also called when the TextField gains focus indirectly through a dispatched event from
+     * one of its parents. We want to have the same behavior in that case.
+     *
+     * @param csr A (possibly null) callback called if the IME has been displayed
+     * @return true if the event was properly sent to the csr
+     */
+    private boolean onTouchFinished(CommitSelectionReceiver csr) {
+        boolean handled = false;
+
+        // Show the IME, except when selecting in read-only text.
+        if (!mTextIsSelectable) {
+            final InputMethodManager imm = (InputMethodManager)
+                    getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
+
+            handled = imm.showSoftInput(this, 0, csr) && (csr != null);
+        }
+
+        stopSelectionActionMode();
+        boolean selectAllGotFocus = mSelectAllOnFocus && mTouchFocusSelected;
+        if (hasInsertionController() && !selectAllGotFocus) {
+            getInsertionController().show();
+        }
+
+        return handled;
+    }
+
     private void prepareCursorControllers() {
         boolean windowSupportsHandles = false;
 
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 6a7db1f0..bb23173 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -301,6 +301,8 @@
         final Runnable mHide = new Runnable() {
             public void run() {
                 handleHide();
+                // Don't do this in handleHide() because it is also invoked by handleShow()
+                mNextView = null;
             }
         };
 
@@ -407,7 +409,6 @@
                 }
 
                 mView = null;
-                mNextView = null;
             }
         }
     }
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 08ce256..25d3aca 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -1341,7 +1341,9 @@
 
         <activity android:name="android.accounts.ChooseAccountActivity"
                 android:excludeFromRecents="true"
-                android:exported="true">
+                android:exported="true"
+                android:theme="@android:style/Theme.Holo.Dialog"
+                android:label="@string/choose_account_label">
         </activity>
 
         <activity android:name="android.accounts.GrantCredentialsPermissionActivity"
diff --git a/core/res/res/layout/choose_account.xml b/core/res/res/layout/choose_account.xml
new file mode 100644
index 0000000..c37a949
--- /dev/null
+++ b/core/res/res/layout/choose_account.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/* //device/apps/common/assets/res/layout/list_content.xml
+**
+** Copyright 2011, The Android Open Source Project
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+**     http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip">
+
+    <ListView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@android:id/list"
+        android:layout_width="match_parent"
+        android:layout_height="0dip"
+        android:layout_weight="1"
+        android:drawSelectorOnTop="false"
+        android:scrollbarAlwaysDrawVerticalTrack="true" />
+
+</LinearLayout>
diff --git a/core/res/res/layout/choose_account_row.xml b/core/res/res/layout/choose_account_row.xml
new file mode 100644
index 0000000..33764a3
--- /dev/null
+++ b/core/res/res/layout/choose_account_row.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+-->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:paddingLeft="16dip"
+    android:paddingRight="16dip"
+    android:orientation="horizontal" >
+
+   <ImageView android:id="@+id/account_row_icon"
+        android:layout_width="wrap_content"
+        android:layout_height="fill_parent"
+        android:paddingRight="8dip" />
+
+    <TextView xmlns:android="http://schemas.android.com/apk/res/android"
+        android:id="@+id/account_row_text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:gravity="center_vertical"
+        android:minHeight="?android:attr/listPreferredItemHeight" />
+
+</LinearLayout>
\ No newline at end of file
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 46e45db..496e254 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2684,4 +2684,7 @@
     <string name="vpn_notification_title_disconnected"><xliff:g id="profilename" example="Home PPTP">%s</xliff:g> VPN disconnected</string>
     <!-- Message of the VPN service notification: Hint to reconnect VPN [CHAR LIMIT=NONE] -->
     <string name="vpn_notification_hint_disconnected">Touch to reconnect to a VPN.</string>
+
+    <!-- Choose Account Activity label -->
+    <string name="choose_account_label">Select an account</string>
 </resources>
diff --git a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
index 3d5588c..fb8b5ce 100644
--- a/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
+++ b/core/tests/ConnectivityManagerTest/src/com/android/connectivitymanagertest/ConnectivityManagerTestActivity.java
@@ -78,7 +78,7 @@
     public int mWifiState;
     public NetworkInfo mWifiNetworkInfo;
     public String mBssid;
-    public String mPowerSsid = "GoogleGuest"; //Default power SSID
+    public String mPowerSsid = "opennet"; //Default power SSID
     private Context mContext;
     public boolean scanResultAvailable = false;
 
diff --git a/docs/html/guide/topics/graphics/animation.jd b/docs/html/guide/topics/graphics/animation.jd
index c977d51..83a4e1d 100644
--- a/docs/html/guide/topics/graphics/animation.jd
+++ b/docs/html/guide/topics/graphics/animation.jd
@@ -13,7 +13,7 @@
 
             <li><a href="#object-animator">Animating with ObjectAnimator</a></li>
 
-            <li><a href="#type-evaluator">Using the TypeEvaluator</a></li>
+            <li><a href="#type-evaluator">Using a TypeEvaluator</a></li>
 
             <li><a href="#interpolators">Using interpolators</a></li>
 
@@ -60,7 +60,7 @@
 
   <p>The Android system provides a flexible animation system that allows you to animate
   almost anything, either programmatically or declaratively with XML. There are two
-  animation systems that you can choose from: <a href="property-animation">property
+  animation systems that you can choose from: <a href="#property-animation">property
   animation</a> and <a href="#view-animation">view animation</a>. You can use whichever
   system that matches your needs, but use only one system for each object that you
   are animating.</p>
@@ -91,7 +91,7 @@
 
   <p>Most of the property animation system's features can be found in
   {@link android.animation android.animation}. Because the 
-  <a href="#view-animation>view animation</a> system already
+  <a href="#view-animation">view animation</a> system already
   defines many interpolators in {@link android.view.animation android.view.animation},
   you will use those to define your animation's interpolation in the property animation
   system as well.
@@ -163,7 +163,7 @@
       <p>The Android system provides a set of common interpolators in
       {@link android.view.animation android.view.animation}. If none of these suits your needs, you
       can implement the {@link android.animation.TimeInterpolator} interface and create
-      your own. See <a href="#interpolators">Interpolators</a> for more information on
+      your own. See <a href="#interpolators">Using interpolators</a> for more information on
       how to write a custom interpolator.</p>
     </dd>
   </dl>
@@ -286,14 +286,13 @@
   android.animation.AnimatorListenerAdapter} for just the {@link
   android.animation.Animator.AnimatorListener#onAnimationEnd onAnimationEnd()}
   callback:</p>
+  
   <pre>ValueAnimator fadeAnim = ObjectAnimator.ofFloat(newBall, "alpha", 1f, 0f);
 fadeAnim.setDuration(250);
 fadeAnim.addListener(new AnimatorListenerAdapter() {
 public void onAnimationEnd(Animator animation) {
     balls.remove(((ObjectAnimator)animation).getTarget());
-}
-  
-</pre>
+}</pre>
 
   <h3 id="object-animator">Animating with ObjectAnimator</h3>
 
@@ -308,11 +307,9 @@
   <p>Instantiating an {@link android.animation.ObjectAnimator} is similar to a {@link
   android.animation.ValueAnimator}, but you also specify the object and that object's
   property (as a String) that you want to animate:</p>
-  <pre>
-ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
+  <pre>ObjectAnimator anim = ObjectAnimator.ofFloat(foo, "alpha", 0f, 1f);
 anim.setDuration(1000);
-anim.start();
-</pre>
+anim.start();</pre>
 
   <p>To have the {@link android.animation.ObjectAnimator} update properties correctly,
   you must do the following:</p>
@@ -355,7 +352,7 @@
     </li>
   </ul>
 
-  <h3 id="type-evaluator">Using the TypeEvaluator</h3>
+  <h3 id="type-evaluator">Using a TypeEvaluator</h3>
 
   <p>If you want to animate a type that is unknown to the Android system,
   you can create your own evaluator by implementing the {@link
@@ -369,15 +366,13 @@
   This allows the animator that you are using to return an
   appropriate value for your animated property at the current point of the animation. The
   {@link android.animation.FloatEvaluator} class demonstrates how to do this:</p>
-  <pre>
-public class FloatEvaluator implements TypeEvaluator {
+  <pre>public class FloatEvaluator implements TypeEvaluator {
 
     public Object evaluate(float fraction, Object startValue, Object endValue) {
         float startFloat = ((Number) startValue).floatValue();
         return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);
     }
-}
-</pre>
+}</pre>
 
   <p class="note"><strong>Note:</strong> When {@link android.animation.ValueAnimator} (or
   {@link android.animation.ObjectAnimator}) runs, it calculates a current elapsed
@@ -387,7 +382,7 @@
   parameter, so you do not have to take into account the interpolator
   when calculating animated values.</p>
 
-  <h3 id="interpolators">Using Interpolators</h3>
+  <h3 id="interpolators">Using interpolators</h3>
 
   <p>An interpolator define how specific values in an animation are
   calculated as a function of time. For example, you can specify animations to happen
@@ -414,12 +409,12 @@
   <p><strong>AccelerateDecelerateInterpolator</strong></p>
   <pre>public float getInterpolation(float input) {
     return (float)(Math.cos((input + 1) * Math.PI) / 2.0f) + 0.5f;
-    }</pre>
+}</pre>
 
   <p><strong>LinearInterpolator</strong></p>
   <pre>public float getInterpolation(float input) {
     return input;
-    }</pre>
+}</pre>
 
   <p>The following table represents the approximate values that are calculated by these
   interpolators for an animation that lasts 1000ms:</p>
@@ -488,7 +483,7 @@
   {@link android.view.animation.LinearInterpolator} between 200ms and 600ms and slower
   between 600ms and 1000ms.</p>
 
-  <h3 id="keyframes">Specifying Keyframes</h3>
+  <h3 id="keyframes">Specifying keyframes</h3>
 
   <p>A {@link android.animation.Keyframe} object consists of a time/value pair that lets
   you define a specific state at a specific time of an animation. Each keyframe can also
@@ -505,19 +500,18 @@
   object, you can obtain an animator by passing in the {@link
   android.animation.PropertyValuesHolder} object and the object to animate. The following
   code snippet demonstrates how to do this:</p>
-  <pre>
-  Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
-  Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
-  Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
-  PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
-  ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
-  rotationAnim.setDuration(5000ms);
- 
-</pre>For a more complete example on how to use keyframes, see the <a href=
+  <pre>Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
+Keyframe kf1 = Keyframe.ofFloat(.9999f, 360f);
+Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
+PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
+ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
+rotationAnim.setDuration(5000ms);
+</pre>
+<p>For a more complete example on how to use keyframes, see the <a href=
 "{@docRoot}resources/samples/ApiDemos/src/com/example/android/apis/animation/MultiPropertyAnimation.html">
-  MultiPropertyAnimation</a> sample in APIDemos.
+  MultiPropertyAnimation</a> sample in APIDemos.</p>
 
-  <h3 id="choreography">Choreographing multiple animations with Animator Sets</h3>
+  <h3 id="choreography">Choreographing multiple animations with AnimatorSet</h3>
 
   <p>In many cases, you want to play an animation that depends on when another animation
   starts or finishes. The Android system lets you bundle animations together into an
@@ -559,7 +553,7 @@
 
   <h3 id="declaring-xml">Declaring animations in XML</h3>
 
-  <p>As with <a href="view-animation">view animation</a>, you can declare property animations with
+  <p>As with <a href="#view-animation">view animation</a>, you can declare property animations with
   XML instead of doing it programmatically. The following Android classes also have XML
   declaration support with the following XML tags:</p>
 
@@ -639,14 +633,13 @@
             android:propertyName="y"
             android:duration="500"
             android:valueTo="300"
-            android:valueType="int" &gt;
-        &lt;/set&gt;
-        &lt;objectAnimator
-            android:propertyName="alpha"
-            android:duration="500"
-            android:valueTo="0f"/&gt;
-        &lt;/set&gt;
-</pre>
+            android:valueType="int"/&gt;
+    &lt;/set&gt;
+    &lt;objectAnimator
+        android:propertyName="alpha"
+        android:duration="500"
+        android:valueTo="0f"/&gt;
+&lt;/set&gt;</pre>
 
   <p>In order to run this animation, you must inflate the XML resources in your code to
   an {@link android.animation.AnimatorSet} object, and then set the target objects for all of
@@ -698,40 +691,38 @@
 
   <p>The following XML from one of the ApiDemos is used to stretch, then simultaneously
   spin and rotate a View object.</p>
-  <pre>
-&lt;set android:shareInterpolator="false"&gt;
-   &lt;scale
-          android:interpolator="@android:anim/accelerate_decelerate_interpolator"
-          android:fromXScale="1.0"
-          android:toXScale="1.4"
-          android:fromYScale="1.0"
-          android:toYScale="0.6"
-          android:pivotX="50%"
-          android:pivotY="50%"
-          android:fillAfter="false"
-          android:duration="700" /&gt;
-   &lt;set android:interpolator="@android:anim/decelerate_interpolator"&gt;
-      &lt;scale
-             android:fromXScale="1.4" 
-             android:toXScale="0.0"
-             android:fromYScale="0.6"
-             android:toYScale="0.0" 
-             android:pivotX="50%" 
-             android:pivotY="50%" 
-             android:startOffset="700"
-             android:duration="400" 
-             android:fillBefore="false" /&gt;
-      &lt;rotate 
-             android:fromDegrees="0" 
-             android:toDegrees="-45"
-             android:toYScale="0.0" 
-             android:pivotX="50%" 
-             android:pivotY="50%"
-             android:startOffset="700"
-             android:duration="400" /&gt;
-   &lt;/set&gt;
-&lt;/set&gt;
-</pre>
+  <pre>&lt;set android:shareInterpolator="false"&gt;
+    &lt;scale
+        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
+        android:fromXScale="1.0"
+        android:toXScale="1.4"
+        android:fromYScale="1.0"
+        android:toYScale="0.6"
+        android:pivotX="50%"
+        android:pivotY="50%"
+        android:fillAfter="false"
+        android:duration="700" /&gt;
+    &lt;set android:interpolator="@android:anim/decelerate_interpolator"&gt;
+        &lt;scale
+           android:fromXScale="1.4"
+           android:toXScale="0.0"
+           android:fromYScale="0.6"
+           android:toYScale="0.0"
+           android:pivotX="50%"
+           android:pivotY="50%"
+           android:startOffset="700"
+           android:duration="400"
+           android:fillBefore="false" /&gt;
+        &lt;rotate
+           android:fromDegrees="0"
+           android:toDegrees="-45"
+           android:toYScale="0.0"
+           android:pivotX="50%"
+           android:pivotY="50%"
+           android:startOffset="700"
+           android:duration="400" /&gt;
+    &lt;/set&gt;
+&lt;/set&gt;</pre>
 
   <p>Screen coordinates (not used in this example) are (0,0) at the upper left hand
   corner, and increase as you go down and to the right.</p>
@@ -805,8 +796,7 @@
   image to a View and then called to play. Here's an example Activity, in which the
   animation is added to an {@link android.widget.ImageView} and then animated when the
   screen is touched:</p>
-  <pre>
-AnimationDrawable rocketAnimation;
+  <pre>AnimationDrawable rocketAnimation;
 
 public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
@@ -823,8 +813,7 @@
     return true;
   }
   return super.onTouchEvent(event);
-}
-</pre>
+}</pre>
 
   <p>It's important to note that the <code>start()</code> method called on the
   AnimationDrawable cannot be called during the <code>onCreate()</code> method of your
diff --git a/graphics/java/android/renderscript/Allocation.java b/graphics/java/android/renderscript/Allocation.java
index 74cdf80..3dcfe88 100644
--- a/graphics/java/android/renderscript/Allocation.java
+++ b/graphics/java/android/renderscript/Allocation.java
@@ -212,7 +212,7 @@
         for (int ct=0; ct < d.length; ct++) {
             i[ct] = d[ct].getID();
         }
-        copy1DRangeFrom(0, mType.getCount(), i);
+        copy1DRangeFromUnchecked(0, mType.getCount(), i);
     }
 
     private void validateBitmapFormat(Bitmap b) {
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index f8daa4f..3251c28 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -305,6 +305,8 @@
 
     void restorePatchedDataPointer(BufferInfo *info);
 
+    status_t applyRotation();
+
     OMXCodec(const OMXCodec &);
     OMXCodec &operator=(const OMXCodec &);
 };
diff --git a/media/jni/android_media_MediaMetadataRetriever.cpp b/media/jni/android_media_MediaMetadataRetriever.cpp
index ec88bb2..3d7dbf9 100644
--- a/media/jni/android_media_MediaMetadataRetriever.cpp
+++ b/media/jni/android_media_MediaMetadataRetriever.cpp
@@ -22,9 +22,6 @@
 #include <utils/Log.h>
 #include <utils/threads.h>
 #include <core/SkBitmap.h>
-#include <core/SkCanvas.h>
-#include <core/SkDevice.h>
-#include <core/SkScalar.h>
 #include <media/mediametadataretriever.h>
 #include <private/media/VideoFrame.h>
 
@@ -136,6 +133,61 @@
     process_media_retriever_call(env, retriever->setDataSource(fd, offset, length), "java/lang/RuntimeException", "setDataSource failed");
 }
 
+template<typename T>
+static void rotate0(T* dst, const T* src, size_t width, size_t height)
+{
+    memcpy(dst, src, width * height * sizeof(T));
+}
+
+template<typename T>
+static void rotate90(T* dst, const T* src, size_t width, size_t height)
+{
+    for (size_t i = 0; i < height; ++i) {
+        for (size_t j = 0; j < width; ++j) {
+            dst[j * height + height - 1 - i] = src[i * width + j];
+        }
+    }
+}
+
+template<typename T>
+static void rotate180(T* dst, const T* src, size_t width, size_t height)
+{
+    for (size_t i = 0; i < height; ++i) {
+        for (size_t j = 0; j < width; ++j) {
+            dst[(height - 1 - i) * width + width - 1 - j] = src[i * width + j];
+        }
+    }
+}
+
+template<typename T>
+static void rotate270(T* dst, const T* src, size_t width, size_t height)
+{
+    for (size_t i = 0; i < height; ++i) {
+        for (size_t j = 0; j < width; ++j) {
+            dst[(width - 1 - j) * height + i] = src[i * width + j];
+        }
+    }
+}
+
+template<typename T>
+static void rotate(T *dst, const T *src, size_t width, size_t height, int angle)
+{
+    switch (angle) {
+        case 0:
+            rotate0(dst, src, width, height);
+            break;
+        case 90:
+            rotate90(dst, src, width, height);
+            break;
+        case 180:
+            rotate180(dst, src, width, height);
+            break;
+        case 270:
+            rotate270(dst, src, width, height);
+            break;
+    }
+}
+
 static jobject android_media_MediaMetadataRetriever_getFrameAtTime(JNIEnv *env, jobject thiz, jlong timeUs, jint option)
 {
     LOGV("getFrameAtTime: %lld us option: %d", timeUs, option);
@@ -166,30 +218,33 @@
                         fields.createConfigMethod,
                         SkBitmap::kRGB_565_Config);
 
+    size_t width, height;
+    if (videoFrame->mRotationAngle == 90 || videoFrame->mRotationAngle == 270) {
+        width = videoFrame->mDisplayHeight;
+        height = videoFrame->mDisplayWidth;
+    } else {
+        width = videoFrame->mDisplayWidth;
+        height = videoFrame->mDisplayHeight;
+    }
+
     jobject jBitmap = env->CallStaticObjectMethod(
                             fields.bitmapClazz,
                             fields.createBitmapMethod,
-                            videoFrame->mDisplayWidth,
-                            videoFrame->mDisplayHeight,
+                            width,
+                            height,
                             config);
+
     SkBitmap *bitmap =
             (SkBitmap *) env->GetIntField(jBitmap, fields.nativeBitmap);
 
     bitmap->lockPixels();
-
-    memcpy((uint8_t*)bitmap->getPixels(),
-            (uint8_t*)videoFrame + sizeof(VideoFrame), videoFrame->mSize);
-
+    rotate((uint16_t*)bitmap->getPixels(),
+           (uint16_t*)((char*)videoFrame + sizeof(VideoFrame)),
+           videoFrame->mDisplayWidth,
+           videoFrame->mDisplayHeight,
+           videoFrame->mRotationAngle);
     bitmap->unlockPixels();
 
-    if (videoFrame->mRotationAngle != 0) {
-        SkDevice device(*bitmap);
-        SkCanvas canvas(&device);
-        canvas.rotate((SkScalar) (videoFrame->mRotationAngle * 1.0));
-        canvas.drawBitmap(*bitmap, 0, 0);
-    }
-
-    LOGV("Return a new bitmap constructed with the rotation matrix");
     return jBitmap;
 }
 
@@ -288,22 +343,6 @@
         jniThrowException(env, "java/lang/RuntimeException", "Can't find android/graphics/Bitmap");
         return;
     }
-#if USE_PRIVATE_NATIVE_BITMAP_CONSTUCTOR
-    fields.bitmapConstructor = env->GetMethodID(fields.bitmapClazz, "<init>", "(I[BZ[BI)V");
-    if (fields.bitmapConstructor == NULL) {
-        jniThrowException(env, "java/lang/RuntimeException", "Can't find Bitmap constructor");
-        return;
-    }
-    fields.createBitmapRotationMethod =
-            env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
-                    "(Landroid/graphics/Bitmap;IIIILandroid/graphics/Matrix;Z)"
-                    "Landroid/graphics/Bitmap;");
-    if (fields.createBitmapRotationMethod == NULL) {
-        jniThrowException(env, "java/lang/RuntimeException",
-                "Can't find Bitmap.createBitmap method");
-        return;
-    }
-#else
     fields.createBitmapMethod =
             env->GetStaticMethodID(fields.bitmapClazz, "createBitmap",
                     "(IILandroid/graphics/Bitmap$Config;)"
@@ -333,7 +372,6 @@
                 "Can't find Bitmap$Config.nativeToConfig(int)  method");
         return;
     }
-#endif
 }
 
 static void android_media_MediaMetadataRetriever_native_setup(JNIEnv *env, jobject thiz)
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 11ac56c..89b3dab 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -378,14 +378,11 @@
 }
 
 void AwesomePlayer::reset() {
-    LOGI("reset");
-
     Mutex::Autolock autoLock(mLock);
     reset_l();
 }
 
 void AwesomePlayer::reset_l() {
-    LOGI("reset_l");
     mDisplayWidth = 0;
     mDisplayHeight = 0;
 
@@ -411,10 +408,6 @@
         }
     }
 
-    if (mFlags & PREPARING) {
-        LOGI("waiting until preparation is completes.");
-    }
-
     while (mFlags & PREPARING) {
         mPreparedCondition.wait(mLock);
     }
@@ -438,8 +431,6 @@
     }
     mAudioSource.clear();
 
-    LOGI("audio source cleared");
-
     mTimeSource = NULL;
 
     delete mAudioPlayer;
@@ -480,8 +471,6 @@
         IPCThreadState::self()->flushCommands();
     }
 
-    LOGI("video source cleared");
-
     mDurationUs = -1;
     mFlags = 0;
     mExtractorFlags = 0;
@@ -498,8 +487,6 @@
     mFileSource.clear();
 
     mBitrate = -1;
-
-    LOGI("reset_l completed");
 }
 
 void AwesomePlayer::notifyListener_l(int msg, int ext1, int ext2) {
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index d842f65..94694a3 100644
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -1680,6 +1680,33 @@
     return OK;
 }
 
+status_t OMXCodec::applyRotation() {
+    sp<MetaData> meta = mSource->getFormat();
+
+    int32_t rotationDegrees;
+    if (!meta->findInt32(kKeyRotation, &rotationDegrees)) {
+        rotationDegrees = 0;
+    }
+
+    uint32_t transform;
+    switch (rotationDegrees) {
+        case 0: transform = 0; break;
+        case 90: transform = HAL_TRANSFORM_ROT_90; break;
+        case 180: transform = HAL_TRANSFORM_ROT_180; break;
+        case 270: transform = HAL_TRANSFORM_ROT_270; break;
+        default: transform = 0; break;
+    }
+
+    status_t err = OK;
+
+    if (transform) {
+        err = native_window_set_buffers_transform(
+                mNativeWindow.get(), transform);
+    }
+
+    return err;
+}
+
 status_t OMXCodec::allocateOutputBuffersFromNativeWindow() {
     // Get the number of buffers needed.
     OMX_PARAM_PORTDEFINITIONTYPE def;
@@ -1713,6 +1740,11 @@
         return err;
     }
 
+    err = applyRotation();
+    if (err != OK) {
+        return err;
+    }
+
     // Set up the native window.
     // XXX TODO: Get the gralloc usage flags from the OMX plugin!
     err = native_window_set_usage(
diff --git a/packages/SettingsProvider/res/values/defaults.xml b/packages/SettingsProvider/res/values/defaults.xml
index 5981139..27c8aea 100644
--- a/packages/SettingsProvider/res/values/defaults.xml
+++ b/packages/SettingsProvider/res/values/defaults.xml
@@ -71,6 +71,9 @@
     <string name="def_lock_sound" translatable="false">/system/media/audio/ui/Lock.ogg</string>
     <string name="def_unlock_sound" translatable="false">/system/media/audio/ui/Unlock.ogg</string>
 
+    <!-- Notifications use ringer volume -->
+    <bool name="def_notifications_use_ring_volume">true</bool>
+
     <!-- Default for Settings.System.VIBRATE_IN_SILENT -->
     <bool name="def_vibrate_in_silent">true</bool>
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
index bc7473e..580113c 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/DatabaseHelper.java
@@ -1168,6 +1168,11 @@
 
             loadBooleanSetting(stmt, Settings.System.USE_PTP_INTERFACE,
                     R.bool.def_use_ptp_interface);
+
+            // Set notification volume to follow ringer volume by default
+            loadBooleanSetting(stmt, Settings.System.NOTIFICATIONS_USE_RING_VOLUME,
+                    R.bool.def_notifications_use_ring_volume);
+
         } finally {
             if (stmt != null) stmt.close();
         }
diff --git a/services/java/com/android/server/ScreenRotationAnimation.java b/services/java/com/android/server/ScreenRotationAnimation.java
index 2ad9cbe..bef64b3 100644
--- a/services/java/com/android/server/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/ScreenRotationAnimation.java
@@ -23,6 +23,8 @@
 import android.graphics.Matrix;
 import android.graphics.Paint;
 import android.graphics.PixelFormat;
+import android.graphics.PorterDuff;
+import android.graphics.PorterDuffXfermode;
 import android.graphics.Rect;
 import android.util.DisplayMetrics;
 import android.util.Slog;
@@ -132,9 +134,11 @@
                 }
         
                 if (screenshot != null) {
-                    c.drawBitmap(screenshot, 0, 0, new Paint(0));
+                    Paint paint = new Paint(0);
+                    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
+                    c.drawBitmap(screenshot, 0, 0, paint);
                 } else {
-                    c.drawColor(Color.GREEN);
+                    c.drawColor(Color.GREEN, PorterDuff.Mode.SRC);
                 }
 
                 mSurface.unlockCanvasAndPost(c);
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index 2af291d..d2a1786 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -680,6 +680,7 @@
 
             // stop intercepting input
             mDragState.unregister();
+            mInputMonitor.setUpdateInputWindowsNeededLw();
             mInputMonitor.updateInputWindowsLw();
 
             // Retain the parameters of any deferred rotation operation so
@@ -2401,7 +2402,8 @@
 
             boolean focusChanged = false;
             if (win.canReceiveKeys()) {
-                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS);
+                focusChanged = updateFocusedWindowLocked(UPDATE_FOCUS_WILL_ASSIGN_LAYERS,
+                        false /*updateInputWindows*/);
                 if (focusChanged) {
                     imMayMove = false;
                 }
@@ -2418,9 +2420,10 @@
             //dump();
 
             if (focusChanged) {
-                finishUpdateFocusedWindowAfterAssignLayersLocked();
+                finishUpdateFocusedWindowAfterAssignLayersLocked(false /*updateInputWindows*/);
             }
-            
+            mInputMonitor.updateInputWindowsLw();
+
             if (localLOGV) Slog.v(
                 TAG, "New client " + client.asBinder()
                 + ": window=" + win);
@@ -2496,8 +2499,10 @@
                 win.mExiting = true;
                 win.mRemoveOnExit = true;
                 mLayoutNeeded = true;
-                updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+                updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                        false /*updateInputWindows*/);
                 performLayoutAndPlaceSurfacesLocked();
+                mInputMonitor.updateInputWindowsLw();
                 if (win.mAppToken != null) {
                     win.mAppToken.updateReportedVisibilityLocked();
                 }
@@ -2515,7 +2520,7 @@
                 && updateOrientationFromAppTokensLocked(false)) {
             mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
         }
-        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
         Binder.restoreCallingIdentity(origId);
     }
 
@@ -2613,6 +2618,7 @@
             }
         }
         
+        mInputMonitor.setUpdateInputWindowsNeededLw();
         mInputMonitor.updateInputWindowsLw();
     }
 
@@ -2863,6 +2869,7 @@
                         outSurface.release();
                     }
                 } catch (Exception e) {
+                    mInputMonitor.setUpdateInputWindowsNeededLw();
                     mInputMonitor.updateInputWindowsLw();
                     
                     Slog.w(TAG, "Exception thrown when creating surface for client "
@@ -2950,7 +2957,8 @@
 
             if (focusMayChange) {
                 //System.out.println("Focus may change: " + win.mAttrs.getTitle());
-                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
+                if (updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                        false /*updateInputWindows*/)) {
                     imMayMove = false;
                 }
                 //System.out.println("Relayout " + win + ": focus=" + mCurrentFocus);
@@ -3006,6 +3014,7 @@
 
             inTouchMode = mInTouchMode;
             
+            mInputMonitor.setUpdateInputWindowsNeededLw();
             mInputMonitor.updateInputWindowsLw();
         }
 
@@ -3378,7 +3387,8 @@
                     if (changed) {
                         mLayoutNeeded = true;
                         performLayoutAndPlaceSurfacesLocked();
-                        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+                        updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL,
+                                false /*updateInputWindows*/);
                     }
 
                     if (delayed) {
@@ -3388,6 +3398,7 @@
                     }
                 }
 
+                mInputMonitor.setUpdateInputWindowsNeededLw();
                 mInputMonitor.updateInputWindowsLw();
             } else {
                 Slog.w(TAG, "Attempted to remove non-existing token: " + token);
@@ -3707,7 +3718,7 @@
 
             if (moveFocusNow && changed) {
                 final long origId = Binder.clearCallingIdentity();
-                updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+                updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
                 Binder.restoreCallingIdentity(origId);
             }
         }
@@ -3882,7 +3893,8 @@
                             ttoken.updateLayers();
                         }
 
-                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+                        updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                                true /*updateInputWindows*/);
                         mLayoutNeeded = true;
                         performLayoutAndPlaceSurfacesLocked();
                         Binder.restoreCallingIdentity(origId);
@@ -4042,12 +4054,13 @@
 
             if (changed) {
                 mLayoutNeeded = true;
+                mInputMonitor.setUpdateInputWindowsNeededLw();
                 if (performLayout) {
-                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                            false /*updateInputWindows*/);
                     performLayoutAndPlaceSurfacesLocked();
-                } else {
-                    mInputMonitor.updateInputWindowsLw();
                 }
+                mInputMonitor.updateInputWindowsLw();
             }
         }
 
@@ -4302,7 +4315,7 @@
                 if (mFocusedApp == wtoken) {
                     if (DEBUG_FOCUS) Slog.v(TAG, "Removing focused app token:" + wtoken);
                     mFocusedApp = null;
-                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL);
+                    updateFocusedWindowLocked(UPDATE_FOCUS_NORMAL, true /*updateInputWindows*/);
                     mInputMonitor.setFocusedAppLw(null);
                 }
             } else {
@@ -4481,9 +4494,11 @@
                 reAddAppWindowsLocked(findWindowOffsetLocked(index), wtoken);
                 if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
                 if (DEBUG_REORDER) dumpWindowsLocked();
-                updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+                updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                        false /*updateInputWindows*/);
                 mLayoutNeeded = true;
                 performLayoutAndPlaceSurfacesLocked();
+                mInputMonitor.updateInputWindowsLw();
             }
             Binder.restoreCallingIdentity(origId);
         }
@@ -4520,11 +4535,13 @@
         pos = reAddAppWindowsLocked(pos, wtoken);
 
         if (updateFocusAndLayout) {
-            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
+            if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/)) {
                 assignLayersLocked();
             }
             mLayoutNeeded = true;
             performLayoutAndPlaceSurfacesLocked();
+            mInputMonitor.updateInputWindowsLw();
         }
     }
 
@@ -4550,11 +4567,13 @@
             }
         }
 
-        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES)) {
+        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                false /*updateInputWindows*/)) {
             assignLayersLocked();
         }
         mLayoutNeeded = true;
         performLayoutAndPlaceSurfacesLocked();
+        mInputMonitor.updateInputWindowsLw();
 
         //dump();
     }
@@ -5797,6 +5816,9 @@
         // When true, input dispatch proceeds normally.  Otherwise all events are dropped.
         private boolean mInputDispatchEnabled = true;
 
+        // When true, need to call updateInputWindowsLw().
+        private boolean mUpdateInputWindowsNeeded = true;
+
         // Temporary list of windows information to provide to the input dispatcher.
         private InputWindowList mTempInputWindows = new InputWindowList();
         
@@ -5891,8 +5913,17 @@
             inputWindow.touchableRegion.setEmpty();
         }
 
+        public void setUpdateInputWindowsNeededLw() {
+            mUpdateInputWindowsNeeded = true;
+        }
+
         /* Updates the cached window information provided to the input dispatcher. */
         public void updateInputWindowsLw() {
+            if (!mUpdateInputWindowsNeeded) {
+                return;
+            }
+            mUpdateInputWindowsNeeded = false;
+
             // Populate the input window list with information about all of the windows that
             // could potentially receive input.
             // As an optimization, we could try to prune the list of windows but this turns
@@ -6021,7 +6052,7 @@
         /* Called when the current input focus changes.
          * Layer assignment is assumed to be complete by the time this is called.
          */
-        public void setInputFocusLw(WindowState newWindow) {
+        public void setInputFocusLw(WindowState newWindow, boolean updateInputWindows) {
             if (DEBUG_INPUT) {
                 Slog.d(TAG, "Input focus has changed to " + newWindow);
             }
@@ -6033,9 +6064,13 @@
                     // forgets to resume.
                     newWindow.mToken.paused = false;
                 }
-            
+
                 mInputFocus = newWindow;
-                updateInputWindowsLw();
+                setUpdateInputWindowsNeededLw();
+
+                if (updateInputWindows) {
+                    updateInputWindowsLw();
+                }
             }
         }
         
@@ -6062,6 +6097,7 @@
                 }
                 
                 window.paused = true;
+                setUpdateInputWindowsNeededLw();
                 updateInputWindowsLw();
             }
         }
@@ -6073,6 +6109,7 @@
                 }
                 
                 window.paused = false;
+                setUpdateInputWindowsNeededLw();
                 updateInputWindowsLw();
             }
         }
@@ -6549,12 +6586,14 @@
                 // the actual drag event dispatch stuff in the dragstate
 
                 mDragState.register();
+                mInputMonitor.setUpdateInputWindowsNeededLw();
                 mInputMonitor.updateInputWindowsLw();
                 if (!mInputManager.transferTouchFocus(callingWin.mInputChannel,
                         mDragState.mServerChannel)) {
                     Slog.e(TAG, "Unable to transfer touch focus");
                     mDragState.unregister();
                     mDragState = null;
+                    mInputMonitor.setUpdateInputWindowsNeededLw();
                     mInputMonitor.updateInputWindowsLw();
                     return false;
                 }
@@ -9151,6 +9190,7 @@
                         // !!! TODO: ANR the app that has failed to start the drag in time
                         if (mDragState != null) {
                             mDragState.unregister();
+                            mInputMonitor.setUpdateInputWindowsNeededLw();
                             mInputMonitor.updateInputWindowsLw();
                             mDragState.reset();
                             mDragState = null;
@@ -9441,7 +9481,7 @@
         }
     }
 
-    private final int performLayoutLockedInner(boolean initial) {
+    private final int performLayoutLockedInner(boolean initial, boolean updateInputWindows) {
         if (!mLayoutNeeded) {
             return 0;
         }
@@ -9549,7 +9589,10 @@
         }
         
         // Window frames may have changed.  Tell the input dispatcher about it.
-        mInputMonitor.updateInputWindowsLw();
+        mInputMonitor.setUpdateInputWindowsNeededLw();
+        if (updateInputWindows) {
+            mInputMonitor.updateInputWindowsLw();
+        }
 
         return mPolicy.finishLayoutLw();
     }
@@ -9570,7 +9613,8 @@
 
         if (mFocusMayChange) {
             mFocusMayChange = false;
-            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES);
+            updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
+                    false /*updateInputWindows*/);
         }
         
         // Initialize state of exiting tokens.
@@ -9646,7 +9690,7 @@
                 
                 // FIRST LOOP: Perform a layout, if needed.
                 if (repeats < 4) {
-                    changes = performLayoutLockedInner(repeats == 0);
+                    changes = performLayoutLockedInner(repeats == 0, false /*updateInputWindows*/);
                     if (changes != 0) {
                         continue;
                     }
@@ -10103,7 +10147,8 @@
                         if (!moveInputMethodWindowsIfNeededLocked(true)) {
                             assignLayersLocked();
                         }
-                        updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES);
+                        updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+                                false /*updateInputWindows*/);
                         mFocusMayChange = false;
                     }
                 }
@@ -10212,7 +10257,8 @@
 
                 if (mFocusMayChange) {
                     mFocusMayChange = false;
-                    if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES)) {
+                    if (updateFocusedWindowLocked(UPDATE_FOCUS_PLACING_SURFACES,
+                            false /*updateInputWindows*/)) {
                         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_ANIM;
                         adjResult = 0;
                     }
@@ -10224,8 +10270,6 @@
 
                 if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** ANIM STEP: changes=0x"
                         + Integer.toHexString(changes));
-                
-                mInputMonitor.updateInputWindowsLw();
             } while (changes != 0);
 
             // THIRD LOOP: Update the surfaces of all windows.
@@ -10679,8 +10723,6 @@
             Slog.e(TAG, "Unhandled exception in Window Manager", e);
         }
 
-        mInputMonitor.updateInputWindowsLw();
-        
         Surface.closeTransaction();
 
         if (SHOW_TRANSACTIONS) Slog.i(TAG, "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
@@ -10810,6 +10852,8 @@
             requestAnimationLocked(currentTime+(1000/60)-SystemClock.uptimeMillis());
         }
 
+        // Finally update all input windows now that the window changes have stabilized.
+        mInputMonitor.setUpdateInputWindowsNeededLw();
         mInputMonitor.updateInputWindowsLw();
 
         setHoldScreenLocked(holdScreen != null);
@@ -10988,7 +11032,7 @@
         }
     }
 
-    private boolean updateFocusedWindowLocked(int mode) {
+    private boolean updateFocusedWindowLocked(int mode, boolean updateInputWindows) {
         WindowState newFocus = computeFocusedWindowLocked();
         if (mCurrentFocus != newFocus) {
             // This check makes sure that we don't already have the focus
@@ -11009,7 +11053,7 @@
                     mLayoutNeeded = true;
                 }
                 if (mode == UPDATE_FOCUS_PLACING_SURFACES) {
-                    performLayoutLockedInner(true);
+                    performLayoutLockedInner(true /*initial*/, updateInputWindows);
                 } else if (mode == UPDATE_FOCUS_WILL_PLACE_SURFACES) {
                     // Client will do the layout, but we need to assign layers
                     // for handleNewWindowLocked() below.
@@ -11020,15 +11064,15 @@
             if (mode != UPDATE_FOCUS_WILL_ASSIGN_LAYERS) {
                 // If we defer assigning layers, then the caller is responsible for
                 // doing this part.
-                finishUpdateFocusedWindowAfterAssignLayersLocked();
+                finishUpdateFocusedWindowAfterAssignLayersLocked(updateInputWindows);
             }
             return true;
         }
         return false;
     }
     
-    private void finishUpdateFocusedWindowAfterAssignLayersLocked() {
-        mInputMonitor.setInputFocusLw(mCurrentFocus);
+    private void finishUpdateFocusedWindowAfterAssignLayersLocked(boolean updateInputWindows) {
+        mInputMonitor.setInputFocusLw(mCurrentFocus, updateInputWindows);
     }
 
     private WindowState computeFocusedWindowLocked() {