Merge "Show scroll indicators in AlertDialog" into lmp-mr1-dev
diff --git a/api/current.txt b/api/current.txt
index 1ef2047..fa02c4e 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -28769,6 +28769,7 @@
     field public static final int MMS_ERROR_RETRY = 6; // 0x6
     field public static final int MMS_ERROR_UNABLE_CONNECT_MMS = 3; // 0x3
     field public static final int MMS_ERROR_UNSPECIFIED = 1; // 0x1
+    field public static final java.lang.String MMS_SHOW_CELL_BROADCAST_APP_LINKS = "config_cellBroadcastAppLinks";
     field public static final int RESULT_ERROR_GENERIC_FAILURE = 1; // 0x1
     field public static final int RESULT_ERROR_NO_SERVICE = 4; // 0x4
     field public static final int RESULT_ERROR_NULL_PDU = 3; // 0x3
@@ -34728,12 +34729,14 @@
     method public void setCallback(android.view.Window.Callback);
     method public abstract void setChildDrawable(int, android.graphics.drawable.Drawable);
     method public abstract void setChildInt(int, int);
+    method public void setClipToOutline(boolean);
     method public void setContainer(android.view.Window);
     method public abstract void setContentView(int);
     method public abstract void setContentView(android.view.View);
     method public abstract void setContentView(android.view.View, android.view.ViewGroup.LayoutParams);
     method protected void setDefaultWindowFormat(int);
     method public void setDimAmount(float);
+    method public void setElevation(float);
     method public void setEnterTransition(android.transition.Transition);
     method public void setExitTransition(android.transition.Transition);
     method public abstract void setFeatureDrawable(int, android.graphics.drawable.Drawable);
diff --git a/core/java/android/app/ApplicationPackageManager.java b/core/java/android/app/ApplicationPackageManager.java
index 854719d..967e97e 100644
--- a/core/java/android/app/ApplicationPackageManager.java
+++ b/core/java/android/app/ApplicationPackageManager.java
@@ -1609,6 +1609,18 @@
         return null;
     }
 
+    /**
+     * @hide
+     */
+    @Override
+    public boolean isUpgrade() {
+        try {
+            return mPM.isUpgrade();
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
     @Override
     public PackageInstaller getPackageInstaller() {
         synchronized (mLock) {
diff --git a/core/java/android/content/pm/IPackageManager.aidl b/core/java/android/content/pm/IPackageManager.aidl
index c37534a..0dc86ad 100644
--- a/core/java/android/content/pm/IPackageManager.aidl
+++ b/core/java/android/content/pm/IPackageManager.aidl
@@ -436,6 +436,7 @@
 
     boolean isFirstBoot();
     boolean isOnlyCoreApps();
+    boolean isUpgrade();
 
     void setPermissionEnforced(String permission, boolean enforced);
     boolean isPermissionEnforced(String permission);
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index ab90b66..e9f7c50 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -3867,6 +3867,13 @@
     public abstract VerifierDeviceIdentity getVerifierDeviceIdentity();
 
     /**
+     * Returns true if the device is upgrading, such as first boot after OTA.
+     *
+     * @hide
+     */
+    public abstract boolean isUpgrade();
+
+    /**
      * Return interface that offers the ability to install, upgrade, and remove
      * applications on the device.
      */
diff --git a/core/java/android/content/res/Configuration.java b/core/java/android/content/res/Configuration.java
index acdd87e..14af584 100644
--- a/core/java/android/content/res/Configuration.java
+++ b/core/java/android/content/res/Configuration.java
@@ -1371,7 +1371,7 @@
             }
         }
 
-        if (!config.locale.getLanguage().isEmpty()) {
+        if (config.locale != null && !config.locale.getLanguage().isEmpty()) {
             parts.add(localeToResourceQualifier(config.locale));
         }
 
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 801d9ad..e4f95a4 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -14098,7 +14098,6 @@
                     } else {
                         draw(canvas);
                     }
-                    drawAccessibilityFocus(canvas);
                 }
             } finally {
                 renderNode.end(canvas);
@@ -14393,7 +14392,6 @@
             } else {
                 draw(canvas);
             }
-            drawAccessibilityFocus(canvas);
 
             canvas.restoreToCount(restoreCount);
             canvas.setBitmap(null);
@@ -14468,7 +14466,6 @@
         } else {
             draw(canvas);
         }
-        drawAccessibilityFocus(canvas);
 
         mPrivateFlags = flags;
 
@@ -15066,13 +15063,9 @@
                     if ((mPrivateFlags & PFLAG_SKIP_DRAW) == PFLAG_SKIP_DRAW) {
                         mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                         dispatchDraw(canvas);
-                        if (mOverlay != null && !mOverlay.isEmpty()) {
-                            mOverlay.getOverlayView().draw(canvas);
-                        }
                     } else {
                         draw(canvas);
                     }
-                    drawAccessibilityFocus(canvas);
                 } else {
                     mPrivateFlags &= ~PFLAG_DIRTY_MASK;
                     ((HardwareCanvas) canvas).drawRenderNode(renderNode, null, flags);
@@ -15324,50 +15317,6 @@
     }
 
     /**
-     * Draws the accessibility focus rect onto the specified canvas.
-     *
-     * @param canvas Canvas on which to draw the focus rect
-     */
-    private void drawAccessibilityFocus(Canvas canvas) {
-        if (mAttachInfo == null) {
-            return;
-        }
-
-        final Rect bounds = mAttachInfo.mTmpInvalRect;
-        final ViewRootImpl viewRoot = getViewRootImpl();
-        if (viewRoot == null || viewRoot.getAccessibilityFocusedHost() != this) {
-            return;
-        }
-
-        final AccessibilityManager manager = AccessibilityManager.getInstance(mContext);
-        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
-            return;
-        }
-
-        final Drawable drawable = viewRoot.getAccessibilityFocusedDrawable();
-        if (drawable == null) {
-            return;
-        }
-
-        final AccessibilityNodeInfo virtualView = viewRoot.getAccessibilityFocusedVirtualView();
-        if (virtualView != null) {
-            virtualView.getBoundsInScreen(bounds);
-            final int[] offset = mAttachInfo.mTmpLocation;
-            getLocationOnScreen(offset);
-            bounds.offset(-offset[0], -offset[1]);
-        } else {
-            bounds.set(0, 0, mRight - mLeft, mBottom - mTop);
-        }
-
-        canvas.save();
-        canvas.translate(mScrollX, mScrollY);
-        canvas.clipRect(bounds, Region.Op.REPLACE);
-        drawable.setBounds(bounds);
-        drawable.draw(canvas);
-        canvas.restore();
-    }
-
-    /**
      * Draws the background onto the specified canvas.
      *
      * @param canvas Canvas on which to draw the background
@@ -16389,6 +16338,12 @@
                 if (tintInfo.mHasTintMode) {
                     mBackground.setTintMode(tintInfo.mTintMode);
                 }
+
+                // The drawable (or one of its children) may not have been
+                // stateful before applying the tint, so let's try again.
+                if (mBackground.isStateful()) {
+                    mBackground.setState(getDrawableState());
+                }
             }
         }
     }
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 7c7e3e7..654a8ed 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -4250,9 +4250,7 @@
             clearChildFocus = true;
         }
 
-        if (view.isAccessibilityFocused()) {
-            view.clearAccessibilityFocus();
-        }
+        view.clearAccessibilityFocus();
 
         cancelTouchTarget(view);
         cancelHoverTarget(view);
@@ -4345,9 +4343,7 @@
                 clearChildFocus = true;
             }
 
-            if (view.isAccessibilityFocused()) {
-                view.clearAccessibilityFocus();
-            }
+            view.clearAccessibilityFocus();
 
             cancelTouchTarget(view);
             cancelHoverTarget(view);
@@ -4432,9 +4428,7 @@
                 clearChildFocus = true;
             }
 
-            if (view.isAccessibilityFocused()) {
-                view.clearAccessibilityFocus();
-            }
+            view.clearAccessibilityFocus();
 
             cancelTouchTarget(view);
             cancelHoverTarget(view);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 81fc966..27f78b6 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -727,7 +727,10 @@
                     mAttachInfo.mHardwareRenderer.destroy();
                 }
 
-                final boolean translucent = attrs.format != PixelFormat.OPAQUE;
+                final Rect insets = attrs.surfaceInsets;
+                final boolean hasSurfaceInsets = insets.left == 0 || insets.right == 0
+                        || insets.top == 0 || insets.bottom == 0;
+                final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets;
                 mAttachInfo.mHardwareRenderer = HardwareRenderer.create(mContext, translucent);
                 if (mAttachInfo.mHardwareRenderer != null) {
                     mAttachInfo.mHardwareRenderer.setName(attrs.getTitle().toString());
@@ -2255,6 +2258,7 @@
             canvas.drawHardwareLayer(mResizeBuffer, mHardwareXOffset, mHardwareYOffset,
                     mResizePaint);
         }
+        drawAccessibilityFocusedDrawableIfNeeded(canvas);
     }
 
     /**
@@ -2474,18 +2478,38 @@
             dirty.offset(surfaceInsets.left, surfaceInsets.right);
         }
 
-        if (!dirty.isEmpty() || mIsAnimating) {
+        boolean accessibilityFocusDirty = false;
+        final Drawable drawable = mAttachInfo.mAccessibilityFocusDrawable;
+        if (drawable != null) {
+            final Rect bounds = mAttachInfo.mTmpInvalRect;
+            final boolean hasFocus = getAccessibilityFocusedRect(bounds);
+            if (!hasFocus) {
+                bounds.setEmpty();
+            }
+            if (!bounds.equals(drawable.getBounds())) {
+                accessibilityFocusDirty = true;
+            }
+        }
+
+        if (!dirty.isEmpty() || mIsAnimating || accessibilityFocusDirty) {
             if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
+                // If accessibility focus moved, always invalidate the root.
+                boolean invalidateRoot = accessibilityFocusDirty;
+
                 // Draw with hardware renderer.
                 mIsAnimating = false;
-                boolean invalidateRoot = false;
+
                 if (mHardwareYOffset != yOffset || mHardwareXOffset != xOffset) {
                     mHardwareYOffset = yOffset;
                     mHardwareXOffset = xOffset;
-                    mAttachInfo.mHardwareRenderer.invalidateRoot();
+                    invalidateRoot = true;
                 }
                 mResizeAlpha = resizeAlpha;
 
+                if (invalidateRoot) {
+                    mAttachInfo.mHardwareRenderer.invalidateRoot();
+                }
+
                 dirty.setEmpty();
 
                 mBlockResizeBuffer = false;
@@ -2604,6 +2628,8 @@
                 attachInfo.mSetIgnoreDirtyState = false;
 
                 mView.draw(canvas);
+
+                drawAccessibilityFocusedDrawableIfNeeded(canvas);
             } finally {
                 if (!attachInfo.mSetIgnoreDirtyState) {
                     // Only clear the flag if it was not set during the mView.draw() call
@@ -2627,7 +2653,56 @@
         return true;
     }
 
-    Drawable getAccessibilityFocusedDrawable() {
+    /**
+     * We want to draw a highlight around the current accessibility focused.
+     * Since adding a style for all possible view is not a viable option we
+     * have this specialized drawing method.
+     *
+     * Note: We are doing this here to be able to draw the highlight for
+     *       virtual views in addition to real ones.
+     *
+     * @param canvas The canvas on which to draw.
+     */
+    private void drawAccessibilityFocusedDrawableIfNeeded(Canvas canvas) {
+        final Rect bounds = mAttachInfo.mTmpInvalRect;
+        if (getAccessibilityFocusedRect(bounds)) {
+            final Drawable drawable = getAccessibilityFocusedDrawable();
+            if (drawable != null) {
+                drawable.setBounds(bounds);
+                drawable.draw(canvas);
+            }
+        } else if (mAttachInfo.mAccessibilityFocusDrawable != null) {
+            mAttachInfo.mAccessibilityFocusDrawable.setBounds(0, 0, 0, 0);
+        }
+    }
+
+    private boolean getAccessibilityFocusedRect(Rect bounds) {
+        final AccessibilityManager manager = AccessibilityManager.getInstance(mView.mContext);
+        if (!manager.isEnabled() || !manager.isTouchExplorationEnabled()) {
+            return false;
+        }
+
+        final View host = mAccessibilityFocusedHost;
+        if (host == null || host.mAttachInfo == null) {
+            return false;
+        }
+
+        final AccessibilityNodeProvider provider = host.getAccessibilityNodeProvider();
+        if (provider == null) {
+            host.getBoundsOnScreen(bounds);
+        } else if (mAccessibilityFocusedVirtualView != null) {
+            mAccessibilityFocusedVirtualView.getBoundsInScreen(bounds);
+        } else {
+            return false;
+        }
+
+        final AttachInfo attachInfo = mAttachInfo;
+        bounds.offset(-attachInfo.mWindowLeft, -attachInfo.mWindowTop);
+        bounds.intersect(0, 0, attachInfo.mViewRootImpl.mWidth, attachInfo.mViewRootImpl.mHeight);
+        return !bounds.isEmpty();
+    }
+
+    private Drawable getAccessibilityFocusedDrawable() {
         // Lazily load the accessibility focus drawable.
         if (mAttachInfo.mAccessibilityFocusDrawable == null) {
             final TypedValue value = new TypedValue();
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 20edeb8..0076abf 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -1074,17 +1074,36 @@
     public abstract void onConfigurationChanged(Configuration newConfig);
 
     /**
+     * Sets the window elevation.
+     *
+     * @param elevation The window elevation.
+     * @see View#setElevation(float)
+     * @see android.R.styleable#Window_windowElevation
+     */
+    public void setElevation(float elevation) {}
+
+    /**
+     * Sets whether window content should be clipped to the outline of the
+     * window background.
+     *
+     * @param clipToOutline Whether window content should be clipped to the
+     *                      outline of the window background.
+     * @see View#setClipToOutline(boolean)
+     * @see android.R.styleable#Window_windowClipToOutline
+     */
+    public void setClipToOutline(boolean clipToOutline) {}
+
+    /**
      * Change the background of this window to a Drawable resource. Setting the
      * background to null will make the window be opaque. To make the window
      * transparent, you can use an empty drawable (for instance a ColorDrawable
      * with the color 0 or the system drawable android:drawable/empty.)
      *
-     * @param resid The resource identifier of a drawable resource which will be
-     *              installed as the new background.
+     * @param resId The resource identifier of a drawable resource which will
+     *              be installed as the new background.
      */
-    public void setBackgroundDrawableResource(int resid)
-    {
-        setBackgroundDrawable(mContext.getDrawable(resid));
+    public void setBackgroundDrawableResource(int resId) {
+        setBackgroundDrawable(mContext.getDrawable(resId));
     }
 
     /**
diff --git a/core/java/android/widget/AbsListView.java b/core/java/android/widget/AbsListView.java
index 4aebaae..6c107a2 100644
--- a/core/java/android/widget/AbsListView.java
+++ b/core/java/android/widget/AbsListView.java
@@ -4910,9 +4910,7 @@
                     if (position >= headerViewsCount && position < footerViewsStart) {
                         // The view will be rebound to new data, clear any
                         // system-managed transient state.
-                        if (child.isAccessibilityFocused()) {
-                            child.clearAccessibilityFocus();
-                        }
+                        child.clearAccessibilityFocus();
                         mRecycler.addScrapView(child, position);
                     }
                 }
@@ -4933,9 +4931,7 @@
                     if (position >= headerViewsCount && position < footerViewsStart) {
                         // The view will be rebound to new data, clear any
                         // system-managed transient state.
-                        if (child.isAccessibilityFocused()) {
-                            child.clearAccessibilityFocus();
-                        }
+                        child.clearAccessibilityFocus();
                         mRecycler.addScrapView(child, position);
                     }
                 }
@@ -6776,9 +6772,7 @@
         }
 
         private void clearAccessibilityFromScrap(View view) {
-            if (view.isAccessibilityFocused()) {
-                view.clearAccessibilityFocus();
-            }
+            view.clearAccessibilityFocus();
             view.setAccessibilityDelegate(null);
         }
 
diff --git a/core/java/android/widget/AbsSeekBar.java b/core/java/android/widget/AbsSeekBar.java
index b2cfdf7..d39960f 100644
--- a/core/java/android/widget/AbsSeekBar.java
+++ b/core/java/android/widget/AbsSeekBar.java
@@ -267,6 +267,12 @@
             if (mHasThumbTintMode) {
                 mThumb.setTintMode(mThumbTintMode);
             }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mThumb.isStateful()) {
+                mThumb.setState(getDrawableState());
+            }
         }
     }
 
diff --git a/core/java/android/widget/CheckedTextView.java b/core/java/android/widget/CheckedTextView.java
index eb8e8aa..69969a9 100644
--- a/core/java/android/widget/CheckedTextView.java
+++ b/core/java/android/widget/CheckedTextView.java
@@ -267,6 +267,12 @@
             if (mHasCheckMarkTintMode) {
                 mCheckMarkDrawable.setTintMode(mCheckMarkTintMode);
             }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mCheckMarkDrawable.isStateful()) {
+                mCheckMarkDrawable.setState(getDrawableState());
+            }
         }
     }
 
diff --git a/core/java/android/widget/CompoundButton.java b/core/java/android/widget/CompoundButton.java
index 092e31c..447ccc2 100644
--- a/core/java/android/widget/CompoundButton.java
+++ b/core/java/android/widget/CompoundButton.java
@@ -315,6 +315,12 @@
             if (mHasButtonTintMode) {
                 mButtonDrawable.setTintMode(mButtonTintMode);
             }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mButtonDrawable.isStateful()) {
+                mButtonDrawable.setState(getDrawableState());
+            }
         }
     }
 
diff --git a/core/java/android/widget/FrameLayout.java b/core/java/android/widget/FrameLayout.java
index e317524..d974c29 100644
--- a/core/java/android/widget/FrameLayout.java
+++ b/core/java/android/widget/FrameLayout.java
@@ -384,6 +384,12 @@
             if (mHasForegroundTintMode) {
                 mForeground.setTintMode(mForegroundTintMode);
             }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mForeground.isStateful()) {
+                mForeground.setState(getDrawableState());
+            }
         }
     }
 
diff --git a/core/java/android/widget/ImageView.java b/core/java/android/widget/ImageView.java
index 75dfcca..1ac4dd8 100644
--- a/core/java/android/widget/ImageView.java
+++ b/core/java/android/widget/ImageView.java
@@ -527,6 +527,12 @@
             if (mHasDrawableTintMode) {
                 mDrawable.setTintMode(mDrawableTintMode);
             }
+
+            // The drawable (or one of its children) may not have been
+            // stateful before applying the tint, so let's try again.
+            if (mDrawable.isStateful()) {
+                mDrawable.setState(getDrawableState());
+            }
         }
     }
 
@@ -820,6 +826,7 @@
             mDrawableHeight = d.getIntrinsicHeight();
             applyImageTint();
             applyColorMod();
+
             configureBounds();
         } else {
             mDrawableWidth = mDrawableHeight = -1;
diff --git a/core/java/android/widget/ProgressBar.java b/core/java/android/widget/ProgressBar.java
index 1c190c3..887a93b 100644
--- a/core/java/android/widget/ProgressBar.java
+++ b/core/java/android/widget/ProgressBar.java
@@ -673,6 +673,12 @@
                 if (tintInfo.mHasIndeterminateTintMode) {
                     mIndeterminateDrawable.setTintMode(tintInfo.mIndeterminateTintMode);
                 }
+
+                // The drawable (or one of its children) may not have been
+                // stateful before applying the tint, so let's try again.
+                if (mIndeterminateDrawable.isStateful()) {
+                    mIndeterminateDrawable.setState(getDrawableState());
+                }
             }
         }
     }
@@ -781,6 +787,12 @@
                 if (mProgressTintInfo.mHasProgressTintMode) {
                     target.setTintMode(mProgressTintInfo.mProgressTintMode);
                 }
+
+                // The drawable (or one of its children) may not have been
+                // stateful before applying the tint, so let's try again.
+                if (target.isStateful()) {
+                    target.setState(getDrawableState());
+                }
             }
         }
     }
@@ -800,6 +812,12 @@
                 if (mProgressTintInfo.mHasProgressBackgroundTintMode) {
                     target.setTintMode(mProgressTintInfo.mProgressBackgroundTintMode);
                 }
+
+                // The drawable (or one of its children) may not have been
+                // stateful before applying the tint, so let's try again.
+                if (target.isStateful()) {
+                    target.setState(getDrawableState());
+                }
             }
         }
     }
@@ -819,6 +837,12 @@
                 if (mProgressTintInfo.mHasSecondaryProgressTintMode) {
                     target.setTintMode(mProgressTintInfo.mSecondaryProgressTintMode);
                 }
+
+                // The drawable (or one of its children) may not have been
+                // stateful before applying the tint, so let's try again.
+                if (target.isStateful()) {
+                    target.setState(getDrawableState());
+                }
             }
         }
     }
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 785b303..d95f0e5 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -876,7 +876,7 @@
             currentTheme.resolveAttribute(com.android.internal.R.attr.actionBarWidgetTheme,
                     outValue, true);
             final int targetThemeRes = outValue.resourceId;
-            
+
             if (targetThemeRes != 0 && mContext.getThemeResId() != targetThemeRes) {
                 mThemedContext = new ContextThemeWrapper(mContext, targetThemeRes);
             } else {
@@ -885,7 +885,7 @@
         }
         return mThemedContext;
     }
-    
+
     @Override
     public boolean isTitleTruncated() {
         return mDecorToolbar != null && mDecorToolbar.isTitleTruncated();
@@ -933,14 +933,17 @@
     }
 
     /**
-     * @hide 
+     * @hide
      */
     public class ActionModeImpl extends ActionMode implements MenuBuilder.Callback {
+        private final Context mActionModeContext;
+        private final MenuBuilder mMenu;
+
         private ActionMode.Callback mCallback;
-        private MenuBuilder mMenu;
         private WeakReference<View> mCustomView;
-        
+
         public ActionModeImpl(Context context, ActionMode.Callback callback) {
+            mActionModeContext = context;
             mCallback = callback;
             mMenu = new MenuBuilder(context)
                     .setDefaultShowAsAction(MenuItem.SHOW_AS_ACTION_IF_ROOM);
@@ -949,7 +952,7 @@
 
         @Override
         public MenuInflater getMenuInflater() {
-            return new MenuInflater(getThemedContext());
+            return new MenuInflater(mActionModeContext);
         }
 
         @Override
@@ -1042,7 +1045,7 @@
         public CharSequence getSubtitle() {
             return mContextView.getSubtitle();
         }
-        
+
         @Override
         public void setTitleOptionalHint(boolean titleOptional) {
             super.setTitleOptionalHint(titleOptional);
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 4159792..4d17877 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -929,8 +929,8 @@
  */
 void AndroidRuntime::start(const char* className, const Vector<String8>& options)
 {
-    ALOGD("\n>>>>>> AndroidRuntime START %s <<<<<<\n",
-            className != NULL ? className : "(unknown)");
+    ALOGD(">>>>>> START %s uid %d <<<<<<\n",
+            className != NULL ? className : "(unknown)", getuid());
 
     static const String8 startSystemServer("start-system-server");
 
diff --git a/core/jni/android_hardware_SoundTrigger.cpp b/core/jni/android_hardware_SoundTrigger.cpp
index 7b33bc2..2a8e6d6 100644
--- a/core/jni/android_hardware_SoundTrigger.cpp
+++ b/core/jni/android_hardware_SoundTrigger.cpp
@@ -265,18 +265,21 @@
                                 event->capture_session, event->capture_delay_ms,
                                 event->capture_preamble_ms, event->trigger_in_data,
                                 jAudioFormat, jData, jExtras);
-        env->DeleteLocalRef(jAudioFormat);
-        env->DeleteLocalRef(jData);
+        env->DeleteLocalRef(jExtras);
     } else {
         jEvent = env->NewObject(gRecognitionEventClass, gRecognitionEventCstor,
                                 event->status, event->model, event->capture_available,
                                 event->capture_session, event->capture_delay_ms,
                                 event->capture_preamble_ms, event->trigger_in_data,
                                 jAudioFormat, jData);
-        env->DeleteLocalRef(jAudioFormat);
-        env->DeleteLocalRef(jData);
     }
 
+    if (jAudioFormat != NULL) {
+        env->DeleteLocalRef(jAudioFormat);
+    }
+    if (jData != NULL) {
+        env->DeleteLocalRef(jData);
+    }
 
     env->CallStaticVoidMethod(mClass, gPostEventFromNative, mObject,
                               SOUNDTRIGGER_EVENT_RECOGNITION, 0, 0, jEvent);
diff --git a/core/jni/android_media_AudioSystem.cpp b/core/jni/android_media_AudioSystem.cpp
index 33bb90bc..f099289 100644
--- a/core/jni/android_media_AudioSystem.cpp
+++ b/core/jni/android_media_AudioSystem.cpp
@@ -390,7 +390,7 @@
     return (jint) check_AudioSystem_Command(AudioSystem::setMasterMute(mute));
 }
 
-static jfloat
+static jboolean
 android_media_AudioSystem_getMasterMute(JNIEnv *env, jobject thiz)
 {
     bool mute;
diff --git a/core/res/res/drawable/view_accessibility_focused.xml b/core/res/res/drawable/view_accessibility_focused.xml
index 68e3f1e..025916b 100644
--- a/core/res/res/drawable/view_accessibility_focused.xml
+++ b/core/res/res/drawable/view_accessibility_focused.xml
@@ -18,9 +18,7 @@
 
     <stroke
         android:width="4dp"
-        android:color="@color/accessibility_focus_highlight"
-        android:dashWidth="4dp"
-        android:dashGap="2dp" />
+        android:color="@color/accessibility_focus_highlight" />
 
     <corners android:radius="2dp" />
 
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 1d46e22..27616c7 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -3509,6 +3509,9 @@
     <!-- [CHAR LIMIT=40] Title of dialog that is shown when performing a system upgrade. -->
     <string name="android_upgrading_title">Android is upgrading\u2026</string>
 
+    <!-- [CHAR LIMIT=40] Title of dialog that is shown when system is starting. -->
+    <string name="android_start_title">Android is starting\u2026</string>
+
     <!-- [CHAR LIMIT=NONE] Message shown in upgrading dialog for each .apk that is optimized. -->
     <string name="android_upgrading_apk">Optimizing app
         <xliff:g id="number" example="123">%1$d</xliff:g> of
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 3cdc1ac..0432425 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1491,6 +1491,7 @@
   <java-symbol type="layout" name="screen_title" />
   <java-symbol type="layout" name="screen_title_icons" />
   <java-symbol type="string" name="system_ui_date_pattern" />
+  <java-symbol type="string" name="android_start_title" />
   <java-symbol type="string" name="android_upgrading_title" />
   <java-symbol type="string" name="bugreport_title" />
   <java-symbol type="string" name="bugreport_message" />
diff --git a/docs/html/google/gcm/adv.jd b/docs/html/google/gcm/adv.jd
index 245467f..95497e3 100644
--- a/docs/html/google/gcm/adv.jd
+++ b/docs/html/google/gcm/adv.jd
@@ -261,7 +261,7 @@
 payload&quot; (non-collapsible message). These concepts are described in more
 detail in the following sections.</p>
 
-<h3 id="s2s"><strong>Send-to-sync messages</strong></h3>
+<h3 id="s2s">Send-to-sync messages</h3>
 
 <p>A send-to-sync (collapsible) message is often a &quot;tickle&quot; that tells
 a mobile application to sync data from the server. For example, suppose you have
@@ -288,6 +288,7 @@
 guarantees about which ones they will be.</p>
 
 <h3 id="payload">Messages with payload</h3>
+
 <p>Unlike a send-to-sync message, every &quot;message with payload&quot;
 (non-collapsible message) is delivered. The payload the message contains can be
 up to 4kb. For example, here is a JSON-formatted message in an IM application in
diff --git a/docs/html/google/gcm/ccs.jd b/docs/html/google/gcm/ccs.jd
index 2faf97f..7db7a74 100644
--- a/docs/html/google/gcm/ccs.jd
+++ b/docs/html/google/gcm/ccs.jd
@@ -21,7 +21,7 @@
       </li>
   <li><a href="#upstream">Upstream Messages</a>
     <ol>
-      <li><a href="#receipts">Receive return receipts</a></li>
+      <li><a href="#receipts">Receive delivery receipts</a></li>
     </ol>
   </li>
   <li><a href="#flow">Flow Control</a> </li>
@@ -45,11 +45,15 @@
 </div>
 </div>
 
-<p>The GCM Cloud Connection Server (CCS) is an XMPP endpoint that provides a
+<p>The Google Cloud Messaging (GCM) Cloud Connection Server (CCS) is an XMPP endpoint that provides a
 persistent, asynchronous, bidirectional connection to Google servers. The
 connection can be used to send and receive messages between your server and
 your users' GCM-connected devices.</p>
 
+<p class="note"><strong>Note:</strong> The content in this document
+applies to <a href="http://developer.chrome.com/apps/cloudMessaging">
+GCM with Chrome apps</a> as well as Android.
+
 <p>You can continue to use the HTTP request mechanism to send messages to GCM
 servers, side-by-side with CCS which uses XMPP. Some of the benefits of CCS include:</p>
 
@@ -259,22 +263,6 @@
 &lt;/message&gt;
 </pre>
 
-<p>Quota exceeded:</p>
-
-<pre>&lt;message&gt;
- &lt;gcm xmlns=&quot;google:mobile:data&quot;&gt;
- {
-   &quot;message_type&quot;:&quot;nack&quot;,
-   &quot;message_id&quot;:&quot;msgId1&quot;,
-   &quot;from&quot;:&quot;APA91bHFOtaQGSwupt5l1og&quot;,
-   &quot;error&quot;:&quot;QUOTA_EXCEEDED&quot;,
-   &quot;error_description&quot;:&quot;Short-term downstream quota exceeded for this registration id&quot;
- }
- &lt;/gcm&gt;
-&lt;/message&gt;
-</pre>
-
-
 <p>The following table lists NACK error codes. Unless otherwise
 indicated, a NACKed message should not be retried. Unexpected NACK error codes
 should be treated the same as {@code INTERNAL_SERVER_ERROR}.</p>
@@ -312,11 +300,11 @@
 <td>{@code INVALID_JSON}</td>
 <td>The JSON message payload is not valid.</td>
 </tr>
-<tr>
-<td>{@code QUOTA_EXCEEDED}</td>
-<td>The rate of messages to a particular registration ID (in other words, to a
-sender/device pair) is too high. If you want to retry the message, try using a slower
-rate.</td>
+<td>{@code DEVICE_MESSAGE_RATE_EXCEEDED}</td>
+<td>The rate of messages to a particular device is too high. You should reduce
+the number of messages sent to this device and should not immediately retry
+sending to this device. This error code replaces {@code QUOTA_EXCEEDED},
+which has been deprecated.</td>
 </tr>
 <tr>
   <td>{@code SERVICE_UNAVAILABLE}</td>
@@ -429,15 +417,17 @@
   &lt;/gcm&gt;
 &lt;/message&gt;</pre>
 
-<h3 id="receipts">Receive return receipts</h3>
+<h3 id="receipts">Receive delivery receipts</h3>
 
-<p>You can use upstream messaging to get receipt notifications, confirming
-that a given message was sent to a device. Your 3rd-party app server receives the receipt
-notification from CCS once the message has been sent to the device.</p>
+<p>You can use upstream messaging to get delivery receipts (sent from CCS to
+your 3rd party app server) when
+a device confirms that it received a message sent by CCS.</p>
 
 <p>To enable this feature, the message your 3rd-party app server sends to CCS must include
 a field called <code>&quot;delivery_receipt_requested&quot;</code>. When this field is set to
-<code>true</code>, CCS sends a return receipt. Here is an XMPP stanza containing a JSON
+<code>true</code>, CCS sends a delivery receipt when a device confirms that it received a particular message.</p>
+
+<p>Here is an XMPP stanza containing a JSON
 message with <code>&quot;delivery_receipt_requested&quot;</code> set to <code>true</code>:</p>
 
 <pre>&lt;message id=&quot;&quot;&gt;
@@ -457,8 +447,10 @@
 &lt;/message&gt;
 </pre>
 
-<p>Here is an example of a receipt notification message that CCS sends back to your 3rd-party
-app server:</p>
+
+
+<p>Here is an example of the delivery receipt that CCS sends to tell your 3rd-party
+app server that a device received a message that CCS sent it:</p>
 
 </p>
 <pre>&lt;message id=&quot;&quot;&gt;
@@ -483,12 +475,12 @@
 <ul>
   <li>The {@code &quot;message_type&quot;} is set to {@code &quot;receipt&quot;}.
   <li>The {@code &quot;message_status&quot;} is set to {@code &quot;MESSAGE_SENT_TO_DEVICE&quot;},
-  indicating that the message was delivered. Notice that in this case,
+  indicating that the device received the message. Notice that in this case,
 {@code &quot;message_status&quot;} is not a field but rather part of the data payload.</li>
   <li>The receipt message ID consists of the original message ID, but with a
-<code>dr:</code> prefix. Your 3rd-party app server must send an ACK back with this ID,
+<code>dr2:</code> prefix. Your 3rd-party app server must send an ACK back with this ID,
 which in this example is {@code dr2:m-1366082849205}.</li>
-  <li>The original message ID and status are inside the
+  <li>The original message ID, the device registration ID, and the status are inside the
 {@code &quot;data&quot;} field.</li>
 </ul>
 
diff --git a/docs/html/google/gcm/client.jd b/docs/html/google/gcm/client.jd
index 20bff10..70109c6 100644
--- a/docs/html/google/gcm/client.jd
+++ b/docs/html/google/gcm/client.jd
@@ -34,14 +34,14 @@
 </div>
 </div>
 
-<p>A GCM client is a GCM-enabled app that runs on an Android device. To write your
-client code, we recommend that you use the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs.
+<p>A Google Cloud Messaging (GCM) client is a GCM-enabled app that runs on an
+Android device. To write your client code, we recommend that you use the
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.
 The client helper library that was offered in previous versions of GCM still works,
 but it has been superseded by the more efficient
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs.</p>
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.</p>
 
 <p>A full GCM implementation requires both a client implementation and a server
 implementation. For more
@@ -57,8 +57,8 @@
 <h2 id="play-services">Step 1: Set Up Google Play Services</h2>
 
 <p>To write your client application, use the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> API.
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.
 To use this API, you must set up your project to use the Google Play services SDK,
 as described in <a href="/google/play-services/setup.html">Setup Google Play
 Services SDK</a>.</p>
@@ -159,7 +159,7 @@
 <p>Finally, write your application. This section features a sample client
 application that illustrates how to use the
 <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs. The sample consists of a main activity
+{@code GoogleCloudMessaging}</a> API. The sample consists of a main activity
 ({@code DemoActivity}), a {@link android.support.v4.content.WakefulBroadcastReceiver}
 ({@code GcmBroadcastReceiver}), and an {@link android.app.IntentService}
 ({@code GcmIntentService}). You can find the complete source code for this sample at the
@@ -456,7 +456,7 @@
 <p>When the user clicks the app's <strong>Send</strong> button, the app sends an
 upstream message using the
 <a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> APIs. In order to receive the upstream message,
+{@code GoogleCloudMessaging}</a> API. In order to receive the upstream message,
 your server should be connected to CCS. You can use one of the demo servers in
 <a href="ccs.html#implement">Implementing an XMPP-based App Server</a> to run the sample and connect
 to CCS.</p>
@@ -652,7 +652,7 @@
 
 <p>To view  statistics and any error messages for your GCM applications:</p>
 <ol>
-  <li> Go to the <code><a href="http://play.google.com/apps/publish">Developer Console</a></code>.</li>
+  <li> Go to the <a href="http://play.google.com/apps/publish">Developer Console</a>.</li>
   <li>Login with your developer account.
   <p>You will see a page that has a list of all of your apps.</p></li>
   <li> Click on the &quot;statistics&quot; link next to the app for which you
diff --git a/docs/html/google/gcm/gcm.jd b/docs/html/google/gcm/gcm.jd
index 19151b9..3d6594d 100644
--- a/docs/html/google/gcm/gcm.jd
+++ b/docs/html/google/gcm/gcm.jd
@@ -21,7 +21,7 @@
 </div>
 </div>
 
-<p>Google Cloud Messaging for Android (GCM) is a free service that helps
+<p>Google Cloud Messaging (GCM) for Android is a free service that helps
 developers  send data from servers to their Android applications on  Android
 devices, and upstream messages from the user's device back to the cloud.
 This could be a lightweight message telling the Android application
diff --git a/docs/html/google/gcm/gs.jd b/docs/html/google/gcm/gs.jd
index ae57b6d..a889624 100644
--- a/docs/html/google/gcm/gs.jd
+++ b/docs/html/google/gcm/gs.jd
@@ -25,12 +25,12 @@
 </div>
 </div>
 
-<p>This document tells you how to get started setting up a GCM
-implementation.
+<p>This document tells you how to get started setting up a Google Cloud Messaging
+(GCM) implementation.
 Before you begin, make sure to <a href="/google/play-services/setup.html">set up
 the Google Play Services SDK</a>. You need this SDK to use the
-<a href="{@docRoot}reference/com/google/android/gms/gcm/GoogleCloudMessaging.html">
-{@code GoogleCloudMessaging}</a> methods.</p>
+<a href="{@docRoot}reference/com/google/android/gms/gcm/package-summary.html">
+GCM APIs</a>.</p>
 
 <h2 id="create-proj">Creating a Google API project</h2>
 <p>To create a Google API project:</p>
diff --git a/docs/html/google/gcm/http.jd b/docs/html/google/gcm/http.jd
index b8d8659..773acd1 100644
--- a/docs/html/google/gcm/http.jd
+++ b/docs/html/google/gcm/http.jd
@@ -33,13 +33,16 @@
 </div>
 </div>
 
-<p>This document describes the GCM HTTP connection server. Connection servers
+<p>This document describes the Google Cloud Messaging (GCM) HTTP
+connection server. Connection servers
 are the Google-provided servers that take messages from the 3rd-party
 application server and sending them to the device.</p>
 
+<p class="note"><strong>Note:</strong> The content in this document
+applies to <a href="http://developer.chrome.com/apps/cloudMessaging">
+GCM with Chrome apps</a> as well as Android.</p>
 
-
-<p class="note"><strong>Note:</strong> See
+<p>See
 <a href="server.html#params">Implementing GCM Server</a> for a list of all the message
 parameters and which connection server(s) supports them.</p>
 
@@ -163,7 +166,7 @@
   </tr>
   <tr>
     <td>5xx</td>
-    <td>Errors in the 500-599 range (such as 500 or 503) indicate that there wa
+    <td>Errors in the 500-599 range (such as 500 or 503) indicate that there was
 an internal error in the GCM server while trying to process the request, or that
 the server is temporarily unavailable (for example, because of timeouts). Sender
 must retry later, honoring any <code>Retry-After</code> header included in the
@@ -416,6 +419,12 @@
 the value passed in the request. Happens when error code is
 <code>InvalidPackageName</code>.
 </dd>
+
+<dt id="big_msg"><strong>Device Message Rate Exceeded</strong></dt>
+  <dd>The rate of messages to a particular device is too high. You should reduce the number
+of messages sent to this device and should not retry sending to this device immediately.
+<br/>Happens when error code is <code>DeviceMessageRateExceeded</code>.</dd>
+
 </dl>
 
 <h3 id="example-responses">Example responses</h3>
diff --git a/docs/html/google/gcm/index.jd b/docs/html/google/gcm/index.jd
index 56e0865..af5d741 100644
--- a/docs/html/google/gcm/index.jd
+++ b/docs/html/google/gcm/index.jd
@@ -13,11 +13,11 @@
 
   <h1 itemprop="name" style="margin-bottom:0;">Google Cloud Messaging for Android</h1>
   <p itemprop="description">
-  Google Cloud Messaging for Android (GCM) is a service that allows you to send data
+  Google Cloud Messaging (GCM) for Android is a service that allows you to send data
 from your server to your users' Android-powered device, and also to receive messages from
 devices on the same connection. The GCM service handles all aspects of queueing of messages
-and delivery to the target Android application running on the target device. GCM is
-completely free no matter how big your messaging needs are, and there are no quotas.
+and delivery to the target Android application running on the target device, and it is
+completely free.
 </p>
 
 </div>
diff --git a/docs/html/google/gcm/notifications.jd b/docs/html/google/gcm/notifications.jd
index 2815f3d..147b69c 100644
--- a/docs/html/google/gcm/notifications.jd
+++ b/docs/html/google/gcm/notifications.jd
@@ -83,7 +83,7 @@
 <h2 id="gen-server">Generate a Notification Key on the Server</h2>
 
 <p>To generate a notification key on the server, you create a new
-create a new <code>notification_key</code> and map it to a
+<code>notification_key</code> and map it to a
 <code>notification_key_name</code>.</p>
 
 <p>This example shows how to create a new <code>notification_key</code> for a
@@ -268,7 +268,7 @@
 
 <p>When you make a request to create a {@code notification_key} or to add/remove its
 regIDs, a successful response always returns the <code>notification_key</code>.
-his is the {@code notification_key} you will use for sending messages:</p>
+Use the returned {@code notification_key} for sending messages:</p>
 
 <pre>HTTP status: 200
 { 
diff --git a/docs/html/google/gcm/server.jd b/docs/html/google/gcm/server.jd
index e3a6b25..20e2b2e 100644
--- a/docs/html/google/gcm/server.jd
+++ b/docs/html/google/gcm/server.jd
@@ -37,7 +37,7 @@
 </div>
 
 
-<p>The server side of GCM consists of 2 components:</p>
+<p>The server side of Google Cloud Messaging (GCM) consists of 2 components:</p>
 <ul>
 <li>Google-provided <strong>GCM Connection Servers</strong>
 take messages from a 3rd-party application server and send them to a GCM-enabled
@@ -168,36 +168,37 @@
 parameter.</p>
 
 <p class="table-caption" id="table1">
-  <strong>Table 1.</strong> Message parameters.</p>
+  <strong>Table 1.</strong> Message Parameters JSON (CCS and HTTP).</p>
 
 <table>
   <tr>
-    <th>Field</th>
+    <th>Parameter</th>
     <th>Description</th>
 <th>Where Supported</th>
 </tr>
   <td><code>to</code></td>
-<td>In CCS, used in place of <code>registration_ids</code> to specify the
-recipient of a message. Its value must be a registration ID.
+<td>In CCS, this parameter is used in place of <code>registration_ids</code> to
+specify the recipient of a message. Its value must be a registration ID.
 The value is a string. Required.</td>
 <td>CCS</td>
 </tr>
 <tr>
 <td><code>message_id</code></td>
-<td>In CCS, uniquely identifies a message in an XMPP connection. The value is a
-string that uniquely identifies the associated message. The value is a string. Required.</td>
+<td>In CCS, this parameter uniquely identifies a message in an XMPP connection.
+The value is a string that uniquely identifies the associated message. Required.</td>
 <td>CCS</td>
 </tr>
 <tr>
 <td><code>message_type</code></td>
-<td>In CCS, indicates a special status message, typically sent by the system.
+<td>In CCS, this parameter indicates a special status message, typically sent by the system.
 However, your app server also uses this parameter to send an 'ack' or 'nack'
 message back to the CCS connection server. For more discussion of this topic, see
 <a href="ccs.html">Cloud Connection Server</a>. The value is a string. Optional.</td>
 <td>CCS</td>
 <tr>
   <td><code>registration_ids</code></td>
-  <td>A string array with the list of devices (registration IDs) receiving the
+  <td>This parameter specifies a string array containing the list of devices
+(registration IDs) receiving the
 message. It must contain at least 1 and at most 1000 registration IDs. To send a
 multicast message, you must use JSON. For sending a single message to a single
 device, you could use a JSON object with just 1 registration id, or plain text
@@ -208,12 +209,13 @@
 </tr>
  <tr>
     <td><code>notification_key</code></td>
-    <td>A string that maps a single user to multiple registration IDs associated
+    <td>This parameter specifies a string that maps a single user to multiple
+registration IDs associated
 with that user. This allows a 3rd-party server to send a single message to
 multiple app instances (typically on multiple devices) owned by a single user.
 A 3rd-party server can use {@code notification_key} as the target for a message
 instead of an individual registration ID (or array of registration IDs). The maximum
-number of members allowed for a {@code notification_key} is 10. For more discussion
+number of members allowed for a {@code notification_key} is 20. For more discussion
 of this topic, see <a href="notifications.html">User Notifications</a>. Optional.
 </td>
 <td style="width:100px">HTTP. This feature is supported in CCS, but you use it by
@@ -221,13 +223,14 @@
 </tr>
   <tr>
     <td><code>collapse_key</code></td>
-    <td>An arbitrary string (such as &quot;Updates Available&quot;) that is used
+    <td>This parameter specifies an arbitrary string (such as
+&quot;Updates Available&quot;) that is used
 to collapse a group of like messages
 when the device is offline, so that only the last message gets sent to the
 client. This is intended to avoid sending too many messages to the phone when it
 comes back online. Note that since there is no guarantee of the order in which
 messages get sent, the &quot;last&quot; message may not actually be the last
-message sent by the application server. Collapse keys are also called
+message sent by the application server. Messages with collapse keys are also called
 <a href="#s2s">send-to-sync messages</a>.
 <br>
 <strong>Note:</strong> GCM allows a maximum of 4 different collapse keys to be
@@ -242,8 +245,9 @@
 </tr>
   <tr>
     <td><code>data</code></td>
-    <td>A JSON object whose fields represents the key-value pairs of the message's
-payload data. If present, the payload data it will be
+    <td>This parameter specifies a JSON object whose fields represents the
+key-value pairs of the message's
+payload data. If present, the payload data will be
 included in the Intent as application data, with the key being the extra's name.
 For instance, <code>"data":{"score":"3x1"}</code> would result in an intent extra
 named <code>score</code> whose value is the string <code>3x1</code>.
@@ -253,17 +257,14 @@
 server anyway. If you want to include objects or other non-string data types
 (such as integers or booleans), you have to do the conversion to string yourself.
 Also note that the key cannot be a reserved word (<code>from</code> or any word
-starting with <code>google.</code>). To complicate things slightly, there are
-some reserved words (such as <code>collapse_key</code>) that are technically
-allowed in payload data. However, if the request also contains the word, the
-value in the request will overwrite the value in the payload data. Hence using
-words that are defined as field names in this table is not recommended, even in
-cases where they are technically allowed. Optional.</td>
+starting with <code>google.</code>). Using words defined in this table as field
+names (such as <code>collapse_key</code>) could yield unpredictable outcomes and
+is not recommended. Optional.</td>
 <td>CCS, HTTP</td>
 </tr>
   <tr>
     <td><code>delay_while_idle</code></td>
-    <td>If included, indicates that the message should not be sent immediately
+    <td>This parameter indicates that the message should not be sent immediately
 if the device is idle. The server will wait for the device to become active, and
 then only the last message for each <code>collapse_key</code> value will be
 sent. The default value is <code>false</code>, and must be a JSON boolean. Optional.</td>
@@ -271,26 +272,70 @@
 </tr>
   <tr>
     <td><code>time_to_live</code></td>
-    <td>How long (in seconds) the message should be kept on GCM storage if the
-device is offline. Optional (default time-to-live is 4 weeks, and must be set as
+    <td>This parameter specifies how long (in seconds) the message should be kept on GCM
+storage if the device is offline. Optional (default time-to-live is 4 weeks, and must be set as
 a JSON number).</td>
 <td>CCS, HTTP</td>
 </tr>
 <tr>
   <td><code>restricted_package_name</code></td>
-  <td>A string containing the package name of your application. When set, messages
-will only be sent to registration IDs that match the package name. Optional.
+  <td>This parameter specifies a string containing the package
+name of your application. When set, messages
+are only sent to registration IDs that match the package name. Optional.
   </td>
 <td>HTTP</td>
 </tr>
 <tr>
   <td><code>dry_run</code></td>
-  <td>If included, allows developers to test their request without actually
+  <td>This parameter allows developers to test a request without actually
 sending a message. Optional. The default value is <code>false</code>, and must
 be a JSON boolean.
   </td>
 <td>HTTP</td>
 </tr>
+<tr>
+  <td><code>delivery_receipt_requested</code></td>
+  <td>This parameter lets you request confirmation of message delivery. When
+this parameter is set to <code>true</code>, CCS sends a
+delivery receipt when a device confirms that it received a message sent by CCS.
+The default value is <code>false</code>, and must be a JSON boolean. Optional.<br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.
+</td>
+  <td>CCS</td>
+</tr>
+<tr>
+  <td><code>message_status</code></td>
+  <td>This parameter specifies the status of the receipt message.
+The parameter appears inside the
+<code>&quot;data&quot;</code> field of a
+delivery receipt message. Currently the only possible value
+is <code>MESSAGE_SENT_TO_DEVICE</code>, which indicates that a device acknowledges
+receiving  a message sent by CCS.<br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.</td>
+  <td>CCS</td>
+</tr>
+<tr>
+  <td><code>original_message_id</code></td>
+  <td>The value of this parameter is the ID of the original message that the server sent to
+the device. This parameter appears inside the <code>&quot;data&quot;</code> field of a
+delivery receipt message. <br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.</td>
+  <td>CCS</td>
+</tr>
+<tr>
+  <td><code>device_registration_id</code></td>
+  <td>For the purpose of tracking the delivery receipt, this parameter lists
+the registration ID of the device to which a given message was sent. This parameter
+appears inside the <code>&quot;data&quot;</code> field of a
+delivery receipt message. <br />
+This parameter relates to <a href="{@docRoot}google/gcm/ccs.html#receipts"}>
+delivery receipts</a>.</td>
+  <td>CCS</td>
+</tr>
+
 </table>
 
 <p>If you want to test your request (either JSON or plain text) without delivering
@@ -298,21 +343,23 @@
 <code>dry_run</code> with the value <code>true</code>. The result will be almost
 identical to running the request without this parameter, except that the message
 will not be delivered to the devices. Consequently, the response will contain fake
-IDs for the message and multicast fields.</p>
+IDs for the message and multicast parameters.</p>
 
-<h3 id="plain-text">Plain text (HTTP only)</h3>
-
-<p>If you are using plain text instead of JSON, the message fields must be set as
+<p>If you are using plain text instead of JSON, the message parameters must be set as
 HTTP parameters sent in the body, and their syntax is slightly different, as
-described below:
+described in the following table:
+
+<p class="table-caption" id="table2">
+  <strong>Table 2.</strong> Message Parameters Plain Text (HTTP only).</p>
 <table>
   <tr>
-    <th>Field</th>
+    <th>Parameter</th>
     <th>Description</th>
   </tr>
   <tr>
     <td><code>registration_id</code></td>
-    <td>Must contain the registration ID of the single device receiving the message.
+    <td>This parameter specifies the registration ID of the single device
+receiving the message.
 Required.</td>
   </tr>
   <tr>
@@ -322,24 +369,23 @@
   <tr>
     <td><code>data.&lt;key&gt;</code></td>
 
-    <td>Payload data, expressed as parameters prefixed with <code>data.</code> and
+    <td>This parameter specifies payload data, expressed as parameters
+prefixed with <code>data.</code> and
 suffixed as the key. For instance, a parameter of <code>data.score=3x1</code> would
 result in an intent extra named <code>score</code> whose value is the string
 <code>3x1</code>. There is no limit on the number of key/value parameters, though
 there is a limit on the total size of the  message. Also note that the key cannot
 be a reserved word (<code>from</code> or any word starting with
-<code>google.</code>). To complicate things slightly, there are some reserved words
-(such as <code>collapse_key</code>) that are technically allowed in payload data.
-However, if the request also contains the word, the value in the request will
-overwrite the value in the payload data. Hence using words that are defined as
-field names in this table is not recommended, even in cases where they are
-technically allowed. Optional.</td>
+<code>google.</code>). Using words defined in this table as field
+names (such as <code>collapse_key</code>) could yield unpredictable outcomes and
+is not recommended. Optional.</td>
 
   </tr>
   <tr>
     <td><code>delay_while_idle</code></td>
-    <td>Should be represented as <code>1</code> or <code>true</code> for
-<code>true</code>, anything else for <code>false</code>. Optional. The default
+    <td>This parameter specifies whether messages should be delivered when the device
+is asleep. A value of <code>1</code> or <code>true</code> indicates
+<code>true</code>, and anything else indicates <code>false</code>. Optional. The default
 value is <code>false</code>.</td>
   </tr>
   <tr>
diff --git a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
index a54334a..35930cd 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/model/PageContentRepository.java
@@ -463,7 +463,8 @@
                     }
                     Intent intent = new Intent(PdfManipulationService.ACTION_GET_RENDERER);
                     intent.setClass(mContext, PdfManipulationService.class);
-                    intent.setData(Uri.fromParts("fake-scheme", String.valueOf(hashCode()), null));
+                    intent.setData(Uri.fromParts("fake-scheme", String.valueOf(
+                            AsyncRenderer.this.hashCode()), null));
                     mContext.bindService(intent, AsyncRenderer.this, Context.BIND_AUTO_CREATE);
                     mBoundToService = true;
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 1b4bdf8..09d0b5d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -59,6 +59,7 @@
 import android.service.notification.StatusBarNotification;
 import android.text.TextUtils;
 import android.util.Log;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
 import android.view.Display;
@@ -113,6 +114,9 @@
     public static final boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
     public static final boolean MULTIUSER_DEBUG = false;
 
+    // STOPSHIP disable once we resolve b/18102199
+    private static final boolean NOTIFICATION_CLICK_DEBUG = true;
+
     protected static final int MSG_SHOW_RECENT_APPS = 1019;
     protected static final int MSG_HIDE_RECENT_APPS = 1020;
     protected static final int MSG_TOGGLE_RECENTS_APPS = 1021;
@@ -325,6 +329,9 @@
                 ViewGroup actionGroup = (ViewGroup) parent;
                 index = actionGroup.indexOfChild(view);
             }
+            if (NOTIFICATION_CLICK_DEBUG) {
+                Log.d(TAG, "Clicked on button " + index + " for " + key);
+            }
             try {
                 mBarService.onNotificationActionClick(key, index);
             } catch (RemoteException e) {
@@ -1515,6 +1522,9 @@
         }
 
         public void onClick(final View v) {
+            if (NOTIFICATION_CLICK_DEBUG) {
+                Log.d(TAG, "Clicked on content of " + mNotificationKey);
+            }
             final boolean keyguardShowing = mStatusBarKeyguardViewManager.isShowing();
             final boolean afterKeyguardGone = mIntent.isActivity()
                     && PreviewInflater.wouldLaunchResolverActivity(mContext, mIntent.getIntent(),
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 1ed61fd..4714826 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -1332,6 +1332,22 @@
     }
 
     @Override
+    public final void setElevation(float elevation) {
+        mElevation = elevation;
+        if (mDecor != null) {
+            mDecor.setElevation(elevation);
+        }
+    }
+
+    @Override
+    public final void setClipToOutline(boolean clipToOutline) {
+        mClipToOutline = clipToOutline;
+        if (mDecor != null) {
+            mDecor.setClipToOutline(clipToOutline);
+        }
+    }
+
+    @Override
     public final void setBackgroundDrawable(Drawable drawable) {
         if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
             mBackgroundResource = 0;
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 558cf56..fb2a17b 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -5352,7 +5352,11 @@
                             return true;
                         }
                     };
-                    mBootMsgDialog.setTitle(R.string.android_upgrading_title);
+                    if (mContext.getPackageManager().isUpgrade()) {
+                        mBootMsgDialog.setTitle(R.string.android_upgrading_title);
+                    } else {
+                        mBootMsgDialog.setTitle(R.string.android_start_title);
+                    }
                     mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
                     mBootMsgDialog.setIndeterminate(true);
                     mBootMsgDialog.getWindow().setType(
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index de6e82b..22ab1db 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -333,6 +333,7 @@
     final DisplayMetrics mMetrics;
     final int mDefParseFlags;
     final String[] mSeparateProcesses;
+    final boolean mIsUpgrade;
 
     // This is where all application persistent data goes.
     final File mAppDataDir;
@@ -1760,7 +1761,8 @@
 
             // If this is first boot after an OTA, and a normal boot, then
             // we need to clear code cache directories.
-            if (!Build.FINGERPRINT.equals(mSettings.mFingerprint) && !onlyCore) {
+            mIsUpgrade = !Build.FINGERPRINT.equals(mSettings.mFingerprint);
+            if (mIsUpgrade && !onlyCore) {
                 Slog.i(TAG, "Build fingerprint changed; clearing code caches");
                 for (String pkgName : mSettings.mPackages.keySet()) {
                     deleteCodeCacheDirsLI(pkgName);
@@ -1800,6 +1802,11 @@
         return mOnlyCore;
     }
 
+    @Override
+    public boolean isUpgrade() {
+        return mIsUpgrade;
+    }
+
     private String getRequiredVerifierLPr() {
         final Intent verification = new Intent(Intent.ACTION_PACKAGE_NEEDS_VERIFICATION);
         final List<ResolveInfo> receivers = queryIntentReceivers(verification, PACKAGE_MIME_TYPE,
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 0e55c1c..13fb96f 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -6049,6 +6049,10 @@
 
         while (true) {
             if (retryCount++ > 0) {
+                // Reset max/min layers on retries so we don't accidentally take a screenshot of a
+                // layer based on the previous try.
+                maxLayer = 0;
+                minLayer = Integer.MAX_VALUE;
                 try {
                     Thread.sleep(100);
                 } catch (InterruptedException e) {
@@ -6071,7 +6075,17 @@
                             continue;
                         }
                     } else if (ws.mIsWallpaper) {
-                        // Fall through.
+                        if (appWin == null) {
+                            // We have not ran across the target window yet, so it is probably
+                            // behind the wallpaper. This can happen when the keyguard is up and
+                            // all windows are moved behind the wallpaper. We don't want to
+                            // include the wallpaper layer in the screenshot as it will coverup
+                            // the layer of the target window.
+                            continue;
+                        }
+                        // Fall through. The target window is in front of the wallpaper. For this
+                        // case we want to include the wallpaper layer in the screenshot because
+                        // the target window might have some transparent areas.
                     } else if (appToken != null) {
                         if (ws.mAppToken == null || ws.mAppToken.token != appToken) {
                             // This app window is of no interest if it is not associated with the
diff --git a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
index cfa4436..11da380 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsDatabase.java
@@ -39,6 +39,7 @@
 
     private static final String TAG = "UsageStatsDatabase";
     private static final boolean DEBUG = UsageStatsService.DEBUG;
+    private static final String BAK_SUFFIX = ".bak";
 
     private final Object mLock = new Object();
     private final File[] mIntervalDirs;
@@ -95,11 +96,71 @@
         }
     }
 
+    public interface CheckinAction {
+        boolean checkin(IntervalStats stats);
+    }
+
+    /**
+     * Calls {@link CheckinAction#checkin(IntervalStats)} on the given {@link CheckinAction}
+     * for all {@link IntervalStats} that haven't been checked-in.
+     * If any of the calls to {@link CheckinAction#checkin(IntervalStats)} returns false or throws
+     * an exception, the check-in will be aborted.
+     *
+     * @param checkinAction The callback to run when checking-in {@link IntervalStats}.
+     * @return true if the check-in succeeded.
+     */
+    public boolean checkinDailyFiles(CheckinAction checkinAction) {
+        synchronized (mLock) {
+            final TimeSparseArray<AtomicFile> files =
+                    mSortedStatFiles[UsageStatsManager.INTERVAL_DAILY];
+            final int fileCount = files.size();
+            int start = 0;
+            while (start < fileCount - 1) {
+                if (!files.valueAt(start).getBaseFile().getName().endsWith("-c")) {
+                    break;
+                }
+            }
+
+            if (start == fileCount - 1) {
+                return true;
+            }
+
+            try {
+                IntervalStats stats = new IntervalStats();
+                for (int i = start; i < fileCount - 1; i++) {
+                    UsageStatsXml.read(files.valueAt(i), stats);
+                    if (!checkinAction.checkin(stats)) {
+                        return false;
+                    }
+                }
+            } catch (IOException e) {
+                Slog.e(TAG, "Failed to check-in", e);
+                return false;
+            }
+
+            // We have successfully checked-in the stats, so rename the files so that they
+            // are marked as checked-in.
+            for (int i = start; i < fileCount - 1; i++) {
+                final AtomicFile file = files.valueAt(i);
+                final File checkedInFile = new File(file.getBaseFile().getParent(),
+                        file.getBaseFile().getName() + "-c");
+                if (!file.getBaseFile().renameTo(checkedInFile)) {
+                    // We must return success, as we've already marked some files as checked-in.
+                    // It's better to repeat ourselves than to lose data.
+                    Slog.e(TAG, "Failed to mark file " + file.getBaseFile().getPath()
+                            + " as checked-in");
+                    return true;
+                }
+            }
+        }
+        return true;
+    }
+
     private void indexFilesLocked() {
         final FilenameFilter backupFileFilter = new FilenameFilter() {
             @Override
             public boolean accept(File dir, String name) {
-                return !name.endsWith(".bak");
+                return !name.endsWith(BAK_SUFFIX);
             }
         };
 
@@ -383,10 +444,10 @@
         if (files != null) {
             for (File f : files) {
                 String path = f.getPath();
-                if (path.endsWith(".bak")) {
-                    f = new File(path.substring(0, path.length() - 4));
+                if (path.endsWith(BAK_SUFFIX)) {
+                    f = new File(path.substring(0, path.length() - BAK_SUFFIX.length()));
                 }
-                long beginTime = Long.parseLong(f.getName());
+                long beginTime = UsageStatsXml.parseBeginTime(f);
                 if (beginTime < expiryTime) {
                     new AtomicFile(f).delete();
                 }
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7ff246a..485b2a2 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -33,7 +33,6 @@
 import android.content.pm.UserInfo;
 import android.content.res.Configuration;
 import android.os.Binder;
-import android.os.Debug;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.Looper;
@@ -48,9 +47,12 @@
 import android.util.SparseArray;
 
 import com.android.internal.os.BackgroundThread;
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.SystemService;
 
 import java.io.File;
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 import java.util.Arrays;
 import java.util.List;
 
@@ -177,7 +179,7 @@
             long currentTimeMillis) {
         UserUsageStatsService service = mUserState.get(userId);
         if (service == null) {
-            service = new UserUsageStatsService(userId,
+            service = new UserUsageStatsService(getContext(), userId,
                     new File(mUsageStatsDir, Integer.toString(userId)), this);
             service.init(currentTimeMillis);
             mUserState.put(userId, service);
@@ -320,6 +322,30 @@
         mHandler.removeMessages(MSG_FLUSH_TO_DISK);
     }
 
+    /**
+     * Called by the Binder stub.
+     */
+    void dump(String[] args, PrintWriter pw) {
+        synchronized (mLock) {
+            IndentingPrintWriter idpw = new IndentingPrintWriter(pw, "  ");
+            ArraySet<String> argSet = new ArraySet<>();
+            argSet.addAll(Arrays.asList(args));
+
+            final int userCount = mUserState.size();
+            for (int i = 0; i < userCount; i++) {
+                idpw.printPair("user", mUserState.keyAt(i));
+                idpw.println();
+                idpw.increaseIndent();
+                if (argSet.contains("--checkin")) {
+                    mUserState.valueAt(i).checkin(idpw);
+                } else {
+                    mUserState.valueAt(i).dump(idpw);
+                }
+                idpw.decreaseIndent();
+            }
+        }
+    }
+
     class H extends Handler {
         public H(Looper looper) {
             super(looper);
@@ -422,6 +448,18 @@
                 Binder.restoreCallingIdentity(token);
             }
         }
+
+        @Override
+        protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+            if (getContext().checkCallingOrSelfPermission(android.Manifest.permission.DUMP)
+                    != PackageManager.PERMISSION_GRANTED) {
+                pw.println("Permission Denial: can't dump UsageStats from pid="
+                        + Binder.getCallingPid() + ", uid=" + Binder.getCallingUid()
+                        + " without permission " + android.Manifest.permission.DUMP);
+                return;
+            }
+            UsageStatsService.this.dump(args, pw);
+        }
     }
 
     /**
diff --git a/services/usage/java/com/android/server/usage/UsageStatsXml.java b/services/usage/java/com/android/server/usage/UsageStatsXml.java
index 9ce6d63..26148ce 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsXml.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsXml.java
@@ -24,21 +24,26 @@
 import org.xmlpull.v1.XmlPullParser;
 import org.xmlpull.v1.XmlPullParserException;
 
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.*;
 
 public class UsageStatsXml {
     private static final String TAG = "UsageStatsXml";
     private static final int CURRENT_VERSION = 1;
     private static final String USAGESTATS_TAG = "usagestats";
     private static final String VERSION_ATTR = "version";
+    private static final String CHECKED_IN_SUFFIX = "-c";
 
     public static long parseBeginTime(AtomicFile file) {
-        return Long.parseLong(file.getBaseFile().getName());
+        return parseBeginTime(file.getBaseFile());
+    }
+
+    public static long parseBeginTime(File file) {
+        final String name = file.getName();
+        if (name.endsWith(CHECKED_IN_SUFFIX)) {
+            return Long.parseLong(
+                    name.substring(0, name.length() - CHECKED_IN_SUFFIX.length()));
+        }
+        return Long.parseLong(name);
     }
 
     public static void read(AtomicFile file, IntervalStats statsOut) throws IOException {
diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
index 4916ec2..6596781 100644
--- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java
@@ -23,9 +23,13 @@
 import android.app.usage.UsageStatsManager;
 import android.content.res.Configuration;
 import android.os.SystemClock;
+import android.content.Context;
+import android.text.format.DateUtils;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
 
+import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.usage.UsageStatsDatabase.StatCombiner;
 
 import java.io.File;
@@ -43,7 +47,13 @@
     private static final String TAG = "UsageStatsService";
     private static final boolean DEBUG = UsageStatsService.DEBUG;
     private static final SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
+    private static final int sDateFormatFlags =
+            DateUtils.FORMAT_SHOW_DATE
+            | DateUtils.FORMAT_SHOW_TIME
+            | DateUtils.FORMAT_SHOW_YEAR
+            | DateUtils.FORMAT_NUMERIC_DATE;
 
+    private final Context mContext;
     private final UsageStatsDatabase mDatabase;
     private final IntervalStats[] mCurrentStats;
     private boolean mStatsChanged = false;
@@ -55,7 +65,8 @@
         void onStatsUpdated();
     }
 
-    UserUsageStatsService(int userId, File usageStatsDir, StatsUpdatedListener listener) {
+    UserUsageStatsService(Context context, int userId, File usageStatsDir, StatsUpdatedListener listener) {
+        mContext = context;
         mDailyExpiryDate = new UnixCalendar(0);
         mDatabase = new UsageStatsDatabase(usageStatsDir);
         mCurrentStats = new IntervalStats[UsageStatsManager.INTERVAL_COUNT];
@@ -433,6 +444,117 @@
                 tempCal.getTimeInMillis() + ")");
     }
 
+    //
+    // -- DUMP related methods --
+    //
+
+    void checkin(final IndentingPrintWriter pw) {
+        mDatabase.checkinDailyFiles(new UsageStatsDatabase.CheckinAction() {
+            @Override
+            public boolean checkin(IntervalStats stats) {
+                printIntervalStats(pw, stats, false);
+                return true;
+            }
+        });
+    }
+
+    void dump(IndentingPrintWriter pw) {
+        // This is not a check-in, only dump in-memory stats.
+        for (int interval = 0; interval < mCurrentStats.length; interval++) {
+            pw.print("In-memory ");
+            pw.print(intervalToString(interval));
+            pw.println(" stats");
+            printIntervalStats(pw, mCurrentStats[interval], true);
+        }
+    }
+
+    private String formatDateTime(long dateTime, boolean pretty) {
+        if (pretty) {
+            return "\"" + DateUtils.formatDateTime(mContext, dateTime, sDateFormatFlags) + "\"";
+        }
+        return Long.toString(dateTime);
+    }
+
+    private String formatElapsedTime(long elapsedTime, boolean pretty) {
+        if (pretty) {
+            return "\"" + DateUtils.formatElapsedTime(elapsedTime / 1000) + "\"";
+        }
+        return Long.toString(elapsedTime);
+    }
+
+    void printIntervalStats(IndentingPrintWriter pw, IntervalStats stats, boolean prettyDates) {
+        if (prettyDates) {
+            pw.printPair("timeRange", "\"" + DateUtils.formatDateRange(mContext,
+                    stats.beginTime, stats.endTime, sDateFormatFlags) + "\"");
+        } else {
+            pw.printPair("beginTime", stats.beginTime);
+            pw.printPair("endTime", stats.endTime);
+        }
+        pw.println();
+        pw.increaseIndent();
+        pw.println("packages");
+        pw.increaseIndent();
+        final ArrayMap<String, UsageStats> pkgStats = stats.packageStats;
+        final int pkgCount = pkgStats.size();
+        for (int i = 0; i < pkgCount; i++) {
+            final UsageStats usageStats = pkgStats.valueAt(i);
+            pw.printPair("package", usageStats.mPackageName);
+            pw.printPair("totalTime", formatElapsedTime(usageStats.mTotalTimeInForeground, prettyDates));
+            pw.printPair("lastTime", formatDateTime(usageStats.mLastTimeUsed, prettyDates));
+            pw.println();
+        }
+        pw.decreaseIndent();
+
+        pw.println("configurations");
+        pw.increaseIndent();
+        final ArrayMap<Configuration, ConfigurationStats> configStats =
+                stats.configurations;
+        final int configCount = configStats.size();
+        for (int i = 0; i < configCount; i++) {
+            final ConfigurationStats config = configStats.valueAt(i);
+            pw.printPair("config", Configuration.resourceQualifierString(config.mConfiguration));
+            pw.printPair("totalTime", formatElapsedTime(config.mTotalTimeActive, prettyDates));
+            pw.printPair("lastTime", formatDateTime(config.mLastTimeActive, prettyDates));
+            pw.printPair("count", config.mActivationCount);
+            pw.println();
+        }
+        pw.decreaseIndent();
+
+        pw.println("events");
+        pw.increaseIndent();
+        final TimeSparseArray<UsageEvents.Event> events = stats.events;
+        final int eventCount = events != null ? events.size() : 0;
+        for (int i = 0; i < eventCount; i++) {
+            final UsageEvents.Event event = events.valueAt(i);
+            pw.printPair("time", formatDateTime(event.mTimeStamp, prettyDates));
+            pw.printPair("type", eventToString(event.mEventType));
+            pw.printPair("package", event.mPackage);
+            if (event.mClass != null) {
+                pw.printPair("class", event.mClass);
+            }
+            if (event.mConfiguration != null) {
+                pw.printPair("config", Configuration.resourceQualifierString(event.mConfiguration));
+            }
+            pw.println();
+        }
+        pw.decreaseIndent();
+        pw.decreaseIndent();
+    }
+
+    private static String intervalToString(int interval) {
+        switch (interval) {
+            case UsageStatsManager.INTERVAL_DAILY:
+                return "daily";
+            case UsageStatsManager.INTERVAL_WEEKLY:
+                return "weekly";
+            case UsageStatsManager.INTERVAL_MONTHLY:
+                return "monthly";
+            case UsageStatsManager.INTERVAL_YEARLY:
+                return "yearly";
+            default:
+                return "?";
+        }
+    }
 
     private static String eventToString(int eventType) {
         switch (eventType) {
diff --git a/telecomm/java/android/telecom/ConferenceParticipant.aidl b/telecomm/java/android/telecom/ConferenceParticipant.aidl
new file mode 100644
index 0000000..020c923
--- /dev/null
+++ b/telecomm/java/android/telecom/ConferenceParticipant.aidl
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2014 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.telecom;
+
+/**
+ * {@hide}
+ */
+parcelable ConferenceParticipant;
diff --git a/telecomm/java/android/telecom/ConferenceParticipant.java b/telecomm/java/android/telecom/ConferenceParticipant.java
new file mode 100644
index 0000000..db0f151
--- /dev/null
+++ b/telecomm/java/android/telecom/ConferenceParticipant.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2014 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.telecom;
+
+import android.net.Uri;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Parcelable representation of a participant's state in a conference call.
+ * @hide
+ */
+public class ConferenceParticipant implements Parcelable {
+
+    /**
+     * The conference participant's handle (e.g., phone number).
+     */
+    private final Uri mHandle;
+
+    /**
+     * The display name for the participant.
+     */
+    private final String mDisplayName;
+
+    /**
+     * The endpoint Uri which uniquely identifies this conference participant.  E.g. for an IMS
+     * conference call, this is the endpoint URI for the participant on the IMS conference server.
+     */
+    private final Uri mEndpoint;
+
+    /**
+     * The state of the participant in the conference.
+     *
+     * @see android.telecom.Connection
+     */
+    private final int mState;
+
+    /**
+     * Creates an instance of {@code ConferenceParticipant}.
+     *
+     * @param handle      The conference participant's handle (e.g., phone number).
+     * @param displayName The display name for the participant.
+     * @param endpoint    The enpoint Uri which uniquely identifies this conference participant.
+     * @param state       The state of the participant in the conference.
+     */
+    public ConferenceParticipant(Uri handle, String displayName, Uri endpoint, int state) {
+        mHandle = handle;
+        mDisplayName = displayName;
+        mEndpoint = endpoint;
+        mState = state;
+    }
+
+    /**
+     * Responsible for creating {@code ConferenceParticipant} objects for deserialized Parcels.
+     */
+    public static final Parcelable.Creator<ConferenceParticipant> CREATOR =
+            new Parcelable.Creator<ConferenceParticipant>() {
+
+                @Override
+                public ConferenceParticipant createFromParcel(Parcel source) {
+                    ClassLoader classLoader = ParcelableCall.class.getClassLoader();
+                    Uri handle = source.readParcelable(classLoader);
+                    String displayName = source.readString();
+                    Uri endpoint = source.readParcelable(classLoader);
+                    int state = source.readInt();
+                    return new ConferenceParticipant(handle, displayName, endpoint, state);
+                }
+
+                @Override
+                public ConferenceParticipant[] newArray(int size) {
+                    return new ConferenceParticipant[size];
+                }
+            };
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * Writes the {@code ConferenceParticipant} to a parcel.
+     *
+     * @param dest The Parcel in which the object should be written.
+     * @param flags Additional flags about how the object should be written.
+     */
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(mHandle, 0);
+        dest.writeString(mDisplayName);
+        dest.writeParcelable(mEndpoint, 0);
+        dest.writeInt(mState);
+    }
+
+    /**
+     * Builds a string representation of this instance.
+     *
+     * @return String representing the conference participant.
+     */
+    @Override
+    public String toString() {
+        StringBuilder sb = new StringBuilder();
+        sb.append("[ConferenceParticipant Handle: ");
+        sb.append(mHandle);
+        sb.append(" DisplayName: ");
+        sb.append(mDisplayName);
+        sb.append(" Endpoint: ");
+        sb.append(mEndpoint);
+        sb.append(" State: ");
+        sb.append(mState);
+        sb.append("]");
+        return sb.toString();
+    }
+
+    /**
+     * The conference participant's handle (e.g., phone number).
+     */
+    public Uri getHandle() {
+        return mHandle;
+    }
+
+    /**
+     * The display name for the participant.
+     */
+    public String getDisplayName() {
+        return mDisplayName;
+    }
+
+    /**
+     * The enpoint Uri which uniquely identifies this conference participant.  E.g. for an IMS
+     * conference call, this is the endpoint URI for the participant on the IMS conference server.
+     */
+    public Uri getEndpoint() {
+        return mEndpoint;
+    }
+
+    /**
+     * The state of the participant in the conference.
+     *
+     * @see android.telecom.Connection
+     */
+    public int getState() {
+        return mState;
+    }
+}
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 2932721..9bdbba8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -82,6 +82,9 @@
         public void onConferenceableConnectionsChanged(
                 Connection c, List<Connection> conferenceableConnections) {}
         public void onConferenceChanged(Connection c, Conference conference) {}
+        /** @hide */
+        public void onConferenceParticipantChanged(Connection c, ConferenceParticipant participant)
+        {}
     }
 
     /** @hide */
@@ -1117,4 +1120,16 @@
         }
         mConferenceableConnections.clear();
     }
+
+    /**
+     * Notifies listeners of a change to a conference participant.
+     *
+     * @param conferenceParticipant The participant.
+     * @hide
+     */
+    protected final void updateConferenceParticipant(ConferenceParticipant conferenceParticipant) {
+        for (Listener l : mListeners) {
+            l.onConferenceParticipantChanged(this, conferenceParticipant);
+        }
+    }
 }
diff --git a/telephony/java/com/android/ims/ImsConferenceState.java b/telephony/java/com/android/ims/ImsConferenceState.java
index f708d5b..c57ef98 100644
--- a/telephony/java/com/android/ims/ImsConferenceState.java
+++ b/telephony/java/com/android/ims/ImsConferenceState.java
@@ -24,6 +24,8 @@
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
+import android.telecom.Call;
+import android.telecom.Connection;
 
 /**
  * Provides the conference information (defined in RFC 4575) for IMS conference call.
@@ -139,4 +141,30 @@
             return new ImsConferenceState[size];
         }
     };
+
+    /**
+     * Translates an {@code ImsConferenceState} status type to a telecom connection state.
+     *
+     * @param status The status type.
+     * @return The corresponding {@link android.telecom.Connection} state.
+     */
+    public static int getConnectionStateForStatus(String status) {
+        if (status.equals(STATUS_PENDING)) {
+            return Connection.STATE_INITIALIZING;
+        } else if (status.equals(STATUS_DIALING_IN)) {
+            return Connection.STATE_RINGING;
+        } else if (status.equals(STATUS_ALERTING) ||
+                status.equals(STATUS_DIALING_OUT)) {
+            return Connection.STATE_DIALING;
+        } else if (status.equals(STATUS_ON_HOLD)) {
+            return Connection.STATE_HOLDING;
+        } else if (status.equals(STATUS_CONNECTED) ||
+                status.equals(STATUS_MUTED_VIA_FOCUS) ||
+                status.equals(STATUS_DISCONNECTING)) {
+            return Connection.STATE_ACTIVE;
+        } else if (status.equals(STATUS_DISCONNECTED)) {
+            return Connection.STATE_DISCONNECTED;
+        }
+        return Call.STATE_ACTIVE;
+    }
 }
diff --git a/test-runner/src/android/test/mock/MockPackageManager.java b/test-runner/src/android/test/mock/MockPackageManager.java
index 7f1dc71..7531d7b 100644
--- a/test-runner/src/android/test/mock/MockPackageManager.java
+++ b/test-runner/src/android/test/mock/MockPackageManager.java
@@ -733,6 +733,14 @@
      * @hide
      */
     @Override
+    public boolean isUpgrade() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * @hide
+     */
+    @Override
     public void installPackage(Uri packageURI, PackageInstallObserver observer,
             int flags, String installerPackageName) {
         throw new UnsupportedOperationException();