Merge "VpnDialogs: add string description for translation."
diff --git a/api/current.txt b/api/current.txt
index 5efa32f..ce78f9e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -11369,13 +11369,13 @@
     method public static boolean isEffectSupported(java.lang.String);
     field public static final java.lang.String EFFECT_AUTOFIX = "android.media.effect.effects.AutoFixEffect";
     field public static final java.lang.String EFFECT_BACKDROPPER = "android.media.effect.effects.BackDropperEffect";
+    field public static final java.lang.String EFFECT_BITMAPOVERLAY = "android.media.effect.effects.BitmapOverlayEffect";
     field public static final java.lang.String EFFECT_BLACKWHITE = "android.media.effect.effects.BlackWhiteEffect";
     field public static final java.lang.String EFFECT_BRIGHTNESS = "android.media.effect.effects.BrightnessEffect";
     field public static final java.lang.String EFFECT_CONTRAST = "android.media.effect.effects.ContrastEffect";
     field public static final java.lang.String EFFECT_CROP = "android.media.effect.effects.CropEffect";
     field public static final java.lang.String EFFECT_CROSSPROCESS = "android.media.effect.effects.CrossProcessEffect";
     field public static final java.lang.String EFFECT_DOCUMENTARY = "android.media.effect.effects.DocumentaryEffect";
-    field public static final java.lang.String EFFECT_DOODLE = "android.media.effect.effects.DoodleEffect";
     field public static final java.lang.String EFFECT_DUOTONE = "android.media.effect.effects.DuotoneEffect";
     field public static final java.lang.String EFFECT_FILLLIGHT = "android.media.effect.effects.FillLightEffect";
     field public static final java.lang.String EFFECT_FISHEYE = "android.media.effect.effects.FisheyeEffect";
@@ -22920,7 +22920,7 @@
     method public android.view.View findFocus();
     method public final android.view.View findViewById(int);
     method public final android.view.View findViewWithTag(java.lang.Object);
-    method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence);
+    method public void findViewsWithText(java.util.ArrayList<android.view.View>, java.lang.CharSequence, int);
     method protected boolean fitSystemWindows(android.graphics.Rect);
     method public boolean fitsSystemWindows();
     method public android.view.View focusSearch(int);
@@ -23249,6 +23249,8 @@
     field protected static final int[] ENABLED_SELECTED_WINDOW_FOCUSED_STATE_SET;
     field protected static final int[] ENABLED_STATE_SET;
     field protected static final int[] ENABLED_WINDOW_FOCUSED_STATE_SET;
+    field public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 2; // 0x2
+    field public static final int FIND_VIEWS_WITH_TEXT = 1; // 0x1
     field public static final int FOCUSABLES_ALL = 0; // 0x0
     field public static final int FOCUSABLES_TOUCH_MODE = 1; // 0x1
     field protected static final int[] FOCUSED_SELECTED_STATE_SET;
diff --git a/core/java/android/hardware/SensorManager.java b/core/java/android/hardware/SensorManager.java
index 2111cce..aeb5d92 100644
--- a/core/java/android/hardware/SensorManager.java
+++ b/core/java/android/hardware/SensorManager.java
@@ -1090,7 +1090,7 @@
                 delay = 20000;
                 break;
             case SENSOR_DELAY_UI:
-                delay = 60000;
+                delay = 66667;
                 break;
             case SENSOR_DELAY_NORMAL:
                 delay = 200000;
diff --git a/core/java/android/inputmethodservice/ExtractEditLayout.java b/core/java/android/inputmethodservice/ExtractEditLayout.java
index 25c0c99..220214b 100644
--- a/core/java/android/inputmethodservice/ExtractEditLayout.java
+++ b/core/java/android/inputmethodservice/ExtractEditLayout.java
@@ -16,6 +16,9 @@
 
 package android.inputmethodservice;
 
+import com.android.internal.view.menu.MenuBuilder;
+import com.android.internal.view.menu.MenuPopupHelper;
+
 import android.content.Context;
 import android.util.AttributeSet;
 import android.view.ActionMode;
@@ -23,12 +26,10 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.Button;
 import android.widget.LinearLayout;
 
-import com.android.internal.view.menu.MenuBuilder;
-import com.android.internal.view.menu.MenuPopupHelper;
-
 /**
  * ExtractEditLayout provides an ActionMode presentation for the
  * limited screen real estate in extract mode.
@@ -56,6 +57,7 @@
             mExtractActionButton.setVisibility(INVISIBLE);
             mEditButton.setVisibility(VISIBLE);
             mActionMode = mode;
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
             return mode;
         }
         return null;
@@ -158,6 +160,8 @@
             mExtractActionButton.setVisibility(VISIBLE);
             mEditButton.setVisibility(INVISIBLE);
 
+            sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
+
             mActionMode = null;
         }
 
diff --git a/core/java/android/inputmethodservice/InputMethodService.java b/core/java/android/inputmethodservice/InputMethodService.java
index d2effff..60188ea 100644
--- a/core/java/android/inputmethodservice/InputMethodService.java
+++ b/core/java/android/inputmethodservice/InputMethodService.java
@@ -687,6 +687,7 @@
         super.onDestroy();
         mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(
                 mInsetsComputer);
+        finishViews();
         if (mWindowAdded) {
             // Disable exit animation for the current IME window
             // to avoid the race condition between the exit and enter animations
@@ -695,7 +696,7 @@
             mWindow.dismiss();
         }
     }
-    
+
     /**
      * Take care of handling configuration changes.  Subclasses of
      * InputMethodService generally don't need to deal directly with
@@ -1436,7 +1437,7 @@
         }
     }
 
-    public void hideWindow() {
+    private void finishViews() {
         if (mInputViewStarted) {
             if (DEBUG) Log.v(TAG, "CALL: onFinishInputView");
             onFinishInputView(false);
@@ -1446,6 +1447,10 @@
         }
         mInputViewStarted = false;
         mCandidatesViewStarted = false;
+    }
+
+    public void hideWindow() {
+        finishViews();
         mImm.setImeWindowStatus(mToken, 0, mBackDisposition);
         if (mWindowVisible) {
             mWindow.hide();
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index bc5994e..e5882fc 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4031,6 +4031,8 @@
         public static final String NETSTATS_UID_MAX_HISTORY = "netstats_uid_max_history";
         /** {@hide} */
         public static final String NETSTATS_TAG_MAX_HISTORY = "netstats_tag_max_history";
+        /** {@hide} */
+        public static final String NETSTATS_FORCE_COMPLETE_POLL = "netstats_force_complete_poll";
 
         /** Preferred NTP server. {@hide} */
         public static final String NTP_SERVER = "ntp_server";
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 85e990aa..3bd0f76 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -30,7 +30,7 @@
  */
 public class Display {
     static final String TAG = "Display";
-    static final boolean DEBUG_COMPAT = false;
+    static final boolean DEBUG_DISPLAY_SIZE = false;
 
     /**
      * The default Display id.
@@ -117,7 +117,8 @@
                 outSize.x = getRawWidth();
                 outSize.y = getRawHeight();
             }
-            if (DEBUG_COMPAT && doCompat) Slog.v(TAG, "Returning display size: " + outSize);
+            if (DEBUG_DISPLAY_SIZE && doCompat) Slog.v(
+                    TAG, "Returning display size: " + outSize);
         } catch (RemoteException e) {
             Slog.w("Display", "Unable to get display size", e);
         }
@@ -203,6 +204,8 @@
                 outSize.x = getRawWidth();
                 outSize.y = getRawHeight();
             }
+            if (DEBUG_DISPLAY_SIZE) Slog.v(
+                    TAG, "Returning real display size: " + outSize);
         } catch (RemoteException e) {
             Slog.w("Display", "Unable to get real display size", e);
         }
@@ -215,7 +218,13 @@
      * </p>
      * @hide
      */
-    native public int getRawWidth();
+    public int getRawWidth() {
+        int w = getRawWidthNative();
+        if (DEBUG_DISPLAY_SIZE) Slog.v(
+                TAG, "Returning raw display width: " + w);
+        return w;
+    }
+    private native int getRawWidthNative();
 
     /**
      * Gets the raw height of the display, in pixels.
@@ -224,7 +233,13 @@
      * </p>
      * @hide
      */
-    native public int getRawHeight();
+    public int getRawHeight() {
+        int h = getRawHeightNative();
+        if (DEBUG_DISPLAY_SIZE) Slog.v(
+                TAG, "Returning raw display height: " + h);
+        return h;
+    }
+    private native int getRawHeightNative();
     
     /**
      * Returns the rotation of the screen from its "natural" orientation.
@@ -293,8 +308,9 @@
             ci.applyToDisplayMetrics(outMetrics);
         }
 
-        if (DEBUG_COMPAT) Slog.v(TAG, "Returning DisplayMetrics: " + outMetrics.widthPixels
-                + "x" + outMetrics.heightPixels + " " + outMetrics.density);
+        if (DEBUG_DISPLAY_SIZE) Slog.v(TAG, "Returning DisplayMetrics: "
+                + outMetrics.widthPixels + "x" + outMetrics.heightPixels
+                + " " + outMetrics.density);
     }
 
     /**
diff --git a/core/java/android/view/VelocityTracker.java b/core/java/android/view/VelocityTracker.java
index 5a91d31..dfb2c32 100644
--- a/core/java/android/view/VelocityTracker.java
+++ b/core/java/android/view/VelocityTracker.java
@@ -59,6 +59,8 @@
     private static native void nativeComputeCurrentVelocity(int ptr, int units, float maxVelocity);
     private static native float nativeGetXVelocity(int ptr, int id);
     private static native float nativeGetYVelocity(int ptr, int id);
+    private static native boolean nativeGetEstimator(int ptr, int id,
+            int degree, int horizonMillis, Estimator outEstimator);
 
     /**
      * Retrieve a new VelocityTracker object to watch the velocity of a
@@ -215,4 +217,94 @@
     public float getYVelocity(int id) {
         return nativeGetYVelocity(mPtr, id);
     }
+
+    /**
+     * Get an estimator for the movements of a pointer using past movements of the
+     * pointer to predict future movements.
+     *
+     * It is not necessary to call {@link #computeCurrentVelocity(int)} before calling
+     * this method.
+     *
+     * @param id Which pointer's velocity to return.
+     * @param degree The desired polynomial degree.  The actual estimator may have
+     * a lower degree than what is requested here.  If -1, uses the default degree.
+     * @param horizonMillis The maximum age of the oldest sample to consider, in milliseconds.
+     * If -1, uses the default horizon.
+     * @param outEstimator The estimator to populate.
+     * @return True if an estimator was obtained, false if there is no information
+     * available about the pointer.
+     *
+     * @hide For internal use only.  Not a final API.
+     */
+    public boolean getEstimator(int id, int degree, int horizonMillis, Estimator outEstimator) {
+        if (outEstimator == null) {
+            throw new IllegalArgumentException("outEstimator must not be null");
+        }
+        return nativeGetEstimator(mPtr, id, degree, horizonMillis, outEstimator);
+    }
+
+    /**
+     * An estimator for the movements of a pointer based on a polynomial model.
+     *
+     * The last recorded position of the pointer is at time zero seconds.
+     * Past estimated positions are at negative times and future estimated positions
+     * are at positive times.
+     *
+     * First coefficient is position (in pixels), second is velocity (in pixels per second),
+     * third is acceleration (in pixels per second squared).
+     *
+     * @hide For internal use only.  Not a final API.
+     */
+    public static final class Estimator {
+        // Must match VelocityTracker::Estimator::MAX_DEGREE
+        private static final int MAX_DEGREE = 2;
+
+        /**
+         * Polynomial coefficients describing motion in X.
+         */
+        public final float[] xCoeff = new float[MAX_DEGREE + 1];
+
+        /**
+         * Polynomial coefficients describing motion in Y.
+         */
+        public final float[] yCoeff = new float[MAX_DEGREE + 1];
+
+        /**
+         * Polynomial degree, or zero if only position information is available.
+         */
+        public int degree;
+
+        /**
+         * Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
+         */
+        public float confidence;
+
+        /**
+         * Gets an estimate of the X position of the pointer at the specified time point.
+         * @param time The time point in seconds, 0 is the last recorded time.
+         * @return The estimated X coordinate.
+         */
+        public float estimateX(float time) {
+            return estimate(time, xCoeff);
+        }
+
+        /**
+         * Gets an estimate of the Y position of the pointer at the specified time point.
+         * @param time The time point in seconds, 0 is the last recorded time.
+         * @return The estimated Y coordinate.
+         */
+        public float estimateY(float time) {
+            return estimate(time, yCoeff);
+        }
+
+        private float estimate(float time, float[] c) {
+            float a = 0;
+            float scale = 1;
+            for (int i = 0; i <= degree; i++) {
+                a += c[i] * scale;
+                scale *= time;
+            }
+            return a;
+        }
+    }
 }
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 65e9857..ca06b9c 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -45,6 +45,7 @@
 import android.os.Parcelable;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.FloatProperty;
 import android.util.LocaleUtil;
@@ -1928,6 +1929,20 @@
     public static final int PUBLIC_STATUS_BAR_VISIBILITY_MASK = 0x0000FFFF;
 
     /**
+     * Find views that render the specified text.
+     *
+     * @see #findViewsWithText(ArrayList, CharSequence, int)
+     */
+    public static final int FIND_VIEWS_WITH_TEXT = 0x00000001;
+
+    /**
+     * Find find views that contain the specified content description.
+     *
+     * @see #findViewsWithText(ArrayList, CharSequence, int)
+     */
+    public static final int FIND_VIEWS_WITH_CONTENT_DESCRIPTION = 0x00000002;
+
+    /**
      * Controls the over-scroll mode for this view.
      * See {@link #overScrollBy(int, int, int, int, int, int, int, int, boolean)},
      * {@link #OVER_SCROLL_ALWAYS}, {@link #OVER_SCROLL_IF_CONTENT_SCROLLS},
@@ -5132,12 +5147,28 @@
 
     /**
      * Finds the Views that contain given text. The containment is case insensitive.
-     * As View's text is considered any text content that View renders.
+     * The search is performed by either the text that the View renders or the content
+     * description that describes the view for accessibility purposes and the view does
+     * not render or both. Clients can specify how the search is to be performed via
+     * passing the {@link #FIND_VIEWS_WITH_TEXT} and
+     * {@link #FIND_VIEWS_WITH_CONTENT_DESCRIPTION} flags.
      *
      * @param outViews The output list of matching Views.
-     * @param text The text to match against.
+     * @param searched The text to match against.
+     * 
+     * @see #FIND_VIEWS_WITH_TEXT
+     * @see #FIND_VIEWS_WITH_CONTENT_DESCRIPTION
+     * @see #setContentDescription(CharSequence)
      */
-    public void findViewsWithText(ArrayList<View> outViews, CharSequence text) {
+    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
+        if ((flags & FIND_VIEWS_WITH_CONTENT_DESCRIPTION) != 0 && !TextUtils.isEmpty(searched)
+                && !TextUtils.isEmpty(mContentDescription)) {
+            String searchedLowerCase = searched.toString().toLowerCase();
+            String contentDescriptionLowerCase = mContentDescription.toString().toLowerCase();
+            if (contentDescriptionLowerCase.contains(searchedLowerCase)) {
+                outViews.add(this);
+            }
+        }
     }
 
     /**
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 1bd0782..c7b59b8 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -802,13 +802,15 @@
     }
 
     @Override
-    public void findViewsWithText(ArrayList<View> outViews, CharSequence text) {
+    public void findViewsWithText(ArrayList<View> outViews, CharSequence text, int flags) {
+        super.findViewsWithText(outViews, text, flags);
         final int childrenCount = mChildrenCount;
         final View[] children = mChildren;
         for (int i = 0; i < childrenCount; i++) {
             View child = children[i];
-            if ((child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
-                child.findViewsWithText(outViews, text);
+            if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
+                    && (child.mPrivateFlags & IS_ROOT_NAMESPACE) == 0) {
+                child.findViewsWithText(outViews, text, flags);
             }
         }
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 81f9d78..4611984 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -4661,7 +4661,8 @@
                     return;
                 }
 
-                root.findViewsWithText(foundViews, text);
+                root.findViewsWithText(foundViews, text, View.FIND_VIEWS_WITH_TEXT
+                        | View.FIND_VIEWS_WITH_CONTENT_DESCRIPTION);
                 if (foundViews.isEmpty()) {
                     return;
                 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index dc1bbd7..980e454 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -478,14 +478,14 @@
      * decorations that can never be removed.  That is, system bar or
      * button bar.
      */
-    public int getNonDecorDisplayWidth(int rotation, int fullWidth);
+    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation);
 
     /**
      * Return the display height available after excluding any screen
      * decorations that can never be removed.  That is, system bar or
      * button bar.
      */
-    public int getNonDecorDisplayHeight(int rotation, int fullHeight);
+    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation);
 
     /**
      * Return the available screen width that we should report for the
@@ -493,7 +493,7 @@
      * {@link #getNonDecorDisplayWidth(int, int)}; it may be smaller than
      * that to account for more transient decoration like a status bar.
      */
-    public int getConfigDisplayWidth(int rotation, int fullWidth);
+    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation);
 
     /**
      * Return the available screen height that we should report for the
@@ -501,7 +501,7 @@
      * {@link #getNonDecorDisplayHeight(int, int)}; it may be smaller than
      * that to account for more transient decoration like a status bar.
      */
-    public int getConfigDisplayHeight(int rotation, int fullHeight);
+    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation);
 
     /**
      * Return whether the given window should forcibly hide everything
@@ -671,8 +671,10 @@
      * 
      * @param displayWidth The current full width of the screen.
      * @param displayHeight The current full height of the screen.
+     * @param displayRotation The current rotation being applied to the base
+     * window.
      */
-    public void beginLayoutLw(int displayWidth, int displayHeight);
+    public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation);
 
     /**
      * Called for each window attached to the window manager as layout is
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index f0e8005..7671312 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -261,6 +261,7 @@
      * Finds {@link AccessibilityNodeInfo}s by text. The match is case
      * insensitive containment. The search is relative to this info i.e.
      * this info is the root of the traversed tree.
+     *
      * <p>
      *   <strong>Note:</strong> It is a client responsibility to recycle the
      *     received info by calling {@link AccessibilityNodeInfo#recycle()}
diff --git a/core/java/android/webkit/WebView.java b/core/java/android/webkit/WebView.java
index 2f73474..be42608 100644
--- a/core/java/android/webkit/WebView.java
+++ b/core/java/android/webkit/WebView.java
@@ -62,6 +62,7 @@
 import android.util.EventLog;
 import android.util.Log;
 import android.view.Gravity;
+import android.view.HapticFeedbackConstants;
 import android.view.HardwareCanvas;
 import android.view.InputDevice;
 import android.view.KeyCharacterMap;
@@ -4252,7 +4253,11 @@
          * click action, look for a word under the  click. If one is found,
          * animate the text selection into view.
          * FIXME: no animation code yet */
-        return selectText();
+        final boolean isSelecting = selectText();
+        if (isSelecting) {
+            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
+        }
+        return isSelecting;
     }
 
     /**
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index edb1bfc..d78a7a3 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8677,18 +8677,15 @@
     }
 
     @Override
-    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched) {
-        if (TextUtils.isEmpty(searched)) {
-            return;
-        }
-        CharSequence thisText = getText();
-        if (TextUtils.isEmpty(thisText)) {
-            return;
-        }
-        String searchedLowerCase = searched.toString().toLowerCase();
-        String thisTextLowerCase = thisText.toString().toLowerCase();
-        if (thisTextLowerCase.contains(searchedLowerCase)) {
-            outViews.add(this);
+    public void findViewsWithText(ArrayList<View> outViews, CharSequence searched, int flags) {
+        super.findViewsWithText(outViews, searched, flags);
+        if (!outViews.contains(this) && (flags & FIND_VIEWS_WITH_TEXT) != 0
+                && !TextUtils.isEmpty(searched) && !TextUtils.isEmpty(mText)) {
+            String searchedLowerCase = searched.toString().toLowerCase();
+            String textLowerCase = mText.toString().toLowerCase();
+            if (textLowerCase.contains(searchedLowerCase)) {
+                outViews.add(this);
+            }
         }
     }
 
diff --git a/core/java/android/widget/TimePicker.java b/core/java/android/widget/TimePicker.java
index 7865d50..7444d46 100644
--- a/core/java/android/widget/TimePicker.java
+++ b/core/java/android/widget/TimePicker.java
@@ -218,9 +218,9 @@
                     updateAmPmControl();
                 }
             });
+            EditText amPmInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
+            amPmInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
         }
-        EditText amPmInput = (EditText) mAmPmSpinner.findViewById(R.id.numberpicker_input);
-        amPmInput.setImeOptions(EditorInfo.IME_ACTION_DONE);
 
         // update controls to initial state
         updateHourControl();
@@ -519,9 +519,11 @@
         text = mContext.getString(R.string.time_picker_decrement_hour_button);
         mHourSpinner.findViewById(R.id.decrement).setContentDescription(text);
         // AM/PM
-        text = mContext.getString(R.string.time_picker_increment_set_pm_button);
-        mAmPmSpinner.findViewById(R.id.increment).setContentDescription(text);
-        text = mContext.getString(R.string.time_picker_decrement_set_am_button);
-        mAmPmSpinner.findViewById(R.id.decrement).setContentDescription(text);
+        if (mAmPmSpinner != null) {
+            text = mContext.getString(R.string.time_picker_increment_set_pm_button);
+            mAmPmSpinner.findViewById(R.id.increment).setContentDescription(text);
+            text = mContext.getString(R.string.time_picker_decrement_set_am_button);
+            mAmPmSpinner.findViewById(R.id.decrement).setContentDescription(text);
+        }
     }
 }
diff --git a/core/java/com/android/internal/app/ActionBarImpl.java b/core/java/com/android/internal/app/ActionBarImpl.java
index ccca22e..afb5bf1 100644
--- a/core/java/com/android/internal/app/ActionBarImpl.java
+++ b/core/java/com/android/internal/app/ActionBarImpl.java
@@ -48,6 +48,7 @@
 import android.view.MenuItem;
 import android.view.View;
 import android.view.Window;
+import android.view.accessibility.AccessibilityEvent;
 import android.widget.SpinnerAdapter;
 
 import java.lang.ref.WeakReference;
@@ -397,6 +398,7 @@
                 // TODO animate this
                 mSplitView.setVisibility(View.VISIBLE);
             }
+            mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
             mActionMode = mode;
             return mode;
         }
@@ -681,6 +683,7 @@
 
             // Clear out the context mode views after the animation finishes
             mContextView.closeMode();
+            mActionView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
 
             mActionMode = null;
 
diff --git a/core/java/com/android/internal/view/StandaloneActionMode.java b/core/java/com/android/internal/view/StandaloneActionMode.java
index b54daba..ecda47e 100644
--- a/core/java/com/android/internal/view/StandaloneActionMode.java
+++ b/core/java/com/android/internal/view/StandaloneActionMode.java
@@ -26,6 +26,7 @@
 import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
+import android.view.accessibility.AccessibilityEvent;
 
 import java.lang.ref.WeakReference;
 
@@ -86,6 +87,7 @@
         }
         mFinished = true;
 
+        mContextView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
         mCallback.onDestroyActionMode(this);
     }
 
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index a631380..7bc33c7 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -34,6 +34,7 @@
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
+import android.view.accessibility.AccessibilityEvent;
 import android.view.animation.DecelerateInterpolator;
 import android.widget.LinearLayout;
 import android.widget.TextView;
@@ -455,4 +456,17 @@
     public boolean shouldDelayChildPressedState() {
         return false;
     }
+
+    @Override
+    public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
+        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
+            // Action mode started
+            event.setSource(this);
+            event.setClassName(getClass().getName());
+            event.setPackageName(getContext().getPackageName());
+            event.setContentDescription(mTitle);
+        } else {
+            super.onInitializeAccessibilityEvent(event);
+        }
+    }
 }
diff --git a/core/java/com/android/internal/widget/PointerLocationView.java b/core/java/com/android/internal/widget/PointerLocationView.java
index 158291b..9a0ce3a 100644
--- a/core/java/com/android/internal/widget/PointerLocationView.java
+++ b/core/java/com/android/internal/widget/PointerLocationView.java
@@ -51,7 +51,10 @@
         // Most recent velocity.
         private float mXVelocity;
         private float mYVelocity;
-        
+
+        // Position estimator.
+        private VelocityTracker.Estimator mEstimator = new VelocityTracker.Estimator();
+
         public void clearTrace() {
             mTraceCount = 0;
         }
@@ -75,6 +78,10 @@
         }
     }
 
+    private final int ESTIMATE_PAST_POINTS = 4;
+    private final int ESTIMATE_FUTURE_POINTS = 2;
+    private final float ESTIMATE_INTERVAL = 0.02f;
+
     private final ViewConfiguration mVC;
     private final Paint mTextPaint;
     private final Paint mTextBackgroundPaint;
@@ -278,8 +285,20 @@
                     haveLast = true;
                 }
                 
-                // Draw velocity vector.
                 if (drawn) {
+                    // Draw movement estimate curve.
+                    mPaint.setARGB(128, 128, 0, 128);
+                    float lx = ps.mEstimator.estimateX(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
+                    float ly = ps.mEstimator.estimateY(-ESTIMATE_PAST_POINTS * ESTIMATE_INTERVAL);
+                    for (int i = -ESTIMATE_PAST_POINTS + 1; i <= ESTIMATE_FUTURE_POINTS; i++) {
+                        float x = ps.mEstimator.estimateX(i * ESTIMATE_INTERVAL);
+                        float y = ps.mEstimator.estimateY(i * ESTIMATE_INTERVAL);
+                        canvas.drawLine(lx, ly, x, y, mPaint);
+                        lx = x;
+                        ly = y;
+                    }
+
+                    // Draw velocity vector.
                     mPaint.setARGB(255, 255, 64, 128);
                     float xVel = ps.mXVelocity * (1000 / 60);
                     float yVel = ps.mYVelocity * (1000 / 60);
@@ -517,6 +536,7 @@
                     ps.addTrace(coords.x, coords.y);
                     ps.mXVelocity = mVelocity.getXVelocity(id);
                     ps.mYVelocity = mVelocity.getYVelocity(id);
+                    mVelocity.getEstimator(id, -1, -1, ps.mEstimator);
                     ps.mToolType = event.getToolType(i);
                 }
             }
diff --git a/core/jni/android_view_Display.cpp b/core/jni/android_view_Display.cpp
index 5e668b9..366a52e 100644
--- a/core/jni/android_view_Display.cpp
+++ b/core/jni/android_view_Display.cpp
@@ -63,14 +63,14 @@
     env->SetFloatField(clazz, offsets.ydpi,     info.ydpi);
 }
 
-static jint android_view_Display_getRawWidth(
+static jint android_view_Display_getRawWidthNative(
         JNIEnv* env, jobject clazz)
 {
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
     return SurfaceComposerClient::getDisplayWidth(dpy);
 }
 
-static jint android_view_Display_getRawHeight(
+static jint android_view_Display_getRawHeightNative(
         JNIEnv* env, jobject clazz)
 {
     DisplayID dpy = env->GetIntField(clazz, offsets.display);
@@ -103,10 +103,10 @@
             (void*)android_view_Display_getDisplayCount },
 	{   "init", "(I)V",
             (void*)android_view_Display_init },
-    {   "getRawWidth", "()I",
-            (void*)android_view_Display_getRawWidth },
-    {   "getRawHeight", "()I",
-            (void*)android_view_Display_getRawHeight },
+    {   "getRawWidthNative", "()I",
+            (void*)android_view_Display_getRawWidthNative },
+    {   "getRawHeightNative", "()I",
+            (void*)android_view_Display_getRawHeightNative },
     {   "getOrientation", "()I",
             (void*)android_view_Display_getOrientation }
 };
diff --git a/core/jni/android_view_VelocityTracker.cpp b/core/jni/android_view_VelocityTracker.cpp
index 01a4c09..516e421 100644
--- a/core/jni/android_view_VelocityTracker.cpp
+++ b/core/jni/android_view_VelocityTracker.cpp
@@ -29,6 +29,14 @@
 // Special constant to request the velocity of the active pointer.
 static const int ACTIVE_POINTER_ID = -1;
 
+static struct {
+    jfieldID xCoeff;
+    jfieldID yCoeff;
+    jfieldID degree;
+    jfieldID confidence;
+} gEstimatorClassInfo;
+
+
 // --- VelocityTrackerState ---
 
 class VelocityTrackerState {
@@ -39,6 +47,8 @@
     void addMovement(const MotionEvent* event);
     void computeCurrentVelocity(int32_t units, float maxVelocity);
     void getVelocity(int32_t id, float* outVx, float* outVy);
+    bool getEstimator(int32_t id, uint32_t degree, nsecs_t horizon,
+            VelocityTracker::Estimator* outEstimator);
 
 private:
     struct Velocity {
@@ -118,6 +128,11 @@
     }
 }
 
+bool VelocityTrackerState::getEstimator(int32_t id, uint32_t degree, nsecs_t horizon,
+        VelocityTracker::Estimator* outEstimator) {
+    return mVelocityTracker.getEstimator(id, degree, horizon, outEstimator);
+}
+
 
 // --- JNI Methods ---
 
@@ -169,6 +184,30 @@
     return vy;
 }
 
+static jboolean android_view_VelocityTracker_nativeGetEstimator(JNIEnv* env, jclass clazz,
+        jint ptr, jint id, jint degree, jint horizonMillis, jobject outEstimatorObj) {
+    VelocityTrackerState* state = reinterpret_cast<VelocityTrackerState*>(ptr);
+    VelocityTracker::Estimator estimator;
+    bool result = state->getEstimator(id,
+            degree < 0 ? VelocityTracker::DEFAULT_DEGREE : uint32_t(degree),
+            horizonMillis < 0 ? VelocityTracker::DEFAULT_HORIZON :
+                    nsecs_t(horizonMillis) * 1000000L,
+            &estimator);
+
+    jfloatArray xCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
+            gEstimatorClassInfo.xCoeff));
+    jfloatArray yCoeffObj = jfloatArray(env->GetObjectField(outEstimatorObj,
+            gEstimatorClassInfo.yCoeff));
+
+    env->SetFloatArrayRegion(xCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
+            estimator.xCoeff);
+    env->SetFloatArrayRegion(yCoeffObj, 0, VelocityTracker::Estimator::MAX_DEGREE + 1,
+            estimator.yCoeff);
+    env->SetIntField(outEstimatorObj, gEstimatorClassInfo.degree, estimator.degree);
+    env->SetFloatField(outEstimatorObj, gEstimatorClassInfo.confidence, estimator.confidence);
+    return result;
+}
+
 
 // --- JNI Registration ---
 
@@ -195,12 +234,35 @@
     { "nativeGetYVelocity",
             "(II)F",
             (void*)android_view_VelocityTracker_nativeGetYVelocity },
+    { "nativeGetEstimator",
+            "(IIIILandroid/view/VelocityTracker$Estimator;)Z",
+            (void*)android_view_VelocityTracker_nativeGetEstimator },
 };
 
+#define FIND_CLASS(var, className) \
+        var = env->FindClass(className); \
+        LOG_FATAL_IF(! var, "Unable to find class " className);
+
+#define GET_FIELD_ID(var, clazz, fieldName, fieldDescriptor) \
+        var = env->GetFieldID(clazz, fieldName, fieldDescriptor); \
+        LOG_FATAL_IF(! var, "Unable to find field " fieldName);
+
 int register_android_view_VelocityTracker(JNIEnv* env) {
     int res = jniRegisterNativeMethods(env, "android/view/VelocityTracker",
             gVelocityTrackerMethods, NELEM(gVelocityTrackerMethods));
     LOG_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz;
+    FIND_CLASS(clazz, "android/view/VelocityTracker$Estimator");
+
+    GET_FIELD_ID(gEstimatorClassInfo.xCoeff, clazz,
+            "xCoeff", "[F");
+    GET_FIELD_ID(gEstimatorClassInfo.yCoeff, clazz,
+            "yCoeff", "[F");
+    GET_FIELD_ID(gEstimatorClassInfo.degree, clazz,
+            "degree", "I");
+    GET_FIELD_ID(gEstimatorClassInfo.confidence, clazz,
+            "confidence", "F");
     return 0;
 }
 
diff --git a/core/res/res/drawable-hdpi/ic_contact_picture.png b/core/res/res/drawable-hdpi/ic_contact_picture.png
index 9123c8c..2eef7b5 100644
--- a/core/res/res/drawable-hdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-hdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/ic_contact_picture.png b/core/res/res/drawable-mdpi/ic_contact_picture.png
index 535a772..6c7cb61 100644
--- a/core/res/res/drawable-mdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-mdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/ic_contact_picture.png b/core/res/res/drawable-xhdpi/ic_contact_picture.png
index 4ade625..1a2bfde 100644
--- a/core/res/res/drawable-xhdpi/ic_contact_picture.png
+++ b/core/res/res/drawable-xhdpi/ic_contact_picture.png
Binary files differ
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index eeff473..87cfa38 100755
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -2485,7 +2485,10 @@
     <string name="textSelectionCABTitle">Text selection</string>
 
     <!-- Option to add the current misspelled word to the user dictionary. [CHAR LIMIT=25] -->
-    <string name="addToDictionary">+ add to dictionary</string>
+    <string name="addToDictionary">add to dictionary</string>
+
+    <!-- Option to delete the highlighted part of the text from the suggestion popup. [CHAR LIMIT=25] -->
+    <string name="deleteText">delete</string>
 
     <!-- EditText context menu -->
     <string name="inputMethod">Input method</string>
@@ -3218,7 +3221,7 @@
     <!-- Notification title when data usage has exceeded warning threshold. [CHAR LIMIT=32] -->
     <string name="data_usage_warning_title">Data usage warning</string>
     <!-- Notification body when data usage has exceeded warning threshold. [CHAR LIMIT=32] -->
-    <string name="data_usage_warning_body">usage exceeds <xliff:g id="size" example="3.8GB">%s</xliff:g></string>
+    <string name="data_usage_warning_body">Touch to view usage and settings</string>
 
     <!-- Notification title when 2G-3G data usage has exceeded limit threshold, and has been disabled. [CHAR LIMIT=32] -->
     <string name="data_usage_3g_limit_title">2G-3G data disabled</string>
diff --git a/core/tests/coretests/res/layout/interrogation_activity.xml b/core/tests/coretests/res/layout/interrogation_activity.xml
index 44ed75c..64af321 100644
--- a/core/tests/coretests/res/layout/interrogation_activity.xml
+++ b/core/tests/coretests/res/layout/interrogation_activity.xml
@@ -70,6 +70,7 @@
             android:layout_width="160px"
             android:layout_height="100px"
             android:text="@string/button6"
+            android:contentDescription="contentDescription"
         />
     </LinearLayout>
 
diff --git a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
index a542a1b..cd8dcb9 100644
--- a/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
+++ b/core/tests/coretests/src/android/accessibilityservice/InterrogationActivityTest.java
@@ -148,6 +148,29 @@
     }
 
     @LargeTest
+    public void testFindAccessibilityNodeInfoByViewTextContentDescription() throws Exception {
+        beforeClassIfNeeded();
+        final long startTimeMillis = SystemClock.uptimeMillis();
+        try {
+            // bring up the activity
+            getActivity();
+
+            // find a view by text
+            List<AccessibilityNodeInfo> buttons =  AccessibilityInteractionClient.getInstance()
+                .findAccessibilityNodeInfosByViewTextInActiveWindow(getConnection(),
+                        "contentDescription");
+            assertEquals(1, buttons.size());
+        } finally {
+            afterClassIfNeeded();
+            if (DEBUG) {
+                final long elapsedTimeMillis = SystemClock.uptimeMillis() - startTimeMillis;
+                Log.i(LOG_TAG, "testFindAccessibilityNodeInfoByViewTextContentDescription: "
+                        + elapsedTimeMillis + "ms");
+            }
+        }
+    }
+
+    @LargeTest
     public void testTraverseAllViews() throws Exception {
         beforeClassIfNeeded();
         final long startTimeMillis = SystemClock.uptimeMillis();
diff --git a/data/videos/AndroidInSpace.480p.lq.mp4 b/data/videos/AndroidInSpace.480p.lq.mp4
new file mode 100755
index 0000000..f1db694
--- /dev/null
+++ b/data/videos/AndroidInSpace.480p.lq.mp4
Binary files differ
diff --git a/data/videos/AndroidInSpace.480p.mq.mp4 b/data/videos/AndroidInSpace.480p.mq.mp4
new file mode 100755
index 0000000..5f4cfb3
--- /dev/null
+++ b/data/videos/AndroidInSpace.480p.mq.mp4
Binary files differ
diff --git a/data/videos/Sunset.480p.lq.mp4 b/data/videos/Sunset.480p.lq.mp4
new file mode 100644
index 0000000..7f9d6a1
--- /dev/null
+++ b/data/videos/Sunset.480p.lq.mp4
Binary files differ
diff --git a/data/videos/Sunset.480p.mq.mp4 b/data/videos/Sunset.480p.mq.mp4
new file mode 100644
index 0000000..7691544
--- /dev/null
+++ b/data/videos/Sunset.480p.mq.mp4
Binary files differ
diff --git a/data/videos/VideoPackage1.mk b/data/videos/VideoPackage1.mk
index daff26f..1e7096a 100644
--- a/data/videos/VideoPackage1.mk
+++ b/data/videos/VideoPackage1.mk
@@ -14,10 +14,14 @@
 # limitations under the License.
 #
 
+# Lower-quality videos for space-constrained devices
+
 LOCAL_PATH  := frameworks/base/data/videos
 TARGET_PATH := system/media/video
 
 PRODUCT_COPY_FILES += \
-	$(LOCAL_PATH)/AndroidInSpace.240p.mp4:$(TARGET_PATH)/AndroidInSpace.240p.mp4 \
-	$(LOCAL_PATH)/Sunset.240p.mp4:$(TARGET_PATH)/Sunset.240p.mp4
+        $(LOCAL_PATH)/AndroidInSpace.240p.mp4:$(TARGET_PATH)/AndroidInSpace.240p.mp4 \
+        $(LOCAL_PATH)/AndroidInSpace.480p.lq.mp4:$(TARGET_PATH)/AndroidInSpace.480p.mp4 \
+        $(LOCAL_PATH)/Sunset.240p.mp4:$(TARGET_PATH)/Sunset.240p.mp4 \
+        $(LOCAL_PATH)/Sunset.480p.lq.mp4:$(TARGET_PATH)/Sunset.480p.mp4
 
diff --git a/data/videos/VideoPackage2.mk b/data/videos/VideoPackage2.mk
new file mode 100644
index 0000000..cb77b3ec
--- /dev/null
+++ b/data/videos/VideoPackage2.mk
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+# Good-quality videos for non-space-constrained devices
+
+LOCAL_PATH  := frameworks/base/data/videos
+TARGET_PATH := system/media/video
+
+PRODUCT_COPY_FILES += \
+        $(LOCAL_PATH)/AndroidInSpace.240p.mp4:$(TARGET_PATH)/AndroidInSpace.240p.mp4 \
+        $(LOCAL_PATH)/AndroidInSpace.480p.mq.mp4:$(TARGET_PATH)/AndroidInSpace.480p.mp4 \
+        $(LOCAL_PATH)/Sunset.240p.mp4:$(TARGET_PATH)/Sunset.240p.mp4 \
+        $(LOCAL_PATH)/Sunset.480p.mq.mp4:$(TARGET_PATH)/Sunset.480p.mp4
+
diff --git a/include/media/stagefright/OMXCodec.h b/include/media/stagefright/OMXCodec.h
index 2932744..8baf5ec 100644
--- a/include/media/stagefright/OMXCodec.h
+++ b/include/media/stagefright/OMXCodec.h
@@ -303,7 +303,7 @@
     bool flushPortAsync(OMX_U32 portIndex);
 
     void disablePortAsync(OMX_U32 portIndex);
-    void enablePortAsync(OMX_U32 portIndex);
+    status_t enablePortAsync(OMX_U32 portIndex);
 
     static size_t countBuffersWeOwn(const Vector<BufferInfo> &buffers);
     static bool isIntermediateState(State state);
diff --git a/include/ui/Input.h b/include/ui/Input.h
index af899ef..438a1a0 100644
--- a/include/ui/Input.h
+++ b/include/ui/Input.h
@@ -620,10 +620,41 @@
  */
 class VelocityTracker {
 public:
+    // Default polynomial degree.  (used by getVelocity)
+    static const uint32_t DEFAULT_DEGREE = 2;
+
+    // Default sample horizon.  (used by getVelocity)
+    // We don't use too much history by default since we want to react to quick
+    // changes in direction.
+    static const nsecs_t DEFAULT_HORIZON = 100 * 1000000; // 100 ms
+
     struct Position {
         float x, y;
     };
 
+    struct Estimator {
+        static const size_t MAX_DEGREE = 2;
+
+        // Polynomial coefficients describing motion in X and Y.
+        float xCoeff[MAX_DEGREE + 1], yCoeff[MAX_DEGREE + 1];
+
+        // Polynomial degree (number of coefficients), or zero if no information is
+        // available.
+        uint32_t degree;
+
+        // Confidence (coefficient of determination), between 0 (no fit) and 1 (perfect fit).
+        float confidence;
+
+        inline void clear() {
+            degree = 0;
+            confidence = 0;
+            for (size_t i = 0; i <= MAX_DEGREE; i++) {
+                xCoeff[i] = 0;
+                yCoeff[i] = 0;
+            }
+        }
+    };
+
     VelocityTracker();
 
     // Resets the velocity tracker state.
@@ -645,10 +676,16 @@
     void addMovement(const MotionEvent* event);
 
     // Gets the velocity of the specified pointer id in position units per second.
-    // Returns false and sets the velocity components to zero if there is no movement
-    // information for the pointer.
+    // Returns false and sets the velocity components to zero if there is
+    // insufficient movement information for the pointer.
     bool getVelocity(uint32_t id, float* outVx, float* outVy) const;
 
+    // Gets a quadratic estimator for the movements of the specified pointer id.
+    // Returns false and clears the estimator if there is no information available
+    // about the pointer.
+    bool getEstimator(uint32_t id, uint32_t degree, nsecs_t horizon,
+            Estimator* outEstimator) const;
+
     // Gets the active pointer id, or -1 if none.
     inline int32_t getActivePointerId() const { return mActivePointerId; }
 
@@ -657,13 +694,7 @@
 
 private:
     // Number of samples to keep.
-    static const uint32_t HISTORY_SIZE = 10;
-
-    // Oldest sample to consider when calculating the velocity.
-    static const nsecs_t MAX_AGE = 100 * 1000000; // 100 ms
-
-    // The minimum duration between samples when estimating velocity.
-    static const nsecs_t MIN_DURATION = 5 * 1000000; // 5 ms
+    static const uint32_t HISTORY_SIZE = 20;
 
     struct Movement {
         nsecs_t eventTime;
diff --git a/libs/ui/Input.cpp b/libs/ui/Input.cpp
index 0d25823..a5ba57d 100644
--- a/libs/ui/Input.cpp
+++ b/libs/ui/Input.cpp
@@ -13,6 +13,9 @@
 // Log debug messages about velocity tracking.
 #define DEBUG_VELOCITY 0
 
+// Log debug messages about least squares fitting.
+#define DEBUG_LEAST_SQUARES 0
+
 // Log debug messages about acceleration.
 #define DEBUG_ACCELERATION 0
 
@@ -682,9 +685,61 @@
 
 // --- VelocityTracker ---
 
+const uint32_t VelocityTracker::DEFAULT_DEGREE;
+const nsecs_t VelocityTracker::DEFAULT_HORIZON;
 const uint32_t VelocityTracker::HISTORY_SIZE;
-const nsecs_t VelocityTracker::MAX_AGE;
-const nsecs_t VelocityTracker::MIN_DURATION;
+
+static inline float vectorDot(const float* a, const float* b, uint32_t m) {
+    float r = 0;
+    while (m--) {
+        r += *(a++) * *(b++);
+    }
+    return r;
+}
+
+static inline float vectorNorm(const float* a, uint32_t m) {
+    float r = 0;
+    while (m--) {
+        float t = *(a++);
+        r += t * t;
+    }
+    return sqrtf(r);
+}
+
+#if DEBUG_LEAST_SQUARES || DEBUG_VELOCITY
+static String8 vectorToString(const float* a, uint32_t m) {
+    String8 str;
+    str.append("[");
+    while (m--) {
+        str.appendFormat(" %f", *(a++));
+        if (m) {
+            str.append(",");
+        }
+    }
+    str.append(" ]");
+    return str;
+}
+
+static String8 matrixToString(const float* a, uint32_t m, uint32_t n, bool rowMajor) {
+    String8 str;
+    str.append("[");
+    for (size_t i = 0; i < m; i++) {
+        if (i) {
+            str.append(",");
+        }
+        str.append(" [");
+        for (size_t j = 0; j < n; j++) {
+            if (j) {
+                str.append(",");
+            }
+            str.appendFormat(" %f", a[rowMajor ? i * n + j : j * m + i]);
+        }
+        str.append(" ]");
+    }
+    str.append(" ]");
+    return str;
+}
+#endif
 
 VelocityTracker::VelocityTracker() {
     clear();
@@ -733,16 +788,15 @@
         uint32_t id = iterBits.firstMarkedBit();
         uint32_t index = idBits.getIndexOfBit(id);
         iterBits.clearBit(id);
-        float vx, vy;
-        bool available = getVelocity(id, &vx, &vy);
-        if (available) {
-            LOGD("  %d: position (%0.3f, %0.3f), vx=%0.3f, vy=%0.3f, speed=%0.3f",
-                    id, positions[index].x, positions[index].y, vx, vy, sqrtf(vx * vx + vy * vy));
-        } else {
-            LOG_ASSERT(vx == 0 && vy == 0);
-            LOGD("  %d: position (%0.3f, %0.3f), velocity not available",
-                    id, positions[index].x, positions[index].y);
-        }
+        Estimator estimator;
+        getEstimator(id, DEFAULT_DEGREE, DEFAULT_HORIZON, &estimator);
+        LOGD("  %d: position (%0.3f, %0.3f), "
+                "estimator (degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f)",
+                id, positions[index].x, positions[index].y,
+                int(estimator.degree),
+                vectorToString(estimator.xCoeff, estimator.degree).string(),
+                vectorToString(estimator.yCoeff, estimator.degree).string(),
+                estimator.confidence);
     }
 #endif
 }
@@ -811,47 +865,228 @@
     addMovement(eventTime, idBits, positions);
 }
 
+/**
+ * Solves a linear least squares problem to obtain a N degree polynomial that fits
+ * the specified input data as nearly as possible.
+ *
+ * Returns true if a solution is found, false otherwise.
+ *
+ * The input consists of two vectors of data points X and Y with indices 0..m-1.
+ * The output is a vector B with indices 0..n-1 that describes a polynomial
+ * that fits the data, such the sum of abs(Y[i] - (B[0] + B[1] X[i] + B[2] X[i]^2 ... B[n] X[i]^n))
+ * for all i between 0 and m-1 is minimized.
+ *
+ * That is to say, the function that generated the input data can be approximated
+ * by y(x) ~= B[0] + B[1] x + B[2] x^2 + ... + B[n] x^n.
+ *
+ * The coefficient of determination (R^2) is also returned to describe the goodness
+ * of fit of the model for the given data.  It is a value between 0 and 1, where 1
+ * indicates perfect correspondence.
+ *
+ * This function first expands the X vector to a m by n matrix A such that
+ * A[i][0] = 1, A[i][1] = X[i], A[i][2] = X[i]^2, ..., A[i][n] = X[i]^n.
+ *
+ * Then it calculates the QR decomposition of A yielding an m by m orthonormal matrix Q
+ * and an m by n upper triangular matrix R.  Because R is upper triangular (lower
+ * part is all zeroes), we can simplify the decomposition into an m by n matrix
+ * Q1 and a n by n matrix R1 such that A = Q1 R1.
+ *
+ * Finally we solve the system of linear equations given by R1 B = (Qtranspose Y)
+ * to find B.
+ *
+ * For efficiency, we lay out A and Q column-wise in memory because we frequently
+ * operate on the column vectors.  Conversely, we lay out R row-wise.
+ *
+ * http://en.wikipedia.org/wiki/Numerical_methods_for_linear_least_squares
+ * http://en.wikipedia.org/wiki/Gram-Schmidt
+ */
+static bool solveLeastSquares(const float* x, const float* y, uint32_t m, uint32_t n,
+        float* outB, float* outDet) {
+#if DEBUG_LEAST_SQUARES
+    LOGD("solveLeastSquares: m=%d, n=%d, x=%s, y=%s", int(m), int(n),
+            vectorToString(x, m).string(), vectorToString(y, m).string());
+#endif
+
+    // Expand the X vector to a matrix A.
+    float a[n][m]; // column-major order
+    for (uint32_t h = 0; h < m; h++) {
+        a[0][h] = 1;
+        for (uint32_t i = 1; i < n; i++) {
+            a[i][h] = a[i - 1][h] * x[h];
+        }
+    }
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - a=%s", matrixToString(&a[0][0], m, n, false /*rowMajor*/).string());
+#endif
+
+    // Apply the Gram-Schmidt process to A to obtain its QR decomposition.
+    float q[n][m]; // orthonormal basis, column-major order
+    float r[n][n]; // upper triangular matrix, row-major order
+    for (uint32_t j = 0; j < n; j++) {
+        for (uint32_t h = 0; h < m; h++) {
+            q[j][h] = a[j][h];
+        }
+        for (uint32_t i = 0; i < j; i++) {
+            float dot = vectorDot(&q[j][0], &q[i][0], m);
+            for (uint32_t h = 0; h < m; h++) {
+                q[j][h] -= dot * q[i][h];
+            }
+        }
+
+        float norm = vectorNorm(&q[j][0], m);
+        if (norm < 0.000001f) {
+            // vectors are linearly dependent or zero so no solution
+#if DEBUG_LEAST_SQUARES
+            LOGD("  - no solution, norm=%f", norm);
+#endif
+            return false;
+        }
+
+        float invNorm = 1.0f / norm;
+        for (uint32_t h = 0; h < m; h++) {
+            q[j][h] *= invNorm;
+        }
+        for (uint32_t i = 0; i < n; i++) {
+            r[j][i] = i < j ? 0 : vectorDot(&q[j][0], &a[i][0], m);
+        }
+    }
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - q=%s", matrixToString(&q[0][0], m, n, false /*rowMajor*/).string());
+    LOGD("  - r=%s", matrixToString(&r[0][0], n, n, true /*rowMajor*/).string());
+
+    // calculate QR, if we factored A correctly then QR should equal A
+    float qr[n][m];
+    for (uint32_t h = 0; h < m; h++) {
+        for (uint32_t i = 0; i < n; i++) {
+            qr[i][h] = 0;
+            for (uint32_t j = 0; j < n; j++) {
+                qr[i][h] += q[j][h] * r[j][i];
+            }
+        }
+    }
+    LOGD("  - qr=%s", matrixToString(&qr[0][0], m, n, false /*rowMajor*/).string());
+#endif
+
+    // Solve R B = Qt Y to find B.  This is easy because R is upper triangular.
+    // We just work from bottom-right to top-left calculating B's coefficients.
+    for (uint32_t i = n; i-- != 0; ) {
+        outB[i] = vectorDot(&q[i][0], y, m);
+        for (uint32_t j = n - 1; j > i; j--) {
+            outB[i] -= r[i][j] * outB[j];
+        }
+        outB[i] /= r[i][i];
+    }
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - b=%s", vectorToString(outB, n).string());
+#endif
+
+    // Calculate the coefficient of determination as 1 - (SSerr / SStot) where
+    // SSerr is the residual sum of squares (squared variance of the error),
+    // and SStot is the total sum of squares (squared variance of the data).
+    float ymean = 0;
+    for (uint32_t h = 0; h < m; h++) {
+        ymean += y[h];
+    }
+    ymean /= m;
+
+    float sserr = 0;
+    float sstot = 0;
+    for (uint32_t h = 0; h < m; h++) {
+        float err = y[h] - outB[0];
+        float term = 1;
+        for (uint32_t i = 1; i < n; i++) {
+            term *= x[h];
+            err -= term * outB[i];
+        }
+        sserr += err * err;
+        float var = y[h] - ymean;
+        sstot += var * var;
+    }
+    *outDet = sstot > 0.000001f ? 1.0f - (sserr / sstot) : 1;
+#if DEBUG_LEAST_SQUARES
+    LOGD("  - sserr=%f", sserr);
+    LOGD("  - sstot=%f", sstot);
+    LOGD("  - det=%f", *outDet);
+#endif
+    return true;
+}
+
 bool VelocityTracker::getVelocity(uint32_t id, float* outVx, float* outVy) const {
+    Estimator estimator;
+    if (getEstimator(id, DEFAULT_DEGREE, DEFAULT_HORIZON, &estimator)) {
+        if (estimator.degree >= 1) {
+            *outVx = estimator.xCoeff[1];
+            *outVy = estimator.yCoeff[1];
+            return true;
+        }
+    }
+    return false;
+}
+
+bool VelocityTracker::getEstimator(uint32_t id, uint32_t degree, nsecs_t horizon,
+        Estimator* outEstimator) const {
+    outEstimator->clear();
+
+    // Iterate over movement samples in reverse time order and collect samples.
+    float x[HISTORY_SIZE];
+    float y[HISTORY_SIZE];
+    float time[HISTORY_SIZE];
+    uint32_t m = 0;
+    uint32_t index = mIndex;
     const Movement& newestMovement = mMovements[mIndex];
-    if (newestMovement.idBits.hasBit(id)) {
-        const Position& newestPosition = newestMovement.getPosition(id);
-        float accumVx = 0;
-        float accumVy = 0;
-        float duration = 0;
+    do {
+        const Movement& movement = mMovements[index];
+        if (!movement.idBits.hasBit(id)) {
+            break;
+        }
 
-        // Iterate over movement samples in reverse time order and accumulate velocity.
-        uint32_t index = mIndex;
-        do {
-            index = (index == 0 ? HISTORY_SIZE : index) - 1;
-            const Movement& movement = mMovements[index];
-            if (!movement.idBits.hasBit(id)) {
-                break;
-            }
+        nsecs_t age = newestMovement.eventTime - movement.eventTime;
+        if (age > horizon) {
+            break;
+        }
 
-            nsecs_t age = newestMovement.eventTime - movement.eventTime;
-            if (age > MAX_AGE) {
-                break;
-            }
+        const Position& position = movement.getPosition(id);
+        x[m] = position.x;
+        y[m] = position.y;
+        time[m] = -age * 0.000000001f;
+        index = (index == 0 ? HISTORY_SIZE : index) - 1;
+    } while (++m < HISTORY_SIZE);
 
-            const Position& position = movement.getPosition(id);
-            accumVx += newestPosition.x - position.x;
-            accumVy += newestPosition.y - position.y;
-            duration += age;
-        } while (index != mIndex);
+    if (m == 0) {
+        return false; // no data
+    }
 
-        // Make sure we used at least one sample.
-        if (duration >= MIN_DURATION) {
-            float scale = 1000000000.0f / duration; // one over time delta in seconds
-            *outVx = accumVx * scale;
-            *outVy = accumVy * scale;
+    // Calculate a least squares polynomial fit.
+    if (degree > Estimator::MAX_DEGREE) {
+        degree = Estimator::MAX_DEGREE;
+    }
+    if (degree > m - 1) {
+        degree = m - 1;
+    }
+    if (degree >= 1) {
+        float xdet, ydet;
+        uint32_t n = degree + 1;
+        if (solveLeastSquares(time, x, m, n, outEstimator->xCoeff, &xdet)
+                && solveLeastSquares(time, y, m, n, outEstimator->yCoeff, &ydet)) {
+            outEstimator->degree = degree;
+            outEstimator->confidence = xdet * ydet;
+#if DEBUG_LEAST_SQUARES
+            LOGD("estimate: degree=%d, xCoeff=%s, yCoeff=%s, confidence=%f",
+                    int(outEstimator->degree),
+                    vectorToString(outEstimator->xCoeff, n).string(),
+                    vectorToString(outEstimator->yCoeff, n).string(),
+                    outEstimator->confidence);
+#endif
             return true;
         }
     }
 
-    // No data available for this pointer.
-    *outVx = 0;
-    *outVy = 0;
-    return false;
+    // No velocity data available for this pointer, but we do have its current position.
+    outEstimator->xCoeff[0] = x[0];
+    outEstimator->yCoeff[0] = y[0];
+    outEstimator->degree = 0;
+    outEstimator->confidence = 1;
+    return true;
 }
 
 
diff --git a/media/libstagefright/OMXCodec.cpp b/media/libstagefright/OMXCodec.cpp
index 9ab470b..6280f51 100755
--- a/media/libstagefright/OMXCodec.cpp
+++ b/media/libstagefright/OMXCodec.cpp
@@ -2452,13 +2452,16 @@
                     mOutputPortSettingsHaveChanged = formatChanged;
                 }
 
-                enablePortAsync(portIndex);
-
-                status_t err = allocateBuffersOnPort(portIndex);
-
+                status_t err = enablePortAsync(portIndex);
                 if (err != OK) {
-                    CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
+                    CODEC_LOGE("enablePortAsync(%ld) failed (err = %d)", portIndex, err);
                     setState(ERROR);
+                } else {
+                    err = allocateBuffersOnPort(portIndex);
+                    if (err != OK) {
+                        CODEC_LOGE("allocateBuffersOnPort failed (err = %d)", err);
+                        setState(ERROR);
+                    }
                 }
             }
             break;
@@ -2773,16 +2776,14 @@
     freeBuffersOnPort(portIndex, true);
 }
 
-void OMXCodec::enablePortAsync(OMX_U32 portIndex) {
+status_t OMXCodec::enablePortAsync(OMX_U32 portIndex) {
     CHECK(mState == EXECUTING || mState == RECONFIGURING);
 
     CHECK_EQ((int)mPortStatus[portIndex], (int)DISABLED);
     mPortStatus[portIndex] = ENABLING;
 
     CODEC_LOGV("sending OMX_CommandPortEnable(%ld)", portIndex);
-    status_t err =
-        mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
-    CHECK_EQ(err, (status_t)OK);
+    return mOMX->sendCommand(mNode, OMX_CommandPortEnable, portIndex);
 }
 
 void OMXCodec::fillOutputBuffers() {
diff --git a/opengl/include/EGL/eglext.h b/opengl/include/EGL/eglext.h
index 6a199db..a08932a 100644
--- a/opengl/include/EGL/eglext.h
+++ b/opengl/include/EGL/eglext.h
@@ -242,6 +242,20 @@
 #define EGL_RECORDABLE_ANDROID                  0x3142  /* EGLConfig attribute */
 #endif
 
+/* EGL_NV_system_time
+ */
+#ifndef EGL_NV_system_time
+#define EGL_NV_system_time 1
+typedef khronos_int64_t EGLint64NV;
+typedef khronos_uint64_t EGLuint64NV;
+#ifdef EGL_EGLEXT_PROTOTYPES
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeFrequencyNV(void);
+EGLAPI EGLuint64NV EGLAPIENTRY eglGetSystemTimeNV(void);
+#endif
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMEFREQUENCYNVPROC)(void);
+typedef EGLuint64NV (EGLAPIENTRYP PFNEGLGETSYSTEMTIMENVPROC)(void);
+#endif
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/opengl/libs/EGL/eglApi.cpp b/opengl/libs/EGL/eglApi.cpp
index 7e85230..23f67d5 100644
--- a/opengl/libs/EGL/eglApi.cpp
+++ b/opengl/libs/EGL/eglApi.cpp
@@ -62,6 +62,7 @@
         "EGL_KHR_fence_sync "
         "EGL_ANDROID_image_native_buffer "
         "EGL_ANDROID_swap_rectangle "
+        "EGL_NV_system_time "
         ;
 
 struct extention_map_t {
@@ -80,6 +81,10 @@
             (__eglMustCastToProperFunctionPointerType)&eglDestroyImageKHR },
     { "eglSetSwapRectangleANDROID",
             (__eglMustCastToProperFunctionPointerType)&eglSetSwapRectangleANDROID },
+    { "eglGetSystemTimeFrequencyNV",
+            (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeFrequencyNV },
+    { "eglGetSystemTimeNV",
+            (__eglMustCastToProperFunctionPointerType)&eglGetSystemTimeNV },
 };
 
 // accesses protected by sExtensionMapMutex
@@ -1454,3 +1459,46 @@
     }
     return setError(EGL_BAD_DISPLAY, NULL);
 }
+
+// ----------------------------------------------------------------------------
+// NVIDIA extensions
+// ----------------------------------------------------------------------------
+EGLuint64NV eglGetSystemTimeFrequencyNV()
+{
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    EGLuint64NV ret = 0;
+    egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
+
+    if (cnx->dso) {
+        if (cnx->egl.eglGetSystemTimeFrequencyNV) {
+            return cnx->egl.eglGetSystemTimeFrequencyNV();
+        }
+    }
+
+    return setError(EGL_BAD_DISPLAY, 0);;
+}
+
+EGLuint64NV eglGetSystemTimeNV()
+{
+    clearError();
+
+    if (egl_init_drivers() == EGL_FALSE) {
+        return setError(EGL_BAD_PARAMETER, EGL_FALSE);
+    }
+
+    EGLuint64NV ret = 0;
+    egl_connection_t* const cnx = &gEGLImpl[IMPL_HARDWARE];
+
+    if (cnx->dso) {
+        if (cnx->egl.eglGetSystemTimeNV) {
+            return cnx->egl.eglGetSystemTimeNV();
+        }
+    }
+
+    return setError(EGL_BAD_DISPLAY, 0);;
+}
diff --git a/opengl/libs/EGL/egl_entries.in b/opengl/libs/EGL/egl_entries.in
index 63c3c19..bdd2a7e 100644
--- a/opengl/libs/EGL/egl_entries.in
+++ b/opengl/libs/EGL/egl_entries.in
@@ -62,3 +62,8 @@
 
 EGL_ENTRY(EGLBoolean, eglSetSwapRectangleANDROID, EGLDisplay, EGLSurface, EGLint, EGLint, EGLint, EGLint)
 EGL_ENTRY(EGLClientBuffer, eglGetRenderBufferANDROID, EGLDisplay, EGLSurface)
+
+/* NVIDIA extensions */
+
+EGL_ENTRY(EGLuint64NV, eglGetSystemTimeFrequencyNV, void)
+EGL_ENTRY(EGLuint64NV, eglGetSystemTimeNV, void)
diff --git a/packages/BackupRestoreConfirmation/res/values/strings.xml b/packages/BackupRestoreConfirmation/res/values/strings.xml
index e207a98..e91c6e2 100644
--- a/packages/BackupRestoreConfirmation/res/values/strings.xml
+++ b/packages/BackupRestoreConfirmation/res/values/strings.xml
@@ -43,4 +43,15 @@
 
     <!-- Text for message to user when performing a full restore operation, explaining that they must enter the password originally used to encrypt the full backup data. -->
     <string name="restore_enc_password_text">If the restore data is encrypted, please enter the password below:</string>
+
+    <!-- Text of a toast telling the user that a full backup operation has begun -->
+    <string name="toast_backup_started">Backup starting...</string>
+    <!-- Text of a toast telling the user that a full backup operation has ended -->
+    <string name="toast_backup_ended">Backup finished</string>
+    <!-- Text of a toast telling the user that a full restore operation has begun -->
+    <string name="toast_restore_started">Restore starting...</string>
+    <!-- Text of a toast telling the user that a full restore operation has ended -->
+    <string name="toast_restore_ended">Restore ended</string>
+    <!-- Text of a toast telling the user that the operation has timed out -->
+    <string name="toast_timeout">Operation timed out</string>
 </resources>
diff --git a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
index d053f29..fbdf3cc 100644
--- a/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
+++ b/packages/BackupRestoreConfirmation/src/com/android/backupconfirm/BackupRestoreConfirmation.java
@@ -82,7 +82,7 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_START_BACKUP: {
-                    Toast.makeText(mContext, "!!! Backup starting !!!", Toast.LENGTH_LONG).show();
+                    Toast.makeText(mContext, R.string.toast_backup_started, Toast.LENGTH_LONG).show();
                 }
                 break;
 
@@ -93,13 +93,13 @@
                 break;
 
                 case MSG_END_BACKUP: {
-                    Toast.makeText(mContext, "!!! Backup ended !!!", Toast.LENGTH_SHORT).show();
+                    Toast.makeText(mContext, R.string.toast_backup_ended, Toast.LENGTH_LONG).show();
                     finish();
                 }
                 break;
 
                 case MSG_START_RESTORE: {
-                    Toast.makeText(mContext, "!!! Restore starting !!!", Toast.LENGTH_LONG).show();
+                    Toast.makeText(mContext, R.string.toast_restore_started, Toast.LENGTH_LONG).show();
                 }
                 break;
 
@@ -110,13 +110,13 @@
                 break;
 
                 case MSG_END_RESTORE: {
-                    Toast.makeText(mContext, "!!! Restore ended !!!", Toast.LENGTH_SHORT).show();
+                    Toast.makeText(mContext, R.string.toast_restore_ended, Toast.LENGTH_SHORT).show();
                     finish();
                 }
                 break;
 
                 case MSG_TIMEOUT: {
-                    Toast.makeText(mContext, "!!! TIMED OUT !!!", Toast.LENGTH_LONG).show();
+                    Toast.makeText(mContext, R.string.toast_timeout, Toast.LENGTH_LONG).show();
                 }
                 break;
             }
diff --git a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
index 0f0cbf1..69f3543 100644
--- a/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
index 374873c..4650417 100644
--- a/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-hdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
index 5e8a116..fb30982 100644
--- a/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
index 75a020c..f334023 100644
--- a/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
+++ b/packages/SystemUI/res/drawable-mdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
index efac368..fe2c642 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_close_on.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/status_bar_hr.9.png b/packages/SystemUI/res/drawable-xhdpi/status_bar_hr.9.png
index f5e6031..748b9f7 100644
--- a/packages/SystemUI/res/drawable-xhdpi/status_bar_hr.9.png
+++ b/packages/SystemUI/res/drawable-xhdpi/status_bar_hr.9.png
Binary files differ
diff --git a/packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.png b/packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.png
new file mode 100644
index 0000000..89f14db
--- /dev/null
+++ b/packages/SystemUI/res/drawable-xhdpi/title_bar_shadow.9.png
Binary files differ
diff --git a/packages/SystemUI/res/layout/status_bar_expanded.xml b/packages/SystemUI/res/layout/status_bar_expanded.xml
index f9f31ca..38ac8a7 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded.xml
@@ -115,14 +115,8 @@
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
                     systemui:rowHeight="@dimen/notification_height"
-                    android:background="@color/notification_list_shadow_top"
                     />
-                <ImageView
-                    android:layout_width="match_parent"
-                    android:layout_height="16dp"
-                    android:src="@drawable/notification_list_shadow"
-                    android:scaleType="fitXY"
-                />
+
             </LinearLayout>
         </ScrollView>
 
diff --git a/packages/SystemUI/res/values/colors.xml b/packages/SystemUI/res/values/colors.xml
index 298536b4..e780ae6 100644
--- a/packages/SystemUI/res/values/colors.xml
+++ b/packages/SystemUI/res/values/colors.xml
@@ -24,8 +24,8 @@
     <drawable name="status_bar_recents_background">#b3000000</drawable>
     <drawable name="status_bar_recents_app_thumbnail_background">#88000000</drawable>
     <color name="status_bar_recents_app_label_color">#ffffffff</color>
-    <drawable name="status_bar_notification_row_background_color">#ff000000</drawable>
+    <drawable name="status_bar_notification_row_background_color">#ff090909</drawable>
     <drawable name="notification_header_bg">#FF000000</drawable>
-    <drawable name="notification_tracking_bg">#cc111315</drawable>
+    <drawable name="notification_tracking_bg">#d8000000</drawable>
     <color name="notification_list_shadow_top">#80000000</color>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
index 0448da7..610edfa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NavigationBarView.java
@@ -112,7 +112,6 @@
     };
 
     public void setDisabledFlags(int disabledFlags) {
-        Slog.d(TAG, "setDisabledFlags: " + disabledFlags);
         setDisabledFlags(disabledFlags, false);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index 590bd3c..febf3ab 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -469,20 +469,10 @@
     }
 
     private WindowManager.LayoutParams getNavigationBarLayoutParams() {
-        final int rotation = mDisplay.getRotation();
-        final boolean sideways = 
-            (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
-
-        final Resources res = mContext.getResources();
-        final int size = res.getDimensionPixelSize(R.dimen.navigation_bar_size);
-
         WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                sideways ? size : ViewGroup.LayoutParams.MATCH_PARENT,
-                sideways ? ViewGroup.LayoutParams.MATCH_PARENT : size,
+                LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT,
                 WindowManager.LayoutParams.TYPE_NAVIGATION_BAR,
                     0
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
-                    | WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS
                     | WindowManager.LayoutParams.FLAG_TOUCHABLE_WHEN_WAKING
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
                     | WindowManager.LayoutParams.FLAG_SPLIT_TOUCH
@@ -494,21 +484,6 @@
         }
 
         lp.setTitle("NavigationBar");
-        switch (rotation) {
-            case Surface.ROTATION_90:
-                // device has been turned 90deg counter-clockwise
-                lp.gravity = Gravity.RIGHT | Gravity.FILL_VERTICAL;
-                break;
-            case Surface.ROTATION_270:
-                // device has been turned 90deg clockwise
-                lp.gravity = (NavigationBarView.NAVBAR_ALWAYS_AT_RIGHT ? Gravity.RIGHT
-                                                                       : Gravity.LEFT) 
-                             | Gravity.FILL_VERTICAL;
-                break;
-            default:
-                lp.gravity = Gravity.BOTTOM | Gravity.FILL_HORIZONTAL;
-                break;
-        }
         lp.windowAnimations = 0;
 
         return lp;
@@ -1116,7 +1091,7 @@
 
         if ((diff & (StatusBarManager.DISABLE_NAVIGATION | StatusBarManager.DISABLE_BACK)) != 0) {
             // the nav bar will take care of DISABLE_NAVIGATION and DISABLE_BACK
-            mNavigationBarView.setDisabledFlags(state);
+            if (mNavigationBarView != null) mNavigationBarView.setDisabledFlags(state);
 
             if ((state & StatusBarManager.DISABLE_NAVIGATION) != 0) {
                 // close recents if it's visible
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 20088b1..903b405 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -2171,6 +2171,8 @@
                         if (mActionModePopup != null) {
                             post(mShowActionModePopup);
                         }
+                        mActionModeView.sendAccessibilityEvent(
+                                AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
                     } else {
                         mActionMode = null;
                     }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 9b51eb0..10447ad 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -345,6 +345,7 @@
     static final Rect mTmpDisplayFrame = new Rect();
     static final Rect mTmpContentFrame = new Rect();
     static final Rect mTmpVisibleFrame = new Rect();
+    static final Rect mTmpNavigationFrame = new Rect();
     
     WindowState mTopFullscreenOpaqueWindowState;
     WindowState mTopAppWindowState;
@@ -1125,27 +1126,27 @@
         return mStatusBarCanHide;
     }
 
-    public int getNonDecorDisplayWidth(int rotation, int fullWidth) {
+    public int getNonDecorDisplayWidth(int fullWidth, int fullHeight, int rotation) {
         // Assumes that the navigation bar appears on the side of the display in landscape.
-        final boolean horizontal
-            = (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90);
-        return fullWidth - (horizontal ? mNavigationBarWidth : 0);
+        if (fullWidth > fullHeight) {
+            return fullWidth - mNavigationBarWidth;
+        }
+        return fullWidth;
     }
 
-    public int getNonDecorDisplayHeight(int rotation, int fullHeight) {
-        final boolean horizontal
-            = (rotation == Surface.ROTATION_270 || rotation == Surface.ROTATION_90);
+    public int getNonDecorDisplayHeight(int fullWidth, int fullHeight, int rotation) {
+        // Assumes the navigation bar appears on the bottom of the display in portrait.
         return fullHeight
             - (mStatusBarCanHide ? 0 : mStatusBarHeight)
-            - (horizontal ? 0 : mNavigationBarHeight);
+            - ((fullWidth > fullHeight) ? 0 : mNavigationBarHeight);
     }
 
-    public int getConfigDisplayWidth(int rotation, int fullWidth) {
-        return getNonDecorDisplayWidth(rotation, fullWidth);
+    public int getConfigDisplayWidth(int fullWidth, int fullHeight, int rotation) {
+        return getNonDecorDisplayWidth(fullWidth, fullHeight, rotation);
     }
 
-    public int getConfigDisplayHeight(int rotation, int fullHeight) {
-        return getNonDecorDisplayHeight(rotation, fullHeight);
+    public int getConfigDisplayHeight(int fullWidth, int fullHeight, int rotation) {
+        return getNonDecorDisplayHeight(fullWidth, fullHeight, rotation);
     }
 
     public boolean doesForceHide(WindowState win, WindowManager.LayoutParams attrs) {
@@ -1687,7 +1688,7 @@
     }
     
     /** {@inheritDoc} */
-    public void beginLayoutLw(int displayWidth, int displayHeight) {
+    public void beginLayoutLw(int displayWidth, int displayHeight, int displayRotation) {
         mUnrestrictedScreenLeft = mUnrestrictedScreenTop = 0;
         mUnrestrictedScreenWidth = displayWidth;
         mUnrestrictedScreenHeight = displayHeight;
@@ -1713,30 +1714,33 @@
         if (mStatusBar != null) {
             Rect navr = null;
             if (mNavigationBar != null) {
-                mNavigationBar.computeFrameLw(pf, df, vf, vf);
-                if (mNavigationBar.isVisibleLw()) {
-                    navr = mNavigationBar.getFrameLw();
-
-                    if (navr.top == 0) {
-                        // Navigation bar is vertical
-                        if (mDockLeft == navr.left) {
-                            mDockLeft = navr.right;
-                        } else if (mDockRight == navr.right) {
-                            mDockRight = navr.left;
-                        }
-                    } else {
-                        // Navigation bar horizontal, at bottom
-                        if (mDockBottom == navr.bottom) {
-                            mDockBottom = navr.top;
-                        }
+                // Force the navigation bar to its appropriate place and
+                // size.  We need to do this directly, instead of relying on
+                // it to bubble up from the nav bar, because this needs to
+                // change atomically with screen rotations.
+                if (displayWidth < displayHeight) {
+                    // Portrait screen; nav bar goes on bottom.
+                    mTmpNavigationFrame.set(0, displayHeight-mNavigationBarHeight,
+                            displayWidth, displayHeight);
+                    if (mNavigationBar.isVisibleLw()) {
+                        mDockBottom = mTmpNavigationFrame.top;
+                        mRestrictedScreenHeight = mDockBottom - mDockTop;
+                    }
+                } else {
+                    // Landscape screen; nav bar goes to the right.
+                    mTmpNavigationFrame.set(displayWidth-mNavigationBarWidth, 0,
+                            displayWidth, displayHeight);
+                    if (mNavigationBar.isVisibleLw()) {
+                        mDockRight = mTmpNavigationFrame.left;
+                        mRestrictedScreenWidth = mDockRight - mDockLeft;
                     }
                 }
+                mNavigationBar.computeFrameLw(mTmpNavigationFrame, mTmpNavigationFrame,
+                        mTmpNavigationFrame, mTmpNavigationFrame);
+                if (DEBUG_LAYOUT) Log.i(TAG, "mNavigationBar frame: " + mTmpNavigationFrame);
             }
-            if (DEBUG_LAYOUT) {
-                Log.i(TAG, "mNavigationBar frame: " + navr);
-                Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
-                            mDockLeft, mDockTop, mDockRight, mDockBottom));
-            }
+            if (DEBUG_LAYOUT) Log.i(TAG, String.format("mDock rect: (%d,%d - %d,%d)",
+                    mDockLeft, mDockTop, mDockRight, mDockBottom));
 
             // apply navigation bar insets
             pf.left = df.left = vf.left = mDockLeft;
@@ -1746,25 +1750,6 @@
 
             mStatusBar.computeFrameLw(pf, df, vf, vf);
 
-            // now, let's consider the navigation bar; if it exists, it must be removed from the
-            // available screen real estate (like an un-hideable status bar)
-            if (navr != null) {
-                if (navr.top == 0) {
-                    // Navigation bar is vertical
-                    if (mRestrictedScreenLeft == navr.left) {
-                        mRestrictedScreenLeft = navr.right;
-                        mRestrictedScreenWidth -= (navr.right - navr.left);
-                    } else if ((mRestrictedScreenLeft+mRestrictedScreenWidth) == navr.right) {
-                        mRestrictedScreenWidth -= (navr.right - navr.left);
-                    }
-                } else {
-                    // Navigation bar horizontal, at bottom
-                    if ((mRestrictedScreenHeight+mRestrictedScreenTop) == navr.bottom) {
-                        mRestrictedScreenHeight -= (navr.bottom-navr.top);
-                    }
-                }
-            }
-
             if (mStatusBar.isVisibleLw()) {
                 // If the status bar is hidden, we don't want to cause
                 // windows behind it to scroll.
@@ -1862,7 +1847,7 @@
     public void layoutWindowLw(WindowState win, WindowManager.LayoutParams attrs,
             WindowState attached) {
         // we've already done the status bar
-        if (win == mStatusBar) {
+        if (win == mStatusBar || win == mNavigationBar) {
             return;
         }
 
diff --git a/services/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
index 10d384b..6830055 100644
--- a/services/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -489,14 +489,16 @@
             if (oldService != null) {
                 tryRemoveServiceLocked(oldService);
             }
+            // Now this service is enabled.
+            mEnabledServices.add(componentName);
+            // Also make sure this service is the only one.
+            Settings.Secure.putString(mContext.getContentResolver(),
+                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES,
+                    componentName.flattenToString());
             // This API is intended for testing so enable accessibility to make
             // sure clients can start poking with the window content.
             Settings.Secure.putInt(mContext.getContentResolver(),
                     Settings.Secure.ACCESSIBILITY_ENABLED, 1);
-            // Also disable all accessibility services to avoid interference
-            // with the tests.
-            Settings.Secure.putString(mContext.getContentResolver(),
-                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES, "");
         }
         AccessibilityServiceInfo accessibilityServiceInfo = new AccessibilityServiceInfo();
         accessibilityServiceInfo.eventTypes = AccessibilityEvent.TYPES_ALL_MASK;
diff --git a/services/java/com/android/server/net/NetworkPolicyManagerService.java b/services/java/com/android/server/net/NetworkPolicyManagerService.java
index 9067fae..0da5cc6 100644
--- a/services/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -572,8 +572,7 @@
         switch (type) {
             case TYPE_WARNING: {
                 final CharSequence title = res.getText(R.string.data_usage_warning_title);
-                final CharSequence body = res.getString(R.string.data_usage_warning_body,
-                        Formatter.formatFileSize(mContext, policy.warningBytes));
+                final CharSequence body = res.getString(R.string.data_usage_warning_body);
 
                 builder.setSmallIcon(R.drawable.ic_menu_info_details);
                 builder.setTicker(title);
diff --git a/services/java/com/android/server/net/NetworkStatsService.java b/services/java/com/android/server/net/NetworkStatsService.java
index af29d85..a2b097e 100644
--- a/services/java/com/android/server/net/NetworkStatsService.java
+++ b/services/java/com/android/server/net/NetworkStatsService.java
@@ -34,6 +34,7 @@
 import static android.net.NetworkTemplate.buildTemplateMobileAll;
 import static android.net.NetworkTemplate.buildTemplateWifi;
 import static android.net.TrafficStats.UID_REMOVED;
+import static android.provider.Settings.Secure.NETSTATS_FORCE_COMPLETE_POLL;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_BUCKET_DURATION;
 import static android.provider.Settings.Secure.NETSTATS_NETWORK_MAX_HISTORY;
 import static android.provider.Settings.Secure.NETSTATS_PERSIST_THRESHOLD;
@@ -176,6 +177,7 @@
         public long getUidMaxHistory();
         public long getTagMaxHistory();
         public long getTimeCacheMaxAge();
+        public boolean getForceCompletePoll();
     }
 
     private final Object mStatsLock = new Object();
@@ -682,8 +684,16 @@
         if (LOGV) Slog.v(TAG, "performPollLocked(flags=0x" + Integer.toHexString(flags) + ")");
         final long startRealtime = SystemClock.elapsedRealtime();
 
-        final boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0;
-        final boolean pollUid = (flags & FLAG_POLL_UID) != 0;
+        boolean pollNetwork = (flags & FLAG_POLL_NETWORK) != 0;
+        boolean pollUid = (flags & FLAG_POLL_UID) != 0;
+
+        // when complete poll requested, any partial poll enables everything
+        final boolean forceCompletePoll = mSettings.getForceCompletePoll();
+        if (forceCompletePoll && (pollNetwork || pollUid)) {
+            pollNetwork = true;
+            pollUid = true;
+        }
+
         final boolean persistNetwork = (flags & FLAG_PERSIST_NETWORK) != 0;
         final boolean persistUid = (flags & FLAG_PERSIST_UID) != 0;
         final boolean forcePersist = (flags & FLAG_FORCE_PERSIST) != 0;
@@ -1360,6 +1370,10 @@
         private long getSecureLong(String name, long def) {
             return Settings.Secure.getLong(mResolver, name, def);
         }
+        private boolean getSecureBoolean(String name, boolean def) {
+            final int defInt = def ? 1 : 0;
+            return Settings.Secure.getInt(mResolver, name, defInt) != 0;
+        }
 
         public long getPollInterval() {
             return getSecureLong(NETSTATS_POLL_INTERVAL, 30 * MINUTE_IN_MILLIS);
@@ -1385,5 +1399,8 @@
         public long getTimeCacheMaxAge() {
             return DAY_IN_MILLIS;
         }
+        public boolean getForceCompletePoll() {
+            return getSecureBoolean(NETSTATS_FORCE_COMPLETE_POLL, false);
+        }
     }
 }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 5a7fc9f..609016b 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -5701,8 +5701,8 @@
         return config;
     }
 
-    private int reduceConfigWidthSize(int curSize, int rotation, float density, int dw) {
-        int size = (int)(mPolicy.getConfigDisplayWidth(rotation, dw) / density);
+    private int reduceConfigWidthSize(int curSize, int rotation, float density, int dw, int dh) {
+        int size = (int)(mPolicy.getConfigDisplayWidth(dw, dh, rotation) / density);
         if (size < curSize) {
             curSize = size;
         }
@@ -5722,17 +5722,17 @@
             unrotDw = dw;
             unrotDh = dh;
         }
-        int sw = reduceConfigWidthSize(unrotDw, Surface.ROTATION_0, density, unrotDw);
-        sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDh);
-        sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw);
-        sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDh);
+        int sw = reduceConfigWidthSize(unrotDw, Surface.ROTATION_0, density, unrotDw, unrotDh);
+        sw = reduceConfigWidthSize(sw, Surface.ROTATION_90, density, unrotDw, unrotDh);
+        sw = reduceConfigWidthSize(sw, Surface.ROTATION_180, density, unrotDw, unrotDh);
+        sw = reduceConfigWidthSize(sw, Surface.ROTATION_270, density, unrotDw, unrotDh);
         return sw;
     }
 
     private int reduceCompatConfigWidthSize(int curSize, int rotation, DisplayMetrics dm,
             int dw, int dh) {
-        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(rotation, dw);
-        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(rotation, dh);
+        dm.noncompatWidthPixels = mPolicy.getNonDecorDisplayWidth(dw, dh, rotation);
+        dm.noncompatHeightPixels = mPolicy.getNonDecorDisplayHeight(dw, dh, rotation);
         float scale = CompatibilityInfo.computeCompatibleScaling(dm, null);
         int size = (int)(((dm.noncompatWidthPixels / scale) / dm.density) + .5f);
         if (curSize == 0 || size < curSize) {
@@ -5809,15 +5809,17 @@
 
         // Update application display metrics.
         final DisplayMetrics dm = mDisplayMetrics;
-        mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(mRotation, dw);
-        mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(mRotation, dh);
+        mAppDisplayWidth = mPolicy.getNonDecorDisplayWidth(dw, dh, mRotation);
+        mAppDisplayHeight = mPolicy.getNonDecorDisplayHeight(dw, dh, mRotation);
         mDisplay.getMetricsWithSize(dm, mAppDisplayWidth, mAppDisplayHeight);
 
         mCompatibleScreenScale = CompatibilityInfo.computeCompatibleScaling(dm,
                 mCompatDisplayMetrics);
 
-        config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(mRotation, dw) / dm.density);
-        config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(mRotation, dh) / dm.density);
+        config.screenWidthDp = (int)(mPolicy.getConfigDisplayWidth(dw, dh, mRotation)
+                / dm.density);
+        config.screenHeightDp = (int)(mPolicy.getConfigDisplayHeight(dw, dh, mRotation)
+                / dm.density);
         config.smallestScreenWidthDp = computeSmallestWidth(rotated, dw, dh, dm.density);
 
         config.compatScreenWidthDp = (int)(config.screenWidthDp / mCompatibleScreenScale);
@@ -7151,7 +7153,7 @@
         if (DEBUG_LAYOUT) Slog.v(TAG, "performLayout: needed="
                 + mLayoutNeeded + " dw=" + dw + " dh=" + dh);
         
-        mPolicy.beginLayoutLw(dw, dh);
+        mPolicy.beginLayoutLw(dw, dh, mRotation);
 
         int seq = mLayoutSeq+1;
         if (seq < 0) seq = 0;
diff --git a/services/sensorservice/Fusion.cpp b/services/sensorservice/Fusion.cpp
index 0ab86c3..d76f19c 100644
--- a/services/sensorservice/Fusion.cpp
+++ b/services/sensorservice/Fusion.cpp
@@ -167,6 +167,9 @@
     Bm.y = 1;
     Bm.z = 0;
 
+    x0 = 0;
+    x1 = 0;
+
     init();
 }
 
diff --git a/services/sensorservice/SensorDevice.cpp b/services/sensorservice/SensorDevice.cpp
index 38d498c..d82a7e2 100644
--- a/services/sensorservice/SensorDevice.cpp
+++ b/services/sensorservice/SensorDevice.cpp
@@ -138,9 +138,18 @@
 
     Mutex::Autolock _l(mLock);
     for (size_t i=0 ; i<size_t(count) ; i++) {
-        snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d\n",
+        const Info& info = mActivationCount.valueFor(list[i].handle);
+        snprintf(buffer, SIZE, "handle=0x%08x, active-count=%d, rates(ms)={ ",
                 list[i].handle,
-                mActivationCount.valueFor(list[i].handle).rates.size());
+                info.rates.size());
+        result.append(buffer);
+        for (size_t j=0 ; j<info.rates.size() ; j++) {
+            snprintf(buffer, SIZE, "%4.1f%s",
+                    info.rates.valueAt(j) / 1e6f,
+                    j<info.rates.size()-1 ? ", " : "");
+            result.append(buffer);
+        }
+        snprintf(buffer, SIZE, " }, selected=%4.1f ms\n",  info.delay / 1e6f);
         result.append(buffer);
     }
 }
@@ -217,17 +226,9 @@
         }
     }
 
-    if (!actuateHardware || enabled) {
+    { // scope for the lock
         Mutex::Autolock _l(mLock);
-        nsecs_t ns = info.rates.valueAt(0);
-        for (size_t i=1 ; i<info.rates.size() ; i++) {
-            if (info.rates.valueAt(i) < ns) {
-                nsecs_t cur = info.rates.valueAt(i);
-                if (cur < ns) {
-                    ns = cur;
-                }
-            }
-        }
+        nsecs_t ns = info.selectDelay();
         mSensorDevice->setDelay(mSensorDevice, handle, ns);
     }
 
@@ -237,24 +238,39 @@
 status_t SensorDevice::setDelay(void* ident, int handle, int64_t ns)
 {
     if (!mSensorDevice) return NO_INIT;
+    Mutex::Autolock _l(mLock);
     Info& info( mActivationCount.editValueFor(handle) );
-    { // scope for lock
-        Mutex::Autolock _l(mLock);
-        ssize_t index = info.rates.indexOfKey(ident);
-        if (index < 0) return BAD_INDEX;
-        info.rates.editValueAt(index) = ns;
-        ns = info.rates.valueAt(0);
-        for (size_t i=1 ; i<info.rates.size() ; i++) {
-            nsecs_t cur = info.rates.valueAt(i);
-            if (cur < ns) {
-                ns = cur;
-            }
+    status_t err = info.setDelayForIdent(ident, ns);
+    if (err < 0) return err;
+    ns = info.selectDelay();
+    return mSensorDevice->setDelay(mSensorDevice, handle, ns);
+}
+
+// ---------------------------------------------------------------------------
+
+status_t SensorDevice::Info::setDelayForIdent(void* ident, int64_t ns)
+{
+    ssize_t index = rates.indexOfKey(ident);
+    if (index < 0) {
+        LOGE("Info::setDelayForIdent(ident=%p, ns=%lld) failed (%s)",
+                ident, ns, strerror(-index));
+        return BAD_INDEX;
+    }
+    rates.editValueAt(index) = ns;
+    return NO_ERROR;
+}
+
+nsecs_t SensorDevice::Info::selectDelay()
+{
+    nsecs_t ns = rates.valueAt(0);
+    for (size_t i=1 ; i<rates.size() ; i++) {
+        nsecs_t cur = rates.valueAt(i);
+        if (cur < ns) {
+            ns = cur;
         }
     }
-
-    //LOGD("setDelay: ident=%p, handle=%d, ns=%lld", ident, handle, ns);
-
-    return mSensorDevice->setDelay(mSensorDevice, handle, ns);
+    delay = ns;
+    return ns;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/sensorservice/SensorDevice.h b/services/sensorservice/SensorDevice.h
index c19b2ce..728b6cb 100644
--- a/services/sensorservice/SensorDevice.h
+++ b/services/sensorservice/SensorDevice.h
@@ -37,11 +37,14 @@
     friend class Singleton<SensorDevice>;
     struct sensors_poll_device_t* mSensorDevice;
     struct sensors_module_t* mSensorModule;
-    Mutex mLock; // protect mActivationCount[].rates
+    mutable Mutex mLock; // protect mActivationCount[].rates
     // fixed-size array after construction
     struct Info {
-        Info() { }
+        Info() : delay(0) { }
         KeyedVector<void*, nsecs_t> rates;
+        nsecs_t delay;
+        status_t setDelayForIdent(void* ident, int64_t ns);
+        nsecs_t selectDelay();
     };
     DefaultKeyedVector<int, Info> mActivationCount;
 
diff --git a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
index e7f1d9a..2b1eea1 100644
--- a/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
+++ b/services/tests/servicestests/src/com/android/server/NetworkStatsServiceTest.java
@@ -758,6 +758,7 @@
         expect(mSettings.getUidMaxHistory()).andReturn(maxHistory).anyTimes();
         expect(mSettings.getTagMaxHistory()).andReturn(maxHistory).anyTimes();
         expect(mSettings.getTimeCacheMaxAge()).andReturn(DAY_IN_MILLIS).anyTimes();
+        expect(mSettings.getForceCompletePoll()).andReturn(false).anyTimes();
     }
 
     private void expectCurrentTime() throws Exception {