Merge "Clean up language in forced foreground service notifications." into jb-mr2-dev
diff --git a/api/current.txt b/api/current.txt
index c9ef978..7fe166e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -24966,14 +24966,6 @@
     field public static final int ORIENTATION_UNKNOWN = -1; // 0xffffffff
   }
 
-  public abstract interface Overlay {
-    method public abstract void add(android.graphics.drawable.Drawable);
-    method public abstract void add(android.view.View);
-    method public abstract void clear();
-    method public abstract void remove(android.graphics.drawable.Drawable);
-    method public abstract void remove(android.view.View);
-  }
-
   public class ScaleGestureDetector {
     ctor public ScaleGestureDetector(android.content.Context, android.view.ScaleGestureDetector.OnScaleGestureListener);
     method public float getCurrentSpan();
@@ -25278,7 +25270,7 @@
     method public int getNextFocusUpId();
     method public android.view.View.OnFocusChangeListener getOnFocusChangeListener();
     method public int getOverScrollMode();
-    method public android.view.Overlay getOverlay();
+    method public android.view.ViewOverlay getOverlay();
     method public int getPaddingBottom();
     method public int getPaddingEnd();
     method public int getPaddingLeft();
@@ -26019,12 +26011,23 @@
     method public abstract void onChildViewRemoved(android.view.View, android.view.View);
   }
 
+  public class ViewGroupOverlay extends android.view.ViewOverlay {
+    method public void add(android.view.View);
+    method public void remove(android.view.View);
+  }
+
   public abstract interface ViewManager {
     method public abstract void addView(android.view.View, android.view.ViewGroup.LayoutParams);
     method public abstract void removeView(android.view.View);
     method public abstract void updateViewLayout(android.view.View, android.view.ViewGroup.LayoutParams);
   }
 
+  public class ViewOverlay {
+    method public void add(android.graphics.drawable.Drawable);
+    method public void clear();
+    method public void remove(android.graphics.drawable.Drawable);
+  }
+
   public abstract interface ViewParent {
     method public abstract void bringChildToFront(android.view.View);
     method public abstract void childDrawableStateChanged(android.view.View);
diff --git a/core/java/android/animation/RectEvaluator.java b/core/java/android/animation/RectEvaluator.java
index 10932bb..28d496b 100644
--- a/core/java/android/animation/RectEvaluator.java
+++ b/core/java/android/animation/RectEvaluator.java
@@ -18,7 +18,7 @@
 import android.graphics.Rect;
 
 /**
- * This evaluator can be used to perform type interpolation between <code>int</code> values.
+ * This evaluator can be used to perform type interpolation between <code>Rect</code> values.
  */
 public class RectEvaluator implements TypeEvaluator<Rect> {
 
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index ebca0414..a7543a8 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1603,7 +1603,7 @@
             n.defaults = mDefaults;
             n.flags = mFlags;
             n.bigContentView = makeBigContentView();
-            if (mLedOnMs != 0 && mLedOffMs != 0) {
+            if (mLedOnMs != 0 || mLedOffMs != 0) {
                 n.flags |= FLAG_SHOW_LIGHTS;
             }
             if ((mDefaults & DEFAULT_LIGHTS) != 0) {
diff --git a/core/java/android/view/Overlay.java b/core/java/android/view/Overlay.java
deleted file mode 100644
index 6630752..0000000
--- a/core/java/android/view/Overlay.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright (C) 2013 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package android.view;
-
-import android.graphics.drawable.Drawable;
-
-/**
- * An overlay is an extra layer that sits on top of a View (the "host view")
- * which is drawn after all other content in that view (including children,
- * if the view is a ViewGroup). Interaction with the overlay layer is done in
- * terms of adding/removing views and drawables.
- *
- * @see android.view.View#getOverlay()
- */
-public interface Overlay {
-
-    /**
-     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
-     * the host view. Any drawable added to the overlay should be removed when it is no longer
-     * needed or no longer visible.
-     *
-     * @param drawable The Drawable to be added to the overlay. This drawable will be
-     * drawn when the view redraws its overlay.
-     * @see #remove(android.graphics.drawable.Drawable)
-     * @see #add(View)
-     */
-    void add(Drawable drawable);
-
-    /**
-     * Removes the specified Drawable from the overlay.
-     *
-     * @param drawable The Drawable to be removed from the overlay.
-     * @see #add(android.graphics.drawable.Drawable)
-     */
-    void remove(Drawable drawable);
-
-    /**
-     * Adds a View to the overlay. The bounds of the added view should be
-     * relative to the host view. Any view added to the overlay should be
-     * removed when it is no longer needed or no longer visible.
-     *
-     * <p>If the view has a parent, the view will be removed from that parent
-     * before being added to the overlay. Also, the view will be repositioned
-     * such that it is in the same relative location inside the activity. For
-     * example, if the view's current parent lies 100 pixels to the right
-     * and 200 pixels down from the origin of the overlay's
-     * host view, then the view will be offset by (100, 200).</p>
-     *
-     * @param view The View to be added to the overlay. The added view will be
-     * drawn when the overlay is drawn.
-     * @see #remove(View)
-     * @see #add(android.graphics.drawable.Drawable)
-     */
-    void add(View view);
-
-    /**
-     * Removes the specified View from the overlay.
-     *
-     * @param view The View to be removed from the overlay.
-     * @see #add(View)
-     */
-    void remove(View view);
-
-    /**
-     * Removes all views and drawables from the overlay.
-     */
-    void clear();
-}
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 3b06da71..a520e17 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -12107,7 +12107,7 @@
         //System.out.println("Attached! " + this);
         mAttachInfo = info;
         if (mOverlay != null) {
-            mOverlay.dispatchAttachedToWindow(info, visibility);
+            mOverlay.getOverlayView().dispatchAttachedToWindow(info, visibility);
         }
         mWindowAttachCount++;
         // We will need to evaluate the drawable state at least once.
@@ -12178,7 +12178,7 @@
 
         mAttachInfo = null;
         if (mOverlay != null) {
-            mOverlay.dispatchDetachedFromWindow();
+            mOverlay.getOverlayView().dispatchDetachedFromWindow();
         }
     }
 
@@ -12831,7 +12831,7 @@
                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         dispatchDraw(canvas);
                         if (mOverlay != null && !mOverlay.isEmpty()) {
-                            mOverlay.draw(canvas);
+                            mOverlay.getOverlayView().draw(canvas);
                         }
                     } else {
                         draw(canvas);
@@ -13147,7 +13147,7 @@
                 mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                 dispatchDraw(canvas);
                 if (mOverlay != null && !mOverlay.isEmpty()) {
-                    mOverlay.draw(canvas);
+                    mOverlay.getOverlayView().draw(canvas);
                 }
             } else {
                 draw(canvas);
@@ -13905,7 +13905,7 @@
             onDrawScrollBars(canvas);
 
             if (mOverlay != null && !mOverlay.isEmpty()) {
-                mOverlay.dispatchDraw(canvas);
+                mOverlay.getOverlayView().dispatchDraw(canvas);
             }
 
             // we're done...
@@ -14049,34 +14049,24 @@
         onDrawScrollBars(canvas);
 
         if (mOverlay != null && !mOverlay.isEmpty()) {
-            mOverlay.dispatchDraw(canvas);
+            mOverlay.getOverlayView().dispatchDraw(canvas);
         }
     }
 
     /**
-     * Called by the addToOverlay() methods to create, attach, and size the overlay as necessary
+     * Returns the overlay for this view, creating it if it does not yet exist.
+     * Adding drawables to the overlay will cause them to be displayed whenever
+     * the view itself is redrawn. Objects in the overlay should be actively
+     * managed: remove them when they should not be displayed anymore. The
+     * overlay will always have the same size as its host view.
+     *
+     * @return The ViewOverlay object for this view.
+     * @see ViewOverlay
      */
-    private void setupOverlay() {
+    public ViewOverlay getOverlay() {
         if (mOverlay == null) {
             mOverlay = new ViewOverlay(mContext, this);
-            mOverlay.mAttachInfo = mAttachInfo;
-            mOverlay.setRight(mRight);
-            mOverlay.setBottom(mBottom);
         }
-    }
-
-    /**
-     * Returns the overlay for this view, creating it if it does not yet exist. Adding drawables
-     * and/or views to the overlay will cause them to be displayed whenever the view itself is
-     * redrawn. Objects in the overlay should be actively managed: remove them when they should
-     * not be displayed anymore and invalidate this view appropriately when overlay drawables
-     * change. The overlay will always have the same size as its host view.
-     *
-     * @return The Overlay object for this view.
-     * @see Overlay
-     */
-    public Overlay getOverlay() {
-        setupOverlay();
         return mOverlay;
     }
 
@@ -14360,8 +14350,8 @@
     private void sizeChange(int newWidth, int newHeight, int oldWidth, int oldHeight) {
         onSizeChanged(newWidth, newHeight, oldWidth, oldHeight);
         if (mOverlay != null) {
-            mOverlay.setRight(mRight);
-            mOverlay.setBottom(mBottom);
+            mOverlay.getOverlayView().setRight(newWidth);
+            mOverlay.getOverlayView().setBottom(newHeight);
         }
     }
 
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index f615e1bc..c07191a 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1876,34 +1876,10 @@
                     // have become out of sync.
                     removePointersFromTouchTargets(idBitsToAssign);
 
-                    final float x = ev.getX(actionIndex);
-                    final float y = ev.getY(actionIndex);
-
-                    if (mOverlay != null) {
-                        ViewOverlay overlay = (ViewOverlay) mOverlay;
-                        // Check to see whether the overlay can handle the event
-                        final View child = mOverlay;
-                        if (canViewReceivePointerEvents(child) &&
-                                isTransformedTouchPointInView(x, y, child, null)) {
-                            newTouchTarget = getTouchTarget(child);
-                            if (newTouchTarget != null) {
-                                newTouchTarget.pointerIdBits |= idBitsToAssign;
-                            } else {
-                                resetCancelNextUpFlag(child);
-                                if (dispatchTransformedTouchEvent(ev, false, child,
-                                        idBitsToAssign)) {
-                                    mLastTouchDownTime = ev.getDownTime();
-                                    mLastTouchDownX = ev.getX();
-                                    mLastTouchDownY = ev.getY();
-                                    newTouchTarget = addTouchTarget(child, idBitsToAssign);
-                                    alreadyDispatchedToNewTouchTarget = true;
-                                }
-                            }
-                        }
-                    }
-
                     final int childrenCount = mChildrenCount;
                     if (newTouchTarget == null && childrenCount != 0) {
+                        final float x = ev.getX(actionIndex);
+                        final float y = ev.getY(actionIndex);
                         // Find a child that can receive the event.
                         // Scan children from front to back.
                         final View[] children = mChildren;
@@ -2991,6 +2967,26 @@
     }
 
     /**
+     * Returns the ViewGroupOverlay for this view group, creating it if it does
+     * not yet exist. In addition to {@link ViewOverlay}'s support for drawables,
+     * {@link ViewGroupOverlay} allows views to be added to the overlay. These
+     * views, like overlay drawables, are visual-only; they do not receive input
+     * events and should not be used as anything other than a temporary
+     * representation of a view in a parent container, such as might be used
+     * by an animation effect.
+     *
+     * @return The ViewGroupOverlay object for this view.
+     * @see ViewGroupOverlay
+     */
+    @Override
+    public ViewGroupOverlay getOverlay() {
+        if (mOverlay == null) {
+            mOverlay = new ViewGroupOverlay(mContext, this);
+        }
+        return (ViewGroupOverlay) mOverlay;
+    }
+
+    /**
      * Returns the index of the child to draw for this iteration. Override this
      * if you want to change the drawing order of children. By default, it
      * returns i.
@@ -3055,11 +3051,12 @@
             }
         }
         if (mOverlay != null) {
-            mOverlay.mRecreateDisplayList = (mOverlay.mPrivateFlags & PFLAG_INVALIDATED)
+            View overlayView = mOverlay.getOverlayView();
+            overlayView.mRecreateDisplayList = (overlayView.mPrivateFlags & PFLAG_INVALIDATED)
                     == PFLAG_INVALIDATED;
-            mOverlay.mPrivateFlags &= ~PFLAG_INVALIDATED;
-            mOverlay.getDisplayList();
-            mOverlay.mRecreateDisplayList = false;
+            overlayView.mPrivateFlags &= ~PFLAG_INVALIDATED;
+            overlayView.getDisplayList();
+            overlayView.mRecreateDisplayList = false;
         }
     }
 
diff --git a/core/java/android/view/ViewGroupOverlay.java b/core/java/android/view/ViewGroupOverlay.java
new file mode 100644
index 0000000..c1b24f2
--- /dev/null
+++ b/core/java/android/view/ViewGroupOverlay.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package android.view;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+
+/**
+ * A group overlay is an extra layer that sits on top of a ViewGroup
+ * (the "host view") which is drawn after all other content in that view
+ * (including the view group's children). Interaction with the overlay
+ * layer is done by adding and removing views and drawables.
+ *
+ * <p>ViewGroupOverlay is a subclass of {@link ViewOverlay}, adding the ability to
+ * manage views for overlays on ViewGroups, in addition to the drawable
+ * support in ViewOverlay.</p>
+ *
+ * @see ViewGroup#getOverlay()
+ */
+public class ViewGroupOverlay extends ViewOverlay {
+
+    ViewGroupOverlay(Context context, View hostView) {
+        super(context, hostView);
+    }
+
+    /**
+     * Adds a View to the overlay. The bounds of the added view should be
+     * relative to the host view. Any view added to the overlay should be
+     * removed when it is no longer needed or no longer visible.
+     *
+     * <p>Views in the overlay are visual-only; they do not receive input
+     * events and do not participate in focus traversal. Overlay views
+     * are intended to be transient, such as might be needed by a temporary
+     * animation effect.</p>
+     *
+     * <p>If the view has a parent, the view will be removed from that parent
+     * before being added to the overlay. Also, the view will be repositioned
+     * such that it is in the same relative location inside the activity. For
+     * example, if the view's current parent lies 100 pixels to the right
+     * and 200 pixels down from the origin of the overlay's
+     * host view, then the view will be offset by (100, 200).</p>
+     *
+     * @param view The View to be added to the overlay. The added view will be
+     * drawn when the overlay is drawn.
+     * @see #remove(View)
+     * @see ViewOverlay#add(Drawable)
+     */
+    public void add(View view) {
+        mOverlayViewGroup.add(view);
+    }
+
+    /**
+     * Removes the specified View from the overlay.
+     *
+     * @param view The View to be removed from the overlay.
+     * @see #add(View)
+     * @see ViewOverlay#remove(Drawable)
+     */
+    public void remove(View view) {
+        mOverlayViewGroup.remove(view);
+    }
+}
diff --git a/core/java/android/view/ViewOverlay.java b/core/java/android/view/ViewOverlay.java
index 8b18d53..78e2597 100644
--- a/core/java/android/view/ViewOverlay.java
+++ b/core/java/android/view/ViewOverlay.java
@@ -23,215 +23,286 @@
 import java.util.ArrayList;
 
 /**
- * ViewOverlay is a container that View uses to host all objects (views and
- * drawables) that are added to its "overlay", gotten through
- * {@link View#getOverlay()}. Views and drawables are added to the overlay
- * via the add/remove methods in this class. These views and drawables are
- * drawn whenever the view itself is drawn; first the view draws its own
- * content (and children, if it is a ViewGroup), then it draws its overlay
- * (if it has one).
+ * An overlay is an extra layer that sits on top of a View (the "host view")
+ * which is drawn after all other content in that view (including children,
+ * if the view is a ViewGroup). Interaction with the overlay layer is done
+ * by adding and removing drawables.
  *
- * Besides managing and drawing the list of drawables, this class serves
- * two purposes:
- * (1) it noops layout calls because children are absolutely positioned and
- * (2) it forwards all invalidation calls to its host view. The invalidation
- * redirect is necessary because the overlay is not a child of the host view
- * and invalidation cannot therefore follow the normal path up through the
- * parent hierarchy.
+ * <p>An overlay requested from a ViewGroup is of type {@link ViewGroupOverlay},
+ * which also supports adding and removing views.</p>
  *
- * @hide
+ * @see View#getOverlay() View.getOverlay()
+ * @see ViewGroup#getOverlay() ViewGroup.getOverlay()
+ * @see ViewGroupOverlay
  */
-class ViewOverlay extends ViewGroup implements Overlay {
+public class ViewOverlay {
 
     /**
-     * The View for which this is an overlay. Invalidations of the overlay are redirected to
-     * this host view.
+     * The actual container for the drawables (and views, if it's a ViewGroupOverlay).
+     * All of the management and rendering details for the overlay are handled in
+     * OverlayViewGroup.
      */
-    View mHostView;
+    OverlayViewGroup mOverlayViewGroup;
 
-    /**
-     * The set of drawables to draw when the overlay is rendered.
-     */
-    ArrayList<Drawable> mDrawables = null;
-
-    ViewOverlay(Context context, View host) {
-        super(context);
-        mHostView = host;
-        mParent = mHostView.getParent();
+    ViewOverlay(Context context, View hostView) {
+        mOverlayViewGroup = new OverlayViewGroup(context, hostView);
     }
 
-    @Override
+    /**
+     * Used internally by View and ViewGroup to handle drawing and invalidation
+     * of the overlay
+     * @return
+     */
+    ViewGroup getOverlayView() {
+        return mOverlayViewGroup;
+    }
+
+    /**
+     * Adds a Drawable to the overlay. The bounds of the drawable should be relative to
+     * the host view. Any drawable added to the overlay should be removed when it is no longer
+     * needed or no longer visible.
+     *
+     * @param drawable The Drawable to be added to the overlay. This drawable will be
+     * drawn when the view redraws its overlay.
+     * @see #remove(Drawable)
+     */
     public void add(Drawable drawable) {
-        if (mDrawables == null) {
-            mDrawables = new ArrayList<Drawable>();
-        }
-        if (!mDrawables.contains(drawable)) {
-            // Make each drawable unique in the overlay; can't add it more than once
-            mDrawables.add(drawable);
-            invalidate(drawable.getBounds());
-            drawable.setCallback(this);
-        }
+        mOverlayViewGroup.add(drawable);
     }
 
-    @Override
+    /**
+     * Removes the specified Drawable from the overlay.
+     *
+     * @param drawable The Drawable to be removed from the overlay.
+     * @see #add(Drawable)
+     */
     public void remove(Drawable drawable) {
-        if (mDrawables != null) {
-            mDrawables.remove(drawable);
-            invalidate(drawable.getBounds());
-            drawable.setCallback(null);
-        }
+        mOverlayViewGroup.remove(drawable);
     }
 
-    @Override
-    public void invalidateDrawable(Drawable drawable) {
-        invalidate(drawable.getBounds());
-    }
-
-    @Override
-    public void add(View child) {
-        int deltaX = 0;
-        int deltaY = 0;
-        if (child.getParent() instanceof ViewGroup) {
-            ViewGroup parent = (ViewGroup) child.getParent();
-            if (parent != mHostView) {
-                // Moving to different container; figure out how to position child such that
-                // it is in the same location on the screen
-                int[] parentLocation = new int[2];
-                int[] hostViewLocation = new int[2];
-                parent.getLocationOnScreen(parentLocation);
-                mHostView.getLocationOnScreen(hostViewLocation);
-                child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]);
-                child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]);
-            }
-            parent.removeView(child);
-        }
-        super.addView(child);
-    }
-
-    @Override
-    public void remove(View view) {
-        super.removeView(view);
-    }
-
-    @Override
+    /**
+     * Removes all content from the overlay.
+     */
     public void clear() {
-        removeAllViews();
-        mDrawables.clear();
+        mOverlayViewGroup.clear();
     }
 
     boolean isEmpty() {
-        if (getChildCount() == 0 && (mDrawables == null || mDrawables.size() == 0)) {
-            return true;
-        }
-        return false;
+        return mOverlayViewGroup.isEmpty();
     }
 
-    @Override
-    protected void dispatchDraw(Canvas canvas) {
-        super.dispatchDraw(canvas);
-        final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
-        for (int i = 0; i < numDrawables; ++i) {
-            mDrawables.get(i).draw(canvas);
-        }
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int l, int t, int r, int b) {
-        // Noop: children are positioned absolutely
-    }
-
-    /*
-     The following invalidation overrides exist for the purpose of redirecting invalidation to
-     the host view. The overlay is not parented to the host view (since a View cannot be a parent),
-     so the invalidation cannot proceed through the normal parent hierarchy.
-     There is a built-in assumption that the overlay exactly covers the host view, therefore
-     the invalidation rectangles received do not need to be adjusted when forwarded to
-     the host view.
+    /**
+     * OverlayViewGroup is a container that View and ViewGroup use to host
+     * drawables and views added to their overlays  ({@link ViewOverlay} and
+     * {@link ViewGroupOverlay}, respectively). Drawables are added to the overlay
+     * via the add/remove methods in ViewOverlay, Views are added/removed via
+     * ViewGroupOverlay. These drawable and view objects are
+     * drawn whenever the view itself is drawn; first the view draws its own
+     * content (and children, if it is a ViewGroup), then it draws its overlay
+     * (if it has one).
+     *
+     * <p>Besides managing and drawing the list of drawables, this class serves
+     * two purposes:
+     * (1) it noops layout calls because children are absolutely positioned and
+     * (2) it forwards all invalidation calls to its host view. The invalidation
+     * redirect is necessary because the overlay is not a child of the host view
+     * and invalidation cannot therefore follow the normal path up through the
+     * parent hierarchy.</p>
+     *
+     * @see View#getOverlay()
+     * @see ViewGroup#getOverlay()
      */
+    static class OverlayViewGroup extends ViewGroup {
 
-    @Override
-    public void invalidate(Rect dirty) {
-        super.invalidate(dirty);
-        if (mHostView != null) {
-            mHostView.invalidate(dirty);
+        /**
+         * The View for which this is an overlay. Invalidations of the overlay are redirected to
+         * this host view.
+         */
+        View mHostView;
+
+        /**
+         * The set of drawables to draw when the overlay is rendered.
+         */
+        ArrayList<Drawable> mDrawables = null;
+
+        OverlayViewGroup(Context context, View hostView) {
+            super(context);
+            mHostView = hostView;
+            mAttachInfo = mHostView.mAttachInfo;
+            mRight = hostView.getWidth();
+            mBottom = hostView.getHeight();
         }
-    }
 
-    @Override
-    public void invalidate(int l, int t, int r, int b) {
-        super.invalidate(l, t, r, b);
-        if (mHostView != null) {
-            mHostView.invalidate(l, t, r, b);
-        }
-    }
+        public void add(Drawable drawable) {
+            if (mDrawables == null) {
 
-    @Override
-    public void invalidate() {
-        super.invalidate();
-        if (mHostView != null) {
-            mHostView.invalidate();
-        }
-    }
-
-    @Override
-    void invalidate(boolean invalidateCache) {
-        super.invalidate(invalidateCache);
-        if (mHostView != null) {
-            mHostView.invalidate(invalidateCache);
-        }
-    }
-
-    @Override
-    void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
-        super.invalidateViewProperty(invalidateParent, forceRedraw);
-        if (mHostView != null) {
-            mHostView.invalidateViewProperty(invalidateParent, forceRedraw);
-        }
-    }
-
-    @Override
-    protected void invalidateParentCaches() {
-        super.invalidateParentCaches();
-        if (mHostView != null) {
-            mHostView.invalidateParentCaches();
-        }
-    }
-
-    @Override
-    protected void invalidateParentIfNeeded() {
-        super.invalidateParentIfNeeded();
-        if (mHostView != null) {
-            mHostView.invalidateParentIfNeeded();
-        }
-    }
-
-    public void invalidateChildFast(View child, final Rect dirty) {
-        if (mHostView != null) {
-            // Note: This is not a "fast" invalidation. Would be nice to instead invalidate using DL
-            // properties and a dirty rect instead of causing a real invalidation of the host view
-            int left = child.mLeft;
-            int top = child.mTop;
-            if (!child.getMatrix().isIdentity()) {
-                child.transformRect(dirty);
+                mDrawables = new ArrayList<Drawable>();
             }
-            dirty.offset(left, top);
-            mHostView.invalidate(dirty);
-        }
-    }
-
-    @Override
-    public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
-        if (mHostView != null) {
-            dirty.offset(location[0], location[1]);
-            if (mHostView instanceof ViewGroup) {
-                location[0] = 0;
-                location[1] = 0;
-                super.invalidateChildInParent(location, dirty);
-                return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
-            } else {
-                invalidate(dirty);
+            if (!mDrawables.contains(drawable)) {
+                // Make each drawable unique in the overlay; can't add it more than once
+                mDrawables.add(drawable);
+                invalidate(drawable.getBounds());
+                drawable.setCallback(this);
             }
         }
-        return null;
+
+        public void remove(Drawable drawable) {
+            if (mDrawables != null) {
+                mDrawables.remove(drawable);
+                invalidate(drawable.getBounds());
+                drawable.setCallback(null);
+            }
+        }
+
+        public void add(View child) {
+            if (child.getParent() instanceof ViewGroup) {
+                ViewGroup parent = (ViewGroup) child.getParent();
+                if (parent != mHostView) {
+                    // Moving to different container; figure out how to position child such that
+                    // it is in the same location on the screen
+                    int[] parentLocation = new int[2];
+                    int[] hostViewLocation = new int[2];
+                    parent.getLocationOnScreen(parentLocation);
+                    mHostView.getLocationOnScreen(hostViewLocation);
+                    child.offsetLeftAndRight(parentLocation[0] - hostViewLocation[0]);
+                    child.offsetTopAndBottom(parentLocation[1] - hostViewLocation[1]);
+                }
+                parent.removeView(child);
+            }
+            super.addView(child);
+        }
+
+        public void remove(View view) {
+            super.removeView(view);
+        }
+
+        public void clear() {
+            removeAllViews();
+            mDrawables.clear();
+        }
+
+        boolean isEmpty() {
+            if (getChildCount() == 0 &&
+                    (mDrawables == null || mDrawables.size() == 0)) {
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public void invalidateDrawable(Drawable drawable) {
+            invalidate(drawable.getBounds());
+        }
+
+        @Override
+        protected void dispatchDraw(Canvas canvas) {
+            super.dispatchDraw(canvas);
+            final int numDrawables = (mDrawables == null) ? 0 : mDrawables.size();
+            for (int i = 0; i < numDrawables; ++i) {
+                mDrawables.get(i).draw(canvas);
+            }
+        }
+
+        @Override
+        protected void onLayout(boolean changed, int l, int t, int r, int b) {
+            // Noop: children are positioned absolutely
+        }
+
+        /*
+         The following invalidation overrides exist for the purpose of redirecting invalidation to
+         the host view. The overlay is not parented to the host view (since a View cannot be a
+         parent), so the invalidation cannot proceed through the normal parent hierarchy.
+         There is a built-in assumption that the overlay exactly covers the host view, therefore
+         the invalidation rectangles received do not need to be adjusted when forwarded to
+         the host view.
+         */
+
+        @Override
+        public void invalidate(Rect dirty) {
+            super.invalidate(dirty);
+            if (mHostView != null) {
+                mHostView.invalidate(dirty);
+            }
+        }
+
+        @Override
+        public void invalidate(int l, int t, int r, int b) {
+            super.invalidate(l, t, r, b);
+            if (mHostView != null) {
+                mHostView.invalidate(l, t, r, b);
+            }
+        }
+
+        @Override
+        public void invalidate() {
+            super.invalidate();
+            if (mHostView != null) {
+                mHostView.invalidate();
+            }
+        }
+
+        @Override
+        void invalidate(boolean invalidateCache) {
+            super.invalidate(invalidateCache);
+            if (mHostView != null) {
+                mHostView.invalidate(invalidateCache);
+            }
+        }
+
+        @Override
+        void invalidateViewProperty(boolean invalidateParent, boolean forceRedraw) {
+            super.invalidateViewProperty(invalidateParent, forceRedraw);
+            if (mHostView != null) {
+                mHostView.invalidateViewProperty(invalidateParent, forceRedraw);
+            }
+        }
+
+        @Override
+        protected void invalidateParentCaches() {
+            super.invalidateParentCaches();
+            if (mHostView != null) {
+                mHostView.invalidateParentCaches();
+            }
+        }
+
+        @Override
+        protected void invalidateParentIfNeeded() {
+            super.invalidateParentIfNeeded();
+            if (mHostView != null) {
+                mHostView.invalidateParentIfNeeded();
+            }
+        }
+
+        public void invalidateChildFast(View child, final Rect dirty) {
+            if (mHostView != null) {
+                // Note: This is not a "fast" invalidation. Would be nice to instead invalidate
+                // using DisplayList properties and a dirty rect instead of causing a real
+                // invalidation of the host view
+                int left = child.mLeft;
+                int top = child.mTop;
+                if (!child.getMatrix().isIdentity()) {
+                    child.transformRect(dirty);
+                }
+                dirty.offset(left, top);
+                mHostView.invalidate(dirty);
+            }
+        }
+
+        @Override
+        public ViewParent invalidateChildInParent(int[] location, Rect dirty) {
+            if (mHostView != null) {
+                dirty.offset(location[0], location[1]);
+                if (mHostView instanceof ViewGroup) {
+                    location[0] = 0;
+                    location[1] = 0;
+                    super.invalidateChildInParent(location, dirty);
+                    return ((ViewGroup) mHostView).invalidateChildInParent(location, dirty);
+                } else {
+                    invalidate(dirty);
+                }
+            }
+            return null;
+        }
     }
+
 }
diff --git a/media/java/android/media/MediaMuxer.java b/media/java/android/media/MediaMuxer.java
index 1f5ca35..c0fbd2e 100644
--- a/media/java/android/media/MediaMuxer.java
+++ b/media/java/android/media/MediaMuxer.java
@@ -257,8 +257,10 @@
     }
 
     /**
-     * Writes an encoded sample into the muxer. The application needs to make
-     * sure that the samples are written into the right tracks.
+     * Writes an encoded sample into the muxer.
+     * <p>The application needs to make sure that the samples are written into
+     * the right tracks. Also, it needs to make sure the samples for each track
+     * are written in chronological order.</p>
      * @param byteBuf The encoded sample.
      * @param trackIndex The track index for this sample.
      * @param bufferInfo The buffer information related to this sample.
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
index 5d0b155..c7c8aa2 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationBuilderTest.java
@@ -49,6 +49,8 @@
 {
     private final static String TAG = "NotificationTestList";
 
+    private final static String NOTIFY_TAG = "foo";
+
     NotificationManager mNM;
     Handler mHandler;
     int mStartDelay;
@@ -196,7 +198,7 @@
         final Notification n = buildNotification(id);
         mHandler.postDelayed(new Runnable() {
             public void run() {
-                mNM.notify(id, n);
+                mNM.notify(NOTIFY_TAG, id, n);
             }
         }, mStartDelay);
     }