Merge "Fix audio focus evaluation order for display update" into jb-mr1.1-dev
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index ff44475..1747627 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -623,6 +623,7 @@
  * @attr ref android.R.styleable#View_hapticFeedbackEnabled
  * @attr ref android.R.styleable#View_keepScreenOn
  * @attr ref android.R.styleable#View_layerType
+ * @attr ref android.R.styleable#View_layoutDirection
  * @attr ref android.R.styleable#View_longClickable
  * @attr ref android.R.styleable#View_minHeight
  * @attr ref android.R.styleable#View_minWidth
@@ -660,6 +661,7 @@
  * @attr ref android.R.styleable#View_soundEffectsEnabled
  * @attr ref android.R.styleable#View_tag
  * @attr ref android.R.styleable#View_textAlignment
+ * @attr ref android.R.styleable#View_textDirection
  * @attr ref android.R.styleable#View_transformPivotX
  * @attr ref android.R.styleable#View_transformPivotY
  * @attr ref android.R.styleable#View_translationX
@@ -5854,6 +5856,7 @@
      *   {@link #LAYOUT_DIRECTION_RTL},
      *   {@link #LAYOUT_DIRECTION_INHERIT} or
      *   {@link #LAYOUT_DIRECTION_LOCALE}.
+     *
      * @attr ref android.R.styleable#View_layoutDirection
      *
      * @hide
@@ -5909,6 +5912,8 @@
      *
      * For compatibility, this will return {@link #LAYOUT_DIRECTION_LTR} if API version
      * is lower than {@link android.os.Build.VERSION_CODES#JELLY_BEAN_MR1}.
+     *
+     * @attr ref android.R.styleable#View_layoutDirection
      */
     @ViewDebug.ExportedProperty(category = "layout", mapping = {
         @ViewDebug.IntToString(from = LAYOUT_DIRECTION_LTR, to = "RESOLVED_DIRECTION_LTR"),
@@ -16627,6 +16632,8 @@
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
      *
+     * @attr ref android.R.styleable#View_textDirection
+     *
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
@@ -16656,6 +16663,8 @@
      * Resolution will be done if the value is set to TEXT_DIRECTION_INHERIT. The resolution
      * proceeds up the parent chain of the view to get the value. If there is no parent, then it will
      * return the default {@link #TEXT_DIRECTION_FIRST_STRONG}.
+     *
+     * @attr ref android.R.styleable#View_textDirection
      */
     public void setTextDirection(int textDirection) {
         if (getRawTextDirection() != textDirection) {
@@ -16684,6 +16693,8 @@
      * {@link #TEXT_DIRECTION_LTR},
      * {@link #TEXT_DIRECTION_RTL},
      * {@link #TEXT_DIRECTION_LOCALE}
+     *
+     * @attr ref android.R.styleable#View_textDirection
      */
     public int getTextDirection() {
         return (mPrivateFlags2 & PFLAG2_TEXT_DIRECTION_RESOLVED_MASK) >> PFLAG2_TEXT_DIRECTION_RESOLVED_MASK_SHIFT;
@@ -16816,6 +16827,8 @@
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
      *
+     * @attr ref android.R.styleable#View_textAlignment
+     *
      * @hide
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
@@ -16879,6 +16892,8 @@
      * {@link #TEXT_ALIGNMENT_TEXT_END},
      * {@link #TEXT_ALIGNMENT_VIEW_START},
      * {@link #TEXT_ALIGNMENT_VIEW_END}
+     *
+     * @attr ref android.R.styleable#View_textAlignment
      */
     @ViewDebug.ExportedProperty(category = "text", mapping = {
             @ViewDebug.IntToString(from = TEXT_ALIGNMENT_INHERIT, to = "INHERIT"),
diff --git a/core/java/android/widget/Editor.java b/core/java/android/widget/Editor.java
index 521e686..85972c3 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -309,13 +309,15 @@
     }
 
     private void setErrorIcon(Drawable icon) {
-        final Drawables dr = mTextView.mDrawables;
-        if (dr != null) {
-            mTextView.setCompoundDrawables(dr.mDrawableLeft, dr.mDrawableTop, icon,
-                    dr.mDrawableBottom);
-        } else {
-            mTextView.setCompoundDrawables(null, null, icon, null);
+        Drawables dr = mTextView.mDrawables;
+        if (dr == null) {
+            mTextView.mDrawables = dr = new Drawables();
         }
+        dr.setErrorDrawable(icon, mTextView);
+
+        mTextView.resetResolvedDrawables();
+        mTextView.invalidate();
+        mTextView.requestLayout();
     }
 
     private void hideError() {
@@ -329,7 +331,7 @@
     }
 
     /**
-     * Returns the Y offset to make the pointy top of the error point
+     * Returns the X offset to make the pointy top of the error point
      * at the middle of the error icon.
      */
     private int getErrorX() {
@@ -340,8 +342,23 @@
         final float scale = mTextView.getResources().getDisplayMetrics().density;
 
         final Drawables dr = mTextView.mDrawables;
-        return mTextView.getWidth() - mErrorPopup.getWidth() - mTextView.getPaddingRight() -
-                (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+
+        final int layoutDirection = mTextView.getLayoutDirection();
+        int errorX;
+        int offset;
+        switch (layoutDirection) {
+            default:
+            case View.LAYOUT_DIRECTION_LTR:
+                offset = - (dr != null ? dr.mDrawableSizeRight : 0) / 2 + (int) (25 * scale + 0.5f);
+                errorX = mTextView.getWidth() - mErrorPopup.getWidth() -
+                        mTextView.getPaddingRight() + offset;
+                break;
+            case View.LAYOUT_DIRECTION_RTL:
+                offset = (dr != null ? dr.mDrawableSizeLeft : 0) / 2 - (int) (25 * scale + 0.5f);
+                errorX = mTextView.getPaddingLeft() + offset;
+                break;
+        }
+        return errorX;
     }
 
     /**
@@ -358,16 +375,27 @@
                 mTextView.getCompoundPaddingBottom() - compoundPaddingTop;
 
         final Drawables dr = mTextView.mDrawables;
-        int icontop = compoundPaddingTop +
-                (vspace - (dr != null ? dr.mDrawableHeightRight : 0)) / 2;
+
+        final int layoutDirection = mTextView.getLayoutDirection();
+        int height;
+        switch (layoutDirection) {
+            default:
+            case View.LAYOUT_DIRECTION_LTR:
+                height = (dr != null ? dr.mDrawableHeightRight : 0);
+                break;
+            case View.LAYOUT_DIRECTION_RTL:
+                height = (dr != null ? dr.mDrawableHeightLeft : 0);
+                break;
+        }
+
+        int icontop = compoundPaddingTop + (vspace - height) / 2;
 
         /*
          * The "2" is the distance between the point and the top edge
          * of the background.
          */
         final float scale = mTextView.getResources().getDisplayMetrics().density;
-        return icontop + (dr != null ? dr.mDrawableHeightRight : 0) - mTextView.getHeight() -
-                (int) (2 * scale + 0.5f);
+        return icontop + height - mTextView.getHeight() - (int) (2 * scale + 0.5f);
     }
 
     void createInputContentTypeIfNeeded() {
@@ -3726,7 +3754,7 @@
             super(v, width, height);
             mView = v;
             // Make sure the TextView has a background set as it will be used the first time it is
-            // shown and positionned. Initialized with below background, which should have
+            // shown and positioned. Initialized with below background, which should have
             // dimensions identical to the above version for this to work (and is more likely).
             mPopupInlineErrorBackgroundId = getResourceId(mPopupInlineErrorBackgroundId,
                     com.android.internal.R.styleable.Theme_errorMessageBackground);
diff --git a/core/java/android/widget/NumberPicker.java b/core/java/android/widget/NumberPicker.java
index 4918e48..ac21671 100644
--- a/core/java/android/widget/NumberPicker.java
+++ b/core/java/android/widget/NumberPicker.java
@@ -1284,7 +1284,12 @@
     /**
      * Sets the min value of the picker.
      *
-     * @param minValue The min value.
+     * @param minValue The min value inclusive.
+     *
+     * <strong>Note:</strong> The length of the displayed values array
+     * set via {@link #setDisplayedValues(String[])} must be equal to the
+     * range of selectable numbers which is equal to
+     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
      */
     public void setMinValue(int minValue) {
         if (mMinValue == minValue) {
@@ -1317,7 +1322,12 @@
     /**
      * Sets the max value of the picker.
      *
-     * @param maxValue The max value.
+     * @param maxValue The max value inclusive.
+     *
+     * <strong>Note:</strong> The length of the displayed values array
+     * set via {@link #setDisplayedValues(String[])} must be equal to the
+     * range of selectable numbers which is equal to
+     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
      */
     public void setMaxValue(int maxValue) {
         if (mMaxValue == maxValue) {
@@ -1351,6 +1361,10 @@
      * Sets the values to be displayed.
      *
      * @param displayedValues The displayed values.
+     *
+     * <strong>Note:</strong> The length of the displayed values array
+     * must be equal to the range of selectable numbers which is equal to
+     * {@link #getMaxValue()} - {@link #getMinValue()} + 1.
      */
     public void setDisplayedValues(String[] displayedValues) {
         if (mDisplayedValues == displayedValues) {
@@ -1361,14 +1375,6 @@
             // Allow text entry rather than strictly numeric entry.
             mInputText.setRawInputType(InputType.TYPE_CLASS_TEXT
                     | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
-            // Make sure the min, max, respect the size of the displayed
-            // values. This will take care of the current value as well.
-            if (getMinValue() >= displayedValues.length) {
-                setMinValue(0);
-            }
-            if (getMaxValue() >= displayedValues.length) {
-                setMaxValue(displayedValues.length - 1);
-            }
         } else {
             mInputText.setRawInputType(InputType.TYPE_CLASS_NUMBER);
         }
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 267b22a..0a16a66 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -284,15 +284,144 @@
     private TextUtils.TruncateAt mEllipsize;
 
     static class Drawables {
+        final static int DRAWABLE_NONE = -1;
+        final static int DRAWABLE_RIGHT = 0;
+        final static int DRAWABLE_LEFT = 1;
+
         final Rect mCompoundRect = new Rect();
+
         Drawable mDrawableTop, mDrawableBottom, mDrawableLeft, mDrawableRight,
-                mDrawableStart, mDrawableEnd;
+                mDrawableStart, mDrawableEnd, mDrawableError, mDrawableTemp;
+
         int mDrawableSizeTop, mDrawableSizeBottom, mDrawableSizeLeft, mDrawableSizeRight,
-                mDrawableSizeStart, mDrawableSizeEnd;
+                mDrawableSizeStart, mDrawableSizeEnd, mDrawableSizeError, mDrawableSizeTemp;
+
         int mDrawableWidthTop, mDrawableWidthBottom, mDrawableHeightLeft, mDrawableHeightRight,
-                mDrawableHeightStart, mDrawableHeightEnd;
+                mDrawableHeightStart, mDrawableHeightEnd, mDrawableHeightError, mDrawableHeightTemp;
+
         int mDrawablePadding;
+
+        int mDrawableSaved = DRAWABLE_NONE;
+
+        public void resolveWithLayoutDirection(int layoutDirection) {
+            switch(layoutDirection) {
+                case LAYOUT_DIRECTION_RTL:
+                    if (mDrawableStart != null) {
+                        mDrawableRight = mDrawableStart;
+
+                        mDrawableSizeRight = mDrawableSizeStart;
+                        mDrawableHeightRight = mDrawableHeightStart;
+                    }
+                    if (mDrawableEnd != null) {
+                        mDrawableLeft = mDrawableEnd;
+
+                        mDrawableSizeLeft = mDrawableSizeEnd;
+                        mDrawableHeightLeft = mDrawableHeightEnd;
+                    }
+                    break;
+
+                case LAYOUT_DIRECTION_LTR:
+                default:
+                    if (mDrawableStart != null) {
+                        mDrawableLeft = mDrawableStart;
+
+                        mDrawableSizeLeft = mDrawableSizeStart;
+                        mDrawableHeightLeft = mDrawableHeightStart;
+                    }
+                    if (mDrawableEnd != null) {
+                        mDrawableRight = mDrawableEnd;
+
+                        mDrawableSizeRight = mDrawableSizeEnd;
+                        mDrawableHeightRight = mDrawableHeightEnd;
+                    }
+                    break;
+            }
+            applyErrorDrawableIfNeeded(layoutDirection);
+            updateDrawablesLayoutDirection(layoutDirection);
+        }
+
+        private void updateDrawablesLayoutDirection(int layoutDirection) {
+            if (mDrawableLeft != null) {
+                mDrawableLeft.setLayoutDirection(layoutDirection);
+            }
+            if (mDrawableRight != null) {
+                mDrawableRight.setLayoutDirection(layoutDirection);
+            }
+            if (mDrawableTop != null) {
+                mDrawableTop.setLayoutDirection(layoutDirection);
+            }
+            if (mDrawableBottom != null) {
+                mDrawableBottom.setLayoutDirection(layoutDirection);
+            }
+        }
+
+        public void setErrorDrawable(Drawable dr, TextView tv) {
+            if (mDrawableError != dr && mDrawableError != null) {
+                mDrawableError.setCallback(null);
+            }
+            mDrawableError = dr;
+
+            final Rect compoundRect = mCompoundRect;
+            int[] state = tv.getDrawableState();
+
+            if (mDrawableError != null) {
+                mDrawableError.setState(state);
+                mDrawableError.copyBounds(compoundRect);
+                mDrawableError.setCallback(tv);
+                mDrawableSizeError = compoundRect.width();
+                mDrawableHeightError = compoundRect.height();
+            } else {
+                mDrawableSizeError = mDrawableHeightError = 0;
+            }
+        }
+
+        private void applyErrorDrawableIfNeeded(int layoutDirection) {
+            // first restore the initial state if needed
+            switch (mDrawableSaved) {
+                case DRAWABLE_LEFT:
+                    mDrawableLeft = mDrawableTemp;
+                    mDrawableSizeLeft = mDrawableSizeTemp;
+                    mDrawableHeightLeft = mDrawableHeightTemp;
+                    break;
+                case DRAWABLE_RIGHT:
+                    mDrawableRight = mDrawableTemp;
+                    mDrawableSizeRight = mDrawableSizeTemp;
+                    mDrawableHeightRight = mDrawableHeightTemp;
+                    break;
+                case DRAWABLE_NONE:
+                default:
+            }
+            // then, if needed, assign the Error drawable to the correct location
+            if (mDrawableError != null) {
+                switch(layoutDirection) {
+                    case LAYOUT_DIRECTION_RTL:
+                        mDrawableSaved = DRAWABLE_LEFT;
+
+                        mDrawableTemp = mDrawableLeft;
+                        mDrawableSizeTemp = mDrawableSizeLeft;
+                        mDrawableHeightTemp = mDrawableHeightLeft;
+
+                        mDrawableLeft = mDrawableError;
+                        mDrawableSizeLeft = mDrawableSizeError;
+                        mDrawableHeightLeft = mDrawableHeightError;
+                        break;
+                    case LAYOUT_DIRECTION_LTR:
+                    default:
+                        mDrawableSaved = DRAWABLE_RIGHT;
+
+                        mDrawableTemp = mDrawableRight;
+                        mDrawableSizeTemp = mDrawableSizeRight;
+                        mDrawableHeightTemp = mDrawableHeightRight;
+
+                        mDrawableRight = mDrawableError;
+                        mDrawableSizeRight = mDrawableSizeError;
+                        mDrawableHeightRight = mDrawableHeightError;
+                        break;
+                }
+            }
+        }
     }
+
     Drawables mDrawables;
 
     private CharWrapper mCharWrapper;
@@ -8263,63 +8392,10 @@
             return;
         }
         mLastLayoutDirection = layoutDirection;
-        // No drawable to resolve
-        if (mDrawables == null) {
-            return;
-        }
-        // No relative drawable to resolve
-        if (mDrawables.mDrawableStart == null && mDrawables.mDrawableEnd == null) {
-            return;
-        }
 
-        Drawables dr = mDrawables;
-        switch(layoutDirection) {
-            case LAYOUT_DIRECTION_RTL:
-                if (dr.mDrawableStart != null) {
-                    dr.mDrawableRight = dr.mDrawableStart;
-
-                    dr.mDrawableSizeRight = dr.mDrawableSizeStart;
-                    dr.mDrawableHeightRight = dr.mDrawableHeightStart;
-                }
-                if (dr.mDrawableEnd != null) {
-                    dr.mDrawableLeft = dr.mDrawableEnd;
-
-                    dr.mDrawableSizeLeft = dr.mDrawableSizeEnd;
-                    dr.mDrawableHeightLeft = dr.mDrawableHeightEnd;
-                }
-                break;
-
-            case LAYOUT_DIRECTION_LTR:
-            default:
-                if (dr.mDrawableStart != null) {
-                    dr.mDrawableLeft = dr.mDrawableStart;
-
-                    dr.mDrawableSizeLeft = dr.mDrawableSizeStart;
-                    dr.mDrawableHeightLeft = dr.mDrawableHeightStart;
-                }
-                if (dr.mDrawableEnd != null) {
-                    dr.mDrawableRight = dr.mDrawableEnd;
-
-                    dr.mDrawableSizeRight = dr.mDrawableSizeEnd;
-                    dr.mDrawableHeightRight = dr.mDrawableHeightEnd;
-                }
-                break;
-        }
-        updateDrawablesLayoutDirection(dr, layoutDirection);
-    }
-
-    private void updateDrawablesLayoutDirection(Drawables dr, int layoutDirection) {
-        if (dr.mDrawableLeft != null) {
-            dr.mDrawableLeft.setLayoutDirection(layoutDirection);
-        }
-        if (dr.mDrawableRight != null) {
-            dr.mDrawableRight.setLayoutDirection(layoutDirection);
-        }
-        if (dr.mDrawableTop != null) {
-            dr.mDrawableTop.setLayoutDirection(layoutDirection);
-        }
-        if (dr.mDrawableBottom != null) {
-            dr.mDrawableBottom.setLayoutDirection(layoutDirection);
+        // Resolve drawables
+        if (mDrawables != null) {
+            mDrawables.resolveWithLayoutDirection(layoutDirection);
         }
     }
 
@@ -8327,6 +8403,7 @@
      * @hide
      */
     protected void resetResolvedDrawables() {
+        super.resetResolvedDrawables();
         mLastLayoutDirection = -1;
     }
 
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..8b43f4e
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..20e9002
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..b5f397c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..a04d695
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..8567b1f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..7d1754c
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-hdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png
new file mode 100644
index 0000000..d2efb62
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..04d200d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-ldpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..27e8d4f
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..4ae2b91
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..8cc3b69
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..7a84200
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..8fc2e2e
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..687a691
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-mdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png
new file mode 100644
index 0000000..db91a56
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png
new file mode 100644
index 0000000..90820b5
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png
new file mode 100644
index 0000000..5989975
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png
new file mode 100644
index 0000000..3b3f87d3
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_above_holo_light.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png
new file mode 100644
index 0000000..75baba2
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_dark.9.png
Binary files differ
diff --git a/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png
new file mode 100644
index 0000000..6c0203d
--- /dev/null
+++ b/core/res/res/drawable-ldrtl-xhdpi/popup_inline_error_holo_light.9.png
Binary files differ
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 447daab..48ee429 100755
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -2107,8 +2107,8 @@
             <enum name="locale" value="3" />
         </attr>
 
-        <!-- Direction of the text. A heuristic is used to determine the resolved text direction
-             of paragraphs. -->
+        <!-- Defines the direction of the text. A heuristic is used to determine the resolved text
+              direction of paragraphs. -->
          <attr name="textDirection" format="integer">
             <!-- Default -->
             <enum name="inherit" value="0" />
@@ -2128,7 +2128,7 @@
             <enum name="locale" value="5" />
         </attr>
 
-        <!-- Alignment of the text. A heuristic is used to determine the resolved
+        <!-- Defines the alignment of the text. A heuristic is used to determine the resolved
             text alignment. -->
         <attr name="textAlignment" format="integer">
             <!-- Default -->
diff --git a/docs/html/guide/google/gcm/gcm.jd b/docs/html/guide/google/gcm/gcm.jd
index a402e8e..1762e12 100644
--- a/docs/html/guide/google/gcm/gcm.jd
+++ b/docs/html/guide/google/gcm/gcm.jd
@@ -80,7 +80,6 @@
 <ul>
   <li>It allows 3rd-party application servers to send messages to
 their Android applications.</li>
-  <li>GCM makes no guarantees about delivery or the order of messages.</li>
   <li>An Android application on an Android device doesn't need to be running to receive
 messages. The system will wake up the Android application via Intent broadcast when the  message arrives, as long as the application is set up with the proper
 broadcast receiver and permissions.</li>
diff --git a/graphics/java/android/graphics/Path.java b/graphics/java/android/graphics/Path.java
index b4f1e84d..f6b5ffc 100644
--- a/graphics/java/android/graphics/Path.java
+++ b/graphics/java/android/graphics/Path.java
@@ -59,6 +59,10 @@
         int valNative = 0;
         if (src != null) {
             valNative = src.mNativePath;
+            isSimplePath = src.isSimplePath;
+            if (src.rects != null) {
+                rects = new Region(src.rects);
+            }
         }
         mNativePath = init2(valNative);
         mDetectSimplePaths = HardwareRenderer.isAvailable();
@@ -544,6 +548,7 @@
         int dstNative = 0;
         if (dst != null) {
             dstNative = dst.mNativePath;
+            dst.isSimplePath = false;
         }
         native_offset(mNativePath, dx, dy, dstNative);
     }
@@ -555,6 +560,7 @@
      * @param dy The amount in the Y direction to offset the entire path
      */
     public void offset(float dx, float dy) {
+        isSimplePath = false;
         native_offset(mNativePath, dx, dy);
     }
 
@@ -580,6 +586,7 @@
     public void transform(Matrix matrix, Path dst) {
         int dstNative = 0;
         if (dst != null) {
+            dst.isSimplePath = false;
             dstNative = dst.mNativePath;
         }
         native_transform(mNativePath, matrix.native_instance, dstNative);
@@ -591,6 +598,7 @@
      * @param matrix The matrix to apply to the path
      */
     public void transform(Matrix matrix) {
+        isSimplePath = false;
         native_transform(mNativePath, matrix.native_instance);
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
index dbd9999..762711d 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/CameraWidgetFrame.java
@@ -18,10 +18,9 @@
 
 import android.content.Context;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
 import android.graphics.Color;
 import android.graphics.Point;
+import android.graphics.Rect;
 import android.os.Handler;
 import android.os.SystemClock;
 import android.util.Log;
@@ -53,17 +52,20 @@
     private final Handler mHandler = new Handler();
     private final KeyguardActivityLauncher mActivityLauncher;
     private final Callbacks mCallbacks;
+    private final CameraWidgetInfo mWidgetInfo;
     private final WindowManager mWindowManager;
     private final Point mRenderedSize = new Point();
-    private final int[] mScreenLocation = new int[2];
+    private final int[] mTmpLoc = new int[2];
+    private final Rect mTmpRect = new Rect();
 
-    private View mWidgetView;
     private long mLaunchCameraStart;
     private boolean mActive;
     private boolean mTransitioning;
-    private boolean mRecovering;
     private boolean mDown;
 
+    private FixedSizeFrameLayout mPreview;
+    private View mFullscreenPreview;
+
     private final Runnable mTransitionToCameraRunnable = new Runnable() {
         @Override
         public void run() {
@@ -81,21 +83,18 @@
             mActivityLauncher.launchCamera(worker, mSecureCameraActivityStartedRunnable);
         }};
 
+    private final Runnable mPostTransitionToCameraEndAction = new Runnable() {
+        @Override
+        public void run() {
+            mHandler.post(mTransitionToCameraEndAction);
+        }};
+
     private final Runnable mRecoverRunnable = new Runnable() {
         @Override
         public void run() {
             recover();
         }};
 
-    private final Runnable mRecoverEndAction = new Runnable() {
-        @Override
-        public void run() {
-            if (!mRecovering)
-                return;
-            mCallbacks.onCameraLaunchedUnsuccessfully();
-            reset();
-        }};
-
     private final Runnable mRenderRunnable = new Runnable() {
         @Override
         public void run() {
@@ -119,13 +118,43 @@
         };
     };
 
+    private static final class FixedSizeFrameLayout extends FrameLayout {
+        int width;
+        int height;
+
+        FixedSizeFrameLayout(Context context) {
+            super(context);
+        }
+
+        @Override
+        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
+            measureChildren(
+                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
+                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
+            setMeasuredDimension(width, height);
+        }
+    }
+
     private CameraWidgetFrame(Context context, Callbacks callbacks,
-            KeyguardActivityLauncher activityLauncher) {
+            KeyguardActivityLauncher activityLauncher,
+            CameraWidgetInfo widgetInfo, View previewWidget) {
         super(context);
         mCallbacks = callbacks;
         mActivityLauncher = activityLauncher;
+        mWidgetInfo = widgetInfo;
         mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
         KeyguardUpdateMonitor.getInstance(context).registerCallback(mCallback);
+
+        mPreview = new FixedSizeFrameLayout(context);
+        mPreview.addView(previewWidget);
+        addView(mPreview);
+
+        View clickBlocker = new View(context);
+        clickBlocker.setBackgroundColor(Color.TRANSPARENT);
+        clickBlocker.setOnClickListener(this);
+        addView(clickBlocker);
+
+        setContentDescription(context.getString(R.string.keyguard_accessibility_camera));
         if (DEBUG) Log.d(TAG, "new CameraWidgetFrame instance " + instanceId());
     }
 
@@ -137,24 +166,17 @@
         CameraWidgetInfo widgetInfo = launcher.getCameraWidgetInfo();
         if (widgetInfo == null)
             return null;
-        View widgetView = widgetInfo.layoutId > 0 ?
-                inflateWidgetView(context, widgetInfo) :
-                inflateGenericWidgetView(context);
-        if (widgetView == null)
+        View previewWidget = getPreviewWidget(context, widgetInfo);
+        if (previewWidget == null)
             return null;
 
-        ImageView preview = new ImageView(context);
-        preview.setLayoutParams(new FrameLayout.LayoutParams(
-                FrameLayout.LayoutParams.MATCH_PARENT,
-                FrameLayout.LayoutParams.MATCH_PARENT));
-        preview.setScaleType(ScaleType.FIT_CENTER);
-        preview.setContentDescription(preview.getContext().getString(
-                R.string.keyguard_accessibility_camera));
-        CameraWidgetFrame cameraWidgetFrame = new CameraWidgetFrame(context, callbacks, launcher);
-        cameraWidgetFrame.addView(preview);
-        cameraWidgetFrame.mWidgetView = widgetView;
-        preview.setOnClickListener(cameraWidgetFrame);
-        return cameraWidgetFrame;
+        return new CameraWidgetFrame(context, callbacks, launcher, widgetInfo, previewWidget);
+    }
+
+    private static View getPreviewWidget(Context context, CameraWidgetInfo widgetInfo) {
+        return widgetInfo.layoutId > 0 ?
+                inflateWidgetView(context, widgetInfo) :
+                inflateGenericWidgetView(context);
     }
 
     private static View inflateWidgetView(Context context, CameraWidgetInfo widgetInfo) {
@@ -188,63 +210,45 @@
         return iv;
     }
 
-    public void render() {
-        final Throwable[] thrown = new Throwable[1];
-        final Bitmap[] offscreen = new Bitmap[1];
-        try {
-            final int width = getRootView().getWidth();
-            final int height = getRootView().getHeight();
-            if (mRenderedSize.x == width && mRenderedSize.y == height) {
-                if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s",
-                        width, height));
-                return;
-            }
-            if (width == 0 || height == 0) {
-                return;
-            }
-            final long start = SystemClock.uptimeMillis();
-            offscreen[0] = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
-            final Canvas c = new Canvas(offscreen[0]);
-            mWidgetView.measure(
-                    MeasureSpec.makeMeasureSpec(width, MeasureSpec.EXACTLY),
-                    MeasureSpec.makeMeasureSpec(height, MeasureSpec.EXACTLY));
-            mWidgetView.layout(0, 0, width, height);
-            mWidgetView.draw(c);
-
-            final long end = SystemClock.uptimeMillis();
-            if (DEBUG) Log.d(TAG, String.format(
-                    "Rendered camera widget in %sms size=%sx%s instance=%s at %s",
-                    end - start,
-                    width, height,
-                    instanceId(),
-                    end));
-            mRenderedSize.set(width, height);
-        } catch (Throwable t) {
-            thrown[0] = t;
+    private void render() {
+        final View root = getRootView();
+        final int width = root.getWidth();
+        final int height = root.getHeight();
+        if (mRenderedSize.x == width && mRenderedSize.y == height) {
+            if (DEBUG) Log.d(TAG, String.format("Already rendered at size=%sx%s", width, height));
+            return;
+        }
+        if (width == 0 || height == 0) {
+            return;
         }
 
-        mHandler.post(new Runnable() {
-            @Override
-            public void run() {
-                if (thrown[0] == null) {
-                    try {
-                        ((ImageView) getChildAt(0)).setImageBitmap(offscreen[0]);
-                    } catch (Throwable t) {
-                        thrown[0] = t;
-                    }
-                }
-                if (thrown[0] == null)
-                    return;
+        mPreview.width = width;
+        mPreview.height = height;
+        mPreview.requestLayout();
 
-                Log.w(TAG, "Error rendering camera widget", thrown[0]);
-                try {
-                    removeAllViews();
-                    final View genericView = inflateGenericWidgetView(mContext);
-                    addView(genericView);
-                } catch (Throwable t) {
-                    Log.w(TAG, "Error inflating generic camera widget", t);
-                }
-            }});
+        final int thisWidth = getWidth() - getPaddingLeft() - getPaddingRight();
+        final int thisHeight = getHeight() - getPaddingTop() - getPaddingBottom();
+
+        final float pvScaleX = (float) thisWidth / width;
+        final float pvScaleY = (float) thisHeight / height;
+        final float pvScale = Math.min(pvScaleX, pvScaleY);
+
+        final int pvWidth = (int) (pvScale * width);
+        final int pvHeight = (int) (pvScale * height);
+
+        final float pvTransX = pvWidth < thisWidth ? (thisWidth - pvWidth) / 2 : 0;
+        final float pvTransY = pvHeight < thisHeight ? (thisHeight - pvHeight) / 2 : 0;
+
+        mPreview.setPivotX(0);
+        mPreview.setPivotY(0);
+        mPreview.setScaleX(pvScale);
+        mPreview.setScaleY(pvScale);
+        mPreview.setTranslationX(pvTransX);
+        mPreview.setTranslationY(pvTransY);
+
+        mRenderedSize.set(width, height);
+        if (DEBUG) Log.d(TAG, String.format("Rendered camera widget size=%sx%s instance=%s",
+                width, height, instanceId()));
     }
 
     private void transitionToCamera() {
@@ -252,55 +256,53 @@
 
         mTransitioning = true;
 
-        final View child = getChildAt(0);
-        final View root = getRootView();
-
-        final int startWidth = child.getWidth();
-        final int startHeight = child.getHeight();
-
-        final int finishWidth = root.getWidth();
-        final int finishHeight = root.getHeight();
-
-        final float scaleX = (float) finishWidth / startWidth;
-        final float scaleY = (float) finishHeight / startHeight;
-        final float scale = Math.round( Math.max(scaleX, scaleY) * 100) / 100f;
-
-        final int[] loc = new int[2];
-        root.getLocationInWindow(loc);
-        final int finishCenter = loc[1] + finishHeight / 2;
-
-        child.getLocationInWindow(loc);
-        final int startCenter = loc[1] + startHeight / 2;
-
-        if (DEBUG) Log.d(TAG, String.format("Transitioning to camera. " +
-                "(start=%sx%s, finish=%sx%s, scale=%s,%s, startCenter=%s, finishCenter=%s)",
-                startWidth, startHeight,
-                finishWidth, finishHeight,
-                scaleX, scaleY,
-                startCenter, finishCenter));
-
         enableWindowExitAnimation(false);
-        animate()
-            .scaleX(scale)
-            .scaleY(scale)
-            .translationY(finishCenter - startCenter)
-            .setDuration(WIDGET_ANIMATION_DURATION)
-            .withEndAction(mTransitionToCameraEndAction)
-            .start();
 
+        mPreview.getLocationInWindow(mTmpLoc);
+        final float pvHeight = mPreview.getHeight() * mPreview.getScaleY();
+        final float pvCenter = mTmpLoc[1] + pvHeight / 2f;
+
+        final ViewGroup root = (ViewGroup) getRootView();
+        if (mFullscreenPreview == null) {
+            mFullscreenPreview = getPreviewWidget(mContext, mWidgetInfo);
+            mFullscreenPreview.setClickable(false);
+            root.addView(mFullscreenPreview);
+        }
+
+        root.getWindowVisibleDisplayFrame(mTmpRect);
+        final float fsHeight = mTmpRect.height();
+        final float fsCenter = mTmpRect.top + fsHeight / 2;
+
+        final float fsScaleY = pvHeight / fsHeight;
+        final float fsTransY = pvCenter - fsCenter;
+        final float fsScaleX = mPreview.getScaleX();
+
+        mPreview.setVisibility(View.GONE);
+        mFullscreenPreview.setVisibility(View.VISIBLE);
+        mFullscreenPreview.setTranslationY(fsTransY);
+        mFullscreenPreview.setScaleX(fsScaleX);
+        mFullscreenPreview.setScaleY(fsScaleY);
+        mFullscreenPreview
+            .animate()
+            .scaleX(1)
+            .scaleY(1)
+            .translationX(0)
+            .translationY(0)
+            .setDuration(WIDGET_ANIMATION_DURATION)
+            .withEndAction(mPostTransitionToCameraEndAction)
+            .start();
         mCallbacks.onLaunchingCamera();
     }
 
     private void recover() {
         if (DEBUG) Log.d(TAG, "recovering at " + SystemClock.uptimeMillis());
-        mRecovering = true;
-        animate()
-            .scaleX(1)
-            .scaleY(1)
-            .translationY(0)
-            .setDuration(WIDGET_ANIMATION_DURATION)
-            .withEndAction(mRecoverEndAction)
-            .start();
+        mCallbacks.onCameraLaunchedUnsuccessfully();
+        reset();
+    }
+
+    @Override
+    public void setOnLongClickListener(OnLongClickListener l) {
+        // ignore
     }
 
     @Override
@@ -340,8 +342,8 @@
             return true;
         }
 
-        getLocationOnScreen(mScreenLocation);
-        int rawBottom = mScreenLocation[1] + getHeight();
+        getLocationOnScreen(mTmpLoc);
+        int rawBottom = mTmpLoc[1] + getHeight();
         if (event.getRawY() > rawBottom) {
             if (DEBUG) Log.d(TAG, "onUserInteraction eaten: below widget");
             return true;
@@ -388,14 +390,14 @@
         if (DEBUG) Log.d(TAG, "reset at " + SystemClock.uptimeMillis());
         mLaunchCameraStart = 0;
         mTransitioning = false;
-        mRecovering = false;
         mDown = false;
         cancelTransitionToCamera();
         mHandler.removeCallbacks(mRecoverRunnable);
-        animate().cancel();
-        setScaleX(1);
-        setScaleY(1);
-        setTranslationY(0);
+        mPreview.setVisibility(View.VISIBLE);
+        if (mFullscreenPreview != null) {
+            mFullscreenPreview.animate().cancel();
+            mFullscreenPreview.setVisibility(View.GONE);
+        }
         enableWindowExitAnimation(true);
     }
 
@@ -403,11 +405,18 @@
     protected void onSizeChanged(int w, int h, int oldw, int oldh) {
         if (DEBUG) Log.d(TAG, String.format("onSizeChanged new=%sx%s old=%sx%s at %s",
                 w, h, oldw, oldh, SystemClock.uptimeMillis()));
-        final Handler worker =  getWorkerHandler();
-        (worker != null ? worker : mHandler).post(mRenderRunnable);
+        mHandler.post(mRenderRunnable);
         super.onSizeChanged(w, h, oldw, oldh);
     }
 
+    @Override
+    public void onBouncerShowing(boolean showing) {
+        if (showing) {
+            mTransitioning = false;
+            mHandler.post(mRecoverRunnable);
+        }
+    }
+
     private void enableWindowExitAnimation(boolean isEnabled) {
         View root = getRootView();
         ViewGroup.LayoutParams lp = root.getLayoutParams();
@@ -427,15 +436,14 @@
         if (DEBUG) Log.d(TAG, "onKeyguardVisibilityChanged " + showing
                 + " at " + SystemClock.uptimeMillis());
         if (mTransitioning && !showing) {
-          mTransitioning = false;
-          mRecovering = false;
-          mHandler.removeCallbacks(mRecoverRunnable);
-          if (mLaunchCameraStart > 0) {
-              long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
-              if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
-              mLaunchCameraStart = 0;
-              onCameraLaunched();
-          }
+            mTransitioning = false;
+            mHandler.removeCallbacks(mRecoverRunnable);
+            if (mLaunchCameraStart > 0) {
+                long launchTime = SystemClock.uptimeMillis() - mLaunchCameraStart;
+                if (DEBUG) Log.d(TAG, String.format("Camera took %sms to launch", launchTime));
+                mLaunchCameraStart = 0;
+                onCameraLaunched();
+            }
         }
     }
 
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
index 3c79206..53b149c4 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetFrame.java
@@ -512,6 +512,10 @@
         return false;
     }
 
+    public void onBouncerShowing(boolean showing) {
+        // hook for subclasses
+    }
+
     public void setWorkerHandler(Handler workerHandler) {
         mWorkerHandler = workerHandler;
     }
@@ -519,4 +523,5 @@
     public Handler getWorkerHandler() {
         return mWorkerHandler;
     }
+
 }
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
index 85b5472..f62af8e4 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardWidgetPager.java
@@ -775,6 +775,9 @@
             mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
             mZoomInOutAnim.start();
         }
+        if (currentPage instanceof KeyguardWidgetFrame) {
+            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(false);
+        }
     }
 
     // Zoom out after the bouncer is initiated
@@ -800,6 +803,9 @@
             mZoomInOutAnim.setInterpolator(new DecelerateInterpolator(1.5f));
             mZoomInOutAnim.start();
         }
+        if (currentPage instanceof KeyguardWidgetFrame) {
+            ((KeyguardWidgetFrame)currentPage).onBouncerShowing(true);
+        }
     }
 
     boolean isAddPage(int pageIndex) {
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index fa84f486..e2be577 100755
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1128,13 +1128,13 @@
                 final boolean hasCustomVibrate = notification.vibrate != null;
 
                 // new in 4.2: if there was supposed to be a sound and we're in vibrate mode,
-                // and no other vibration is specified, we apply the default vibration anyway
+                // and no other vibration is specified, we fall back to vibration
                 final boolean convertSoundToVibration =
                            !hasCustomVibrate
                         && hasValidSound
                         && (audioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE);
 
-                // The DEFAULT_VIBRATE flag trumps any custom vibration.
+                // The DEFAULT_VIBRATE flag trumps any custom vibration AND the fallback.
                 final boolean useDefaultVibrate =
                         (notification.defaults & Notification.DEFAULT_VIBRATE) != 0;
 
@@ -1147,8 +1147,8 @@
                         // does not have the VIBRATE permission.
                         long identity = Binder.clearCallingIdentity();
                         try {
-                            mVibrator.vibrate(convertSoundToVibration ? mFallbackVibrationPattern
-                                                                      : mDefaultVibrationPattern,
+                            mVibrator.vibrate(useDefaultVibrate ? mDefaultVibrationPattern
+                                                                : mFallbackVibrationPattern,
                                 ((notification.flags & Notification.FLAG_INSISTENT) != 0) ? 0: -1);
                         } finally {
                             Binder.restoreCallingIdentity(identity);
diff --git a/tests/MemoryUsage/Android.mk b/tests/MemoryUsage/Android.mk
index e7bfb4f..0ab793b 100644
--- a/tests/MemoryUsage/Android.mk
+++ b/tests/MemoryUsage/Android.mk
@@ -8,7 +8,8 @@
 
 LOCAL_PACKAGE_NAME := MemoryUsage
 
-LOCAL_SDK_VERSION := 7
+LOCAL_CERTIFICATE := platform
+LOCAL_JAVA_LIBRARIES := android.test.runner
 
 include $(BUILD_PACKAGE)
 
diff --git a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
index 5e27ba7..b550957 100644
--- a/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
+++ b/tests/MemoryUsage/src/com/android/tests/memoryusage/MemoryUsageTest.java
@@ -18,14 +18,17 @@
 import android.app.ActivityManager;
 import android.app.ActivityManager.ProcessErrorStateInfo;
 import android.app.ActivityManager.RunningAppProcessInfo;
+import android.app.ActivityManagerNative;
+import android.app.IActivityManager;
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.PackageInfo;
 import android.content.pm.PackageManager;
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ResolveInfo;
 import android.os.Bundle;
 import android.os.Debug.MemoryInfo;
+import android.os.RemoteException;
+import android.os.UserHandle;
 import android.test.InstrumentationTestCase;
 import android.util.Log;
 
@@ -48,8 +51,9 @@
 
     private static final int SLEEP_TIME = 1000;
     private static final int THRESHOLD = 1024;
-    private static final int MAX_ITERATIONS = 10;
-    private static final int MIN_ITERATIONS = 4;
+    private static final int MAX_ITERATIONS = 20;
+    private static final int MIN_ITERATIONS = 6;
+    private static final int JOIN_TIMEOUT = 10000;
 
     private static final String TAG = "MemoryUsageInstrumentation";
     private static final String KEY_APPS = "apps";
@@ -58,10 +62,13 @@
     private Map<String, String> mNameToProcess;
     private Map<String, String> mNameToResultKey;
 
+    private IActivityManager mAm;
+
     public void testMemory() {
         MemoryUsageInstrumentation instrumentation =
-                    (MemoryUsageInstrumentation) getInstrumentation();
+                (MemoryUsageInstrumentation) getInstrumentation();
         Bundle args = instrumentation.getBundle();
+        mAm = ActivityManagerNative.getDefault();
 
         createMappings();
         parseArgs(args);
@@ -136,7 +143,16 @@
 
         String process = mNameToProcess.get(appName);
         Intent startIntent = mNameToIntent.get(appName);
-        getInstrumentation().getContext().startActivity(startIntent);
+
+        AppLaunchRunnable runnable = new AppLaunchRunnable(startIntent);
+        Thread t = new Thread(runnable);
+        t.start();
+        try {
+            t.join(JOIN_TIMEOUT);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
         return process;
     }
 
@@ -234,7 +250,7 @@
             }
 
             int[] pids = {
-                proc.pid };
+                    proc.pid };
 
             MemoryInfo meminfo = am.getProcessMemoryInfo(pids)[0];
             return meminfo.getTotalPss();
@@ -242,4 +258,29 @@
         }
         return -1;
     }
+
+    private class AppLaunchRunnable implements Runnable {
+        private Intent mLaunchIntent;
+
+        public AppLaunchRunnable(Intent intent) {
+            mLaunchIntent = intent;
+        }
+
+        public void run() {
+            try {
+                String mimeType = mLaunchIntent.getType();
+                if (mimeType == null && mLaunchIntent.getData() != null
+                        && "content".equals(mLaunchIntent.getData().getScheme())) {
+                    mimeType = mAm.getProviderMimeType(mLaunchIntent.getData(),
+                            UserHandle.USER_CURRENT);
+                }
+
+                mAm.startActivityAndWait(null, mLaunchIntent, mimeType,
+                        null, null, 0, mLaunchIntent.getFlags(), null, null, null,
+                        UserHandle.USER_CURRENT_OR_SELF);
+            } catch (RemoteException e) {
+                Log.w(TAG, "Error launching app", e);
+            }
+        }
+    }
 }