Merge "Fixing no first "device added" notification." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index d5685a6..3e0a1b3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -4000,6 +4000,7 @@
   public deprecated class AssistContent {
     ctor public AssistContent();
     method public android.content.ClipData getClipData();
+    method public android.os.Bundle getExtras();
     method public android.net.Uri getWebUri();
     method public boolean isAppProvidedIntent();
     method public void setClipData(android.content.ClipData);
@@ -4058,6 +4059,7 @@
   }
 
   public static class AssistStructure.WindowNode {
+    method public int getDisplayId();
     method public int getHeight();
     method public int getLeft();
     method public android.app.AssistStructure.ViewNode getRootViewNode();
@@ -8457,8 +8459,6 @@
     field public static final int NO_MATCH_CATEGORY = -4; // 0xfffffffc
     field public static final int NO_MATCH_DATA = -2; // 0xfffffffe
     field public static final int NO_MATCH_TYPE = -1; // 0xffffffff
-    field public static final java.lang.String SCHEME_HTTP = "http";
-    field public static final java.lang.String SCHEME_HTTPS = "https";
     field public static final int SYSTEM_HIGH_PRIORITY = 1000; // 0x3e8
     field public static final int SYSTEM_LOW_PRIORITY = -1000; // 0xfffffc18
   }
@@ -37054,6 +37054,7 @@
 
   public abstract class ViewStructure {
     ctor public ViewStructure();
+    method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewAssistStructure asyncNewChild(int);
     method public abstract int getChildCount();
diff --git a/api/system-current.txt b/api/system-current.txt
index fbf8d1d..a61b9fb53 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -4096,6 +4096,7 @@
   public deprecated class AssistContent {
     ctor public AssistContent();
     method public android.content.ClipData getClipData();
+    method public android.os.Bundle getExtras();
     method public android.net.Uri getWebUri();
     method public boolean isAppProvidedIntent();
     method public void setClipData(android.content.ClipData);
@@ -4154,6 +4155,7 @@
   }
 
   public static class AssistStructure.WindowNode {
+    method public int getDisplayId();
     method public int getHeight();
     method public int getLeft();
     method public android.app.AssistStructure.ViewNode getRootViewNode();
@@ -8689,8 +8691,6 @@
     field public static final int NO_MATCH_CATEGORY = -4; // 0xfffffffc
     field public static final int NO_MATCH_DATA = -2; // 0xfffffffe
     field public static final int NO_MATCH_TYPE = -1; // 0xffffffff
-    field public static final java.lang.String SCHEME_HTTP = "http";
-    field public static final java.lang.String SCHEME_HTTPS = "https";
     field public static final int SYSTEM_HIGH_PRIORITY = 1000; // 0x3e8
     field public static final int SYSTEM_LOW_PRIORITY = -1000; // 0xfffffc18
   }
@@ -39331,6 +39331,7 @@
 
   public abstract class ViewStructure {
     ctor public ViewStructure();
+    method public abstract int addChildCount(int);
     method public abstract void asyncCommit();
     method public abstract android.view.ViewAssistStructure asyncNewChild(int);
     method public abstract int getChildCount();
diff --git a/core/java/android/app/ActivityManager.java b/core/java/android/app/ActivityManager.java
index da345a6..b65593d 100644
--- a/core/java/android/app/ActivityManager.java
+++ b/core/java/android/app/ActivityManager.java
@@ -2812,7 +2812,9 @@
      * continues running even if the process is killed and restarted.  To remove the watch,
      * use {@link #clearWatchHeapLimit()}.
      *
-     * <p>This API only work if running on a debuggable (userdebug or eng) build.</p>
+     * <p>This API only work if the calling process has been marked as
+     * {@link ApplicationInfo#FLAG_DEBUGGABLE} or this is running on a debuggable
+     * (userdebug or eng) build.</p>
      *
      * <p>Callers can optionally implement {@link #ACTION_REPORT_HEAP_LIMIT} to directly
      * handle heap limit reports themselves.</p>
diff --git a/core/java/android/app/AlarmManager.java b/core/java/android/app/AlarmManager.java
index 5e7bd0d..9ea1606 100644
--- a/core/java/android/app/AlarmManager.java
+++ b/core/java/android/app/AlarmManager.java
@@ -142,13 +142,22 @@
     public static final int FLAG_ALLOW_WHILE_IDLE = 1<<2;
 
     /**
+     * Flag for alarms: same as {@link #FLAG_ALLOW_WHILE_IDLE}, but doesn't have restrictions
+     * on how frequently it can be scheduled.  Only available (and automatically applied) to
+     * system alarms.
+     *
+     * @hide
+     */
+    public static final int FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED = 1<<3;
+
+    /**
      * Flag for alarms: this alarm marks the point where we would like to come out of idle
      * mode.  It may be moved by the alarm manager to match the first wake-from-idle alarm.
      * Scheduling an alarm with this flag puts the alarm manager in to idle mode, where it
      * avoids scheduling any further alarms until the marker alarm is executed.
      * @hide
      */
-    public static final int FLAG_IDLE_UNTIL = 1<<3;
+    public static final int FLAG_IDLE_UNTIL = 1<<4;
 
     private final IAlarmManager mService;
     private final boolean mAlwaysExact;
@@ -565,6 +574,12 @@
      * of the device when idle (and thus cause significant battery blame to the app scheduling
      * them), so they should be used with care.
      *
+     * <p>To reduce abuse, there are restrictions on how frequently these alarms will go off
+     * for a particular application.  Under normal system operation, it will not dispatch these
+     * alarms more than about every minute (at which point every such pending alarm is
+     * dispatched); when in low-power idle modes this duration may be significantly longer,
+     * such as 15 minutes.</p>
+     *
      * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
      * out of order with any other alarms, even those from the same app.  This will clearly happen
      * when the device is idle (since this alarm can go off while idle, when any other alarms
@@ -608,6 +623,12 @@
      * of the device when idle (and thus cause significant battery blame to the app scheduling
      * them), so they should be used with care.
      *
+     * <p>To reduce abuse, there are restrictions on how frequently these alarms will go off
+     * for a particular application.  Under normal system operation, it will not dispatch these
+     * alarms more than about every minute (at which point every such pending alarm is
+     * dispatched); when in low-power idle modes this duration may be significantly longer,
+     * such as 15 minutes.</p>
+     *
      * <p>Unlike other alarms, the system is free to reschedule this type of alarm to happen
      * out of order with any other alarms, even those from the same app.  This will clearly happen
      * when the device is idle (since this alarm can go off while idle, when any other alarms
diff --git a/core/java/android/app/AssistContent.java b/core/java/android/app/AssistContent.java
index 173b237..0df9ce5 100644
--- a/core/java/android/app/AssistContent.java
+++ b/core/java/android/app/AssistContent.java
@@ -35,6 +35,7 @@
     private Intent mIntent;
     private ClipData mClipData;
     private Uri mUri;
+    private final Bundle mExtras;
 
     /**
      * @hide
@@ -53,6 +54,7 @@
     }
 
     public AssistContent() {
+        mExtras = new Bundle();
     }
 
     /**
@@ -143,6 +145,13 @@
         return mUri;
     }
 
+    /**
+     * Return Bundle for extra vendor-specific data that can be modified and examined.
+     */
+    public Bundle getExtras() {
+        return mExtras;
+    }
+
     /** @hide */
     public AssistContent(Parcel in) {
         if (in.readInt() != 0) {
@@ -155,6 +164,7 @@
             mUri = Uri.CREATOR.createFromParcel(in);
         }
         mIsAppProvidedIntent = in.readInt() == 1;
+        mExtras = in.readBundle();
     }
 
     /** @hide */
@@ -178,5 +188,6 @@
             dest.writeInt(0);
         }
         dest.writeInt(mIsAppProvidedIntent ? 1 : 0);
+        dest.writeBundle(mExtras);
     }
 }
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index 0f69817..7f6dae5 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -131,6 +131,7 @@
         final int mWidth;
         final int mHeight;
         final CharSequence mTitle;
+        final int mDisplayId;
         final ViewNode mRoot;
 
         WindowNode(AssistStructure assist, ViewRootImpl root) {
@@ -142,6 +143,7 @@
             mWidth = rect.width();
             mHeight = rect.height();
             mTitle = root.getTitle();
+            mDisplayId = root.getDisplayId();
             mRoot = new ViewNode();
             ViewNodeBuilder builder = new ViewNodeBuilder(assist, mRoot, false);
             if ((root.getWindowFlags()&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
@@ -160,6 +162,7 @@
             mWidth = in.readInt();
             mHeight = in.readInt();
             mTitle = TextUtils.CHAR_SEQUENCE_CREATOR.createFromParcel(in);
+            mDisplayId = in.readInt();
             mRoot = new ViewNode(in, preader);
         }
 
@@ -169,29 +172,58 @@
             out.writeInt(mWidth);
             out.writeInt(mHeight);
             TextUtils.writeToParcel(mTitle, out, 0);
+            out.writeInt(mDisplayId);
             mRoot.writeToParcel(out, pwriter);
         }
 
+        /**
+         * Returns the left edge of the window, in pixels, relative to the left
+         * edge of the screen.
+         */
         public int getLeft() {
             return mX;
         }
 
+        /**
+         * Returns the top edge of the window, in pixels, relative to the top
+         * edge of the screen.
+         */
         public int getTop() {
             return mY;
         }
 
+        /**
+         * Returns the total width of the window in pixels.
+         */
         public int getWidth() {
             return mWidth;
         }
 
+        /**
+         * Returns the total height of the window in pixels.
+         */
         public int getHeight() {
             return mHeight;
         }
 
+        /**
+         * Returns the title associated with the window, if it has one.
+         */
         public CharSequence getTitle() {
             return mTitle;
         }
 
+        /**
+         * Returns the ID of the display this window is on, for use with
+         * {@link android.hardware.display.DisplayManager#getDisplay DisplayManager.getDisplay()}.
+         */
+        public int getDisplayId() {
+            return mDisplayId;
+        }
+
+        /**
+         * Returns the {@link ViewNode} containing the root content of the window.
+         */
         public ViewNode getRootViewNode() {
             return mRoot;
         }
@@ -325,146 +357,288 @@
             }
         }
 
+        /**
+         * Returns the ID associated with this view, as per {@link View#getId() View.getId()}.
+         */
         public int getId() {
             return mId;
         }
 
+        /**
+         * If {@link #getId()} is a resource identifier, this is the package name of that
+         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
+         * for more information.
+         */
         public String getIdPackage() {
             return mIdPackage;
         }
 
+        /**
+         * If {@link #getId()} is a resource identifier, this is the type name of that
+         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
+         * for more information.
+         */
         public String getIdType() {
             return mIdType;
         }
 
+        /**
+         * If {@link #getId()} is a resource identifier, this is the entry name of that
+         * identifier.  See {@link android.view.ViewStructure#setId ViewStructure.setId}
+         * for more information.
+         */
         public String getIdEntry() {
             return mIdEntry;
         }
 
+        /**
+         * Returns the left edge of this view, in pixels, relative to the left edge of its parent.
+         */
         public int getLeft() {
             return mX;
         }
 
+        /**
+         * Returns the top edge of this view, in pixels, relative to the top edge of its parent.
+         */
         public int getTop() {
             return mY;
         }
 
+        /**
+         * Returns the current X scroll offset of this view, as per
+         * {@link android.view.View#getScrollX() View.getScrollX()}.
+         */
         public int getScrollX() {
             return mScrollX;
         }
 
+        /**
+         * Returns the current Y scroll offset of this view, as per
+         * {@link android.view.View#getScrollX() View.getScrollY()}.
+         */
         public int getScrollY() {
             return mScrollY;
         }
 
+        /**
+         * Returns the width of this view, in pixels.
+         */
         public int getWidth() {
             return mWidth;
         }
 
+        /**
+         * Returns the height of this view, in pixels.
+         */
         public int getHeight() {
             return mHeight;
         }
 
+        /**
+         * Returns the visibility mode of this view, as per
+         * {@link android.view.View#getVisibility() View.getVisibility()}.
+         */
         public int getVisibility() {
             return mFlags&ViewNode.FLAGS_VISIBILITY_MASK;
         }
 
+        /**
+         * Returns true if assist data has been blocked starting at this node in the hierarchy.
+         */
         public boolean isAssistBlocked() {
             return (mFlags&ViewNode.FLAGS_ASSIST_BLOCKED) == 0;
         }
 
+        /**
+         * Returns true if this node is in an enabled state.
+         */
         public boolean isEnabled() {
             return (mFlags&ViewNode.FLAGS_DISABLED) == 0;
         }
 
+        /**
+         * Returns true if this node is clickable by the user.
+         */
         public boolean isClickable() {
             return (mFlags&ViewNode.FLAGS_CLICKABLE) != 0;
         }
 
+        /**
+         * Returns true if this node can take input focus.
+         */
         public boolean isFocusable() {
             return (mFlags&ViewNode.FLAGS_FOCUSABLE) != 0;
         }
 
+        /**
+         * Returns true if this node currently had input focus at the time that the
+         * structure was collected.
+         */
         public boolean isFocused() {
             return (mFlags&ViewNode.FLAGS_FOCUSED) != 0;
         }
 
+        /**
+         * Returns true if this node currently had accessibility focus at the time that the
+         * structure was collected.
+         */
         public boolean isAccessibilityFocused() {
             return (mFlags&ViewNode.FLAGS_ACCESSIBILITY_FOCUSED) != 0;
         }
 
+        /**
+         * Returns true if this node represents something that is checkable by the user.
+         */
         public boolean isCheckable() {
             return (mFlags&ViewNode.FLAGS_CHECKABLE) != 0;
         }
 
+        /**
+         * Returns true if this node is currently in a checked state.
+         */
         public boolean isChecked() {
             return (mFlags&ViewNode.FLAGS_CHECKED) != 0;
         }
 
+        /**
+         * Returns true if this node has currently been selected by the user.
+         */
         public boolean isSelected() {
             return (mFlags&ViewNode.FLAGS_SELECTED) != 0;
         }
 
+        /**
+         * Returns true if this node has currently been activated by the user.
+         */
         public boolean isActivated() {
             return (mFlags&ViewNode.FLAGS_ACTIVATED) != 0;
         }
 
+        /**
+         * Returns true if this node is something the user can perform a long click/press on.
+         */
         public boolean isLongClickable() {
             return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
         }
 
+        /**
+         * Returns true if this node is something the user can perform a context click on.
+         */
         public boolean isContextClickable() {
             return (mFlags&ViewNode.FLAGS_CONTEXT_CLICKABLE) != 0;
         }
 
+        /**
+         * Returns the class name of the node's implementation, indicating its behavior.
+         * For example, a button will report "android.widget.Button" meaning it behaves
+         * like a {@link android.widget.Button}.
+         */
         public String getClassName() {
             return mClassName;
         }
 
+        /**
+         * Returns any content description associated with the node, which semantically describes
+         * its purpose for accessibility and other uses.
+         */
         public CharSequence getContentDescription() {
             return mContentDescription;
         }
 
+        /**
+         * Returns any text associated with the node that is displayed to the user, or null
+         * if there is none.
+         */
         public CharSequence getText() {
             return mText != null ? mText.mText : null;
         }
 
+        /**
+         * If {@link #getText()} is non-null, this is where the current selection starts.
+         */
         public int getTextSelectionStart() {
             return mText != null ? mText.mTextSelectionStart : -1;
         }
 
+        /**
+         * If {@link #getText()} is non-null, this is where the current selection starts.
+         * If there is no selection, returns the same value as {@link #getTextSelectionStart()},
+         * indicating the cursor position.
+         */
         public int getTextSelectionEnd() {
             return mText != null ? mText.mTextSelectionEnd : -1;
         }
 
+        /**
+         * If {@link #getText()} is non-null, this is the main text color associated with it.
+         * If there is no text color, {@link #TEXT_COLOR_UNDEFINED} is returned.
+         * Note that the text may also contain style spans that modify the color of specific
+         * parts of the text.
+         */
         public int getTextColor() {
             return mText != null ? mText.mTextColor : TEXT_COLOR_UNDEFINED;
         }
 
+        /**
+         * If {@link #getText()} is non-null, this is the main text background color associated
+         * with it.
+         * If there is no text background color, {@link #TEXT_COLOR_UNDEFINED} is returned.
+         * Note that the text may also contain style spans that modify the color of specific
+         * parts of the text.
+         */
         public int getTextBackgroundColor() {
             return mText != null ? mText.mTextBackgroundColor : TEXT_COLOR_UNDEFINED;
         }
 
+        /**
+         * If {@link #getText()} is non-null, this is the main text size (in pixels) associated
+         * with it.
+         * Note that the text may also contain style spans that modify the size of specific
+         * parts of the text.
+         */
         public float getTextSize() {
             return mText != null ? mText.mTextSize : 0;
         }
 
+        /**
+         * If {@link #getText()} is non-null, this is the main text style associated
+         * with it, containing a bit mask of {@link #TEXT_STYLE_BOLD},
+         * {@link #TEXT_STYLE_BOLD}, {@link #TEXT_STYLE_STRIKE_THRU}, and/or
+         * {@link #TEXT_STYLE_UNDERLINE}.
+         * Note that the text may also contain style spans that modify the style of specific
+         * parts of the text.
+         */
         public int getTextStyle() {
             return mText != null ? mText.mTextStyle : 0;
         }
 
+        /**
+         * Return additional hint text associated with the node; this is typically used with
+         * a node that takes user input, describing to the user what the input means.
+         */
         public String getHint() {
             return mText != null ? mText.mHint : null;
         }
 
+        /**
+         * Return a Bundle containing optional vendor-specific extension information.
+         */
         public Bundle getExtras() {
             return mExtras;
         }
 
+        /**
+         * Return the number of children this node has.
+         */
         public int getChildCount() {
             return mChildren != null ? mChildren.length : 0;
         }
 
+        /**
+         * Return a child of this node, given an index value from 0 to
+         * {@link #getChildCount()}-1.
+         */
         public ViewNode getChildAt(int index) {
             return mChildren[index];
         }
@@ -663,6 +837,19 @@
         }
 
         @Override
+        public int addChildCount(int num) {
+            if (mNode.mChildren == null) {
+                setChildCount(num);
+                return 0;
+            }
+            final int start = mNode.mChildren.length;
+            ViewNode[] newArray = new ViewNode[start + num];
+            System.arraycopy(mNode.mChildren, 0, newArray, 0, start);
+            mNode.mChildren = newArray;
+            return start;
+        }
+
+        @Override
         public int getChildCount() {
             return mNode.mChildren != null ? mNode.mChildren.length : 0;
         }
@@ -801,6 +988,9 @@
         return assistBundle.getParcelable(ASSIST_KEY);
     }
 
+    /**
+     * Return the activity this AssistStructure came from.
+     */
     public ComponentName getActivityComponent() {
         ensureData();
         return mActivityComponent;
diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 2ed8b0f..5327646 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -418,7 +418,7 @@
         private int mNotificationVisibility = VISIBILITY_VISIBLE;
 
         /**
-         * @param uri the HTTP URI to download.
+         * @param uri the HTTP or HTTPS URI to download.
          */
         public Request(Uri uri) {
             if (uri == null) {
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 96c6878..33a47b24 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1331,11 +1331,14 @@
     public Notification(Context context, int icon, CharSequence tickerText, long when,
             CharSequence contentTitle, CharSequence contentText, Intent contentIntent)
     {
-        this.when = when;
-        this.icon = icon;
-        this.tickerText = tickerText;
-        setLatestEventInfo(context, contentTitle, contentText,
-                PendingIntent.getActivity(context, 0, contentIntent, 0));
+        new Builder(context)
+                .setWhen(when)
+                .setSmallIcon(icon)
+                .setTicker(tickerText)
+                .setContentTitle(contentTitle)
+                .setContentText(contentText)
+                .setContentIntent(PendingIntent.getActivity(context, 0, contentIntent, 0))
+                .buildInto(this);
     }
 
     /**
diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java
index 42d0dcb..9f49154 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -149,6 +149,7 @@
      * <li>{@link #EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME}</li>
      * <li>{@link #EXTRA_PROVISIONING_SKIP_ENCRYPTION}, optional</li>
      * <li>{@link #EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED}, optional</li>
+     * <li>{@link #EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE}, optional</li>
      * </ul>
      *
      * <p> When device owner provisioning has completed, an intent of the type
@@ -163,14 +164,19 @@
         = "android.app.action.PROVISION_MANAGED_DEVICE";
 
     /**
-     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that allows
-     * a mobile device management application that starts managed profile provisioning to pass data
-     * to itself on the managed profile when provisioning completes. The mobile device management
-     * application sends this extra in an intent with the action
-     * {@link #ACTION_PROVISION_MANAGED_PROFILE} and receives it in
+     * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
+     * allows a mobile device management application which starts managed provisioning to pass data
+     * to itself.
+     * <p>
+     * If used with {@link #ACTION_PROVISION_MANAGED_PROFILE} it can be used by the application that
+     * sends the intent to pass data to itself on the newly created profile.
+     * If used with {@link #ACTION_PROVISION_MANAGED_DEVICE} it allows passing data to the same
+     * instance of the app on the primary user.
+     * <p>
+     * In both cases the application receives the data in
      * {@link DeviceAdminReceiver#onProfileProvisioningComplete} via an intent with the action
      * {@link DeviceAdminReceiver#ACTION_PROFILE_PROVISIONING_COMPLETE}. The bundle is not changed
-     * during the managed profile provisioning.
+     * during the managed provisioning.
      */
     public static final String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE =
             "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
diff --git a/core/java/android/content/ContentProviderClient.java b/core/java/android/content/ContentProviderClient.java
index e15ac94..d12595f 100644
--- a/core/java/android/content/ContentProviderClient.java
+++ b/core/java/android/content/ContentProviderClient.java
@@ -16,6 +16,8 @@
 
 package android.content;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.content.res.AssetFileDescriptor;
 import android.database.Cursor;
 import android.net.Uri;
@@ -30,6 +32,7 @@
 import android.util.Log;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.util.Preconditions;
 
 import dalvik.system.CloseGuard;
 
@@ -109,14 +112,19 @@
     }
 
     /** See {@link ContentProvider#query ContentProvider.query} */
-    public Cursor query(Uri url, String[] projection, String selection,
-            String[] selectionArgs, String sortOrder) throws RemoteException {
+    public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder) throws RemoteException {
         return query(url, projection, selection,  selectionArgs, sortOrder, null);
     }
 
     /** See {@link ContentProvider#query ContentProvider.query} */
-    public Cursor query(Uri url, String[] projection, String selection, String[] selectionArgs,
-            String sortOrder, CancellationSignal cancellationSignal) throws RemoteException {
+    public @Nullable Cursor query(@NonNull Uri url, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal)
+                    throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             ICancellationSignal remoteCancellationSignal = null;
@@ -138,7 +146,9 @@
     }
 
     /** See {@link ContentProvider#getType ContentProvider.getType} */
-    public String getType(Uri url) throws RemoteException {
+    public @Nullable String getType(@NonNull Uri url) throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             return mContentProvider.getType(url);
@@ -153,7 +163,11 @@
     }
 
     /** See {@link ContentProvider#getStreamTypes ContentProvider.getStreamTypes} */
-    public String[] getStreamTypes(Uri url, String mimeTypeFilter) throws RemoteException {
+    public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter)
+            throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+        Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+
         beforeRemote();
         try {
             return mContentProvider.getStreamTypes(url, mimeTypeFilter);
@@ -168,7 +182,9 @@
     }
 
     /** See {@link ContentProvider#canonicalize} */
-    public final Uri canonicalize(Uri url) throws RemoteException {
+    public final @Nullable Uri canonicalize(@NonNull Uri url) throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             return mContentProvider.canonicalize(mPackageName, url);
@@ -183,7 +199,9 @@
     }
 
     /** See {@link ContentProvider#uncanonicalize} */
-    public final Uri uncanonicalize(Uri url) throws RemoteException {
+    public final @Nullable Uri uncanonicalize(@NonNull Uri url) throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             return mContentProvider.uncanonicalize(mPackageName, url);
@@ -198,7 +216,10 @@
     }
 
     /** See {@link ContentProvider#insert ContentProvider.insert} */
-    public Uri insert(Uri url, ContentValues initialValues) throws RemoteException {
+    public @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues initialValues)
+            throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             return mContentProvider.insert(mPackageName, url, initialValues);
@@ -213,7 +234,11 @@
     }
 
     /** See {@link ContentProvider#bulkInsert ContentProvider.bulkInsert} */
-    public int bulkInsert(Uri url, ContentValues[] initialValues) throws RemoteException {
+    public int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] initialValues)
+            throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+        Preconditions.checkNotNull(initialValues, "initialValues");
+
         beforeRemote();
         try {
             return mContentProvider.bulkInsert(mPackageName, url, initialValues);
@@ -228,8 +253,10 @@
     }
 
     /** See {@link ContentProvider#delete ContentProvider.delete} */
-    public int delete(Uri url, String selection, String[] selectionArgs)
-            throws RemoteException {
+    public int delete(@NonNull Uri url, @Nullable String selection,
+            @Nullable String[] selectionArgs) throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             return mContentProvider.delete(mPackageName, url, selection, selectionArgs);
@@ -244,8 +271,10 @@
     }
 
     /** See {@link ContentProvider#update ContentProvider.update} */
-    public int update(Uri url, ContentValues values, String selection,
-            String[] selectionArgs) throws RemoteException {
+    public int update(@NonNull Uri url, @Nullable ContentValues values, @Nullable String selection,
+            @Nullable String[] selectionArgs) throws RemoteException {
+        Preconditions.checkNotNull(url, "url");
+
         beforeRemote();
         try {
             return mContentProvider.update(mPackageName, url, values, selection, selectionArgs);
@@ -266,7 +295,7 @@
      * you use the {@link ContentResolver#openFileDescriptor
      * ContentResolver.openFileDescriptor} API instead.
      */
-    public ParcelFileDescriptor openFile(Uri url, String mode)
+    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode)
             throws RemoteException, FileNotFoundException {
         return openFile(url, mode, null);
     }
@@ -278,8 +307,11 @@
      * you use the {@link ContentResolver#openFileDescriptor
      * ContentResolver.openFileDescriptor} API instead.
      */
-    public ParcelFileDescriptor openFile(Uri url, String mode, CancellationSignal signal)
-            throws RemoteException, FileNotFoundException {
+    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri url, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
+        Preconditions.checkNotNull(url, "url");
+        Preconditions.checkNotNull(mode, "mode");
+
         beforeRemote();
         try {
             ICancellationSignal remoteSignal = null;
@@ -306,7 +338,7 @@
      * you use the {@link ContentResolver#openAssetFileDescriptor
      * ContentResolver.openAssetFileDescriptor} API instead.
      */
-    public AssetFileDescriptor openAssetFile(Uri url, String mode)
+    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode)
             throws RemoteException, FileNotFoundException {
         return openAssetFile(url, mode, null);
     }
@@ -318,8 +350,11 @@
      * you use the {@link ContentResolver#openAssetFileDescriptor
      * ContentResolver.openAssetFileDescriptor} API instead.
      */
-    public AssetFileDescriptor openAssetFile(Uri url, String mode, CancellationSignal signal)
-            throws RemoteException, FileNotFoundException {
+    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri url, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws RemoteException, FileNotFoundException {
+        Preconditions.checkNotNull(url, "url");
+        Preconditions.checkNotNull(mode, "mode");
+
         beforeRemote();
         try {
             ICancellationSignal remoteSignal = null;
@@ -340,15 +375,19 @@
     }
 
     /** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
-    public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
-            String mimeType, Bundle opts) throws RemoteException, FileNotFoundException {
+    public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+            @NonNull String mimeType, @Nullable Bundle opts)
+                    throws RemoteException, FileNotFoundException {
         return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
     }
 
     /** See {@link ContentProvider#openTypedAssetFile ContentProvider.openTypedAssetFile} */
-    public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
-            String mimeType, Bundle opts, CancellationSignal signal)
-            throws RemoteException, FileNotFoundException {
+    public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+            @NonNull String mimeType, @Nullable Bundle opts, @Nullable CancellationSignal signal)
+                    throws RemoteException, FileNotFoundException {
+        Preconditions.checkNotNull(uri, "uri");
+        Preconditions.checkNotNull(mimeType, "mimeType");
+
         beforeRemote();
         try {
             ICancellationSignal remoteSignal = null;
@@ -370,8 +409,11 @@
     }
 
     /** See {@link ContentProvider#applyBatch ContentProvider.applyBatch} */
-    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
-            throws RemoteException, OperationApplicationException {
+    public @NonNull ContentProviderResult[] applyBatch(
+            @NonNull ArrayList<ContentProviderOperation> operations)
+                    throws RemoteException, OperationApplicationException {
+        Preconditions.checkNotNull(operations, "operations");
+
         beforeRemote();
         try {
             return mContentProvider.applyBatch(mPackageName, operations);
@@ -386,7 +428,10 @@
     }
 
     /** See {@link ContentProvider#call(String, String, Bundle)} */
-    public Bundle call(String method, String arg, Bundle extras) throws RemoteException {
+    public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
+            @Nullable Bundle extras) throws RemoteException {
+        Preconditions.checkNotNull(method, "method");
+
         beforeRemote();
         try {
             return mContentProvider.call(mPackageName, method, arg, extras);
@@ -436,7 +481,7 @@
      * @return If the associated {@link ContentProvider} is local, returns it.
      * Otherwise returns null.
      */
-    public ContentProvider getLocalContentProvider() {
+    public @Nullable ContentProvider getLocalContentProvider() {
         return ContentProvider.coerceToLocalContentProvider(mContentProvider);
     }
 
diff --git a/core/java/android/content/IntentFilter.java b/core/java/android/content/IntentFilter.java
index 33c0b87..08c5236 100644
--- a/core/java/android/content/IntentFilter.java
+++ b/core/java/android/content/IntentFilter.java
@@ -254,12 +254,14 @@
      * HTTP scheme.
      *
      * @see #addDataScheme(String)
+     * @hide
      */
     public static final String SCHEME_HTTP = "http";
     /**
      * HTTPS scheme.
      *
      * @see #addDataScheme(String)
+     * @hide
      */
     public static final String SCHEME_HTTPS = "https";
 
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index a6efc58..f76192e 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -1177,8 +1177,13 @@
         public static final int EVENT_ALARM = 0x000e;
         // Record that we have decided we need to collect new stats data.
         public static final int EVENT_COLLECT_EXTERNAL_STATS = 0x000f;
+        // Event for a package becoming inactive due to being unused for a period of time.
+        public static final int EVENT_PACKAGE_INACTIVE = 0x0010;
+        // Event for a package becoming active due to an interaction.
+        public static final int EVENT_PACKAGE_ACTIVE = 0x0011;
+
         // Number of event types.
-        public static final int EVENT_COUNT = 0x0010;
+        public static final int EVENT_COUNT = 0x0012;
         // Mask to extract out only the type part of the event.
         public static final int EVENT_TYPE_MASK = ~(EVENT_FLAG_START|EVENT_FLAG_FINISH);
 
@@ -1835,12 +1840,12 @@
 
     public static final String[] HISTORY_EVENT_NAMES = new String[] {
             "null", "proc", "fg", "top", "sync", "wake_lock_in", "job", "user", "userfg", "conn",
-            "motion", "active", "pkginst", "pkgunin", "alarm", "stats"
+            "motion", "active", "pkginst", "pkgunin", "alarm", "stats", "inactive", "active"
     };
 
     public static final String[] HISTORY_EVENT_CHECKIN_NAMES = new String[] {
             "Enl", "Epr", "Efg", "Etp", "Esy", "Ewl", "Ejb", "Eur", "Euf", "Ecn",
-            "Esm", "Eac", "Epi", "Epu", "Eal", "Est"
+            "Esm", "Eac", "Epi", "Epu", "Eal", "Est", "Eai", "Eaa"
     };
 
     /**
diff --git a/core/java/android/os/PowerManager.java b/core/java/android/os/PowerManager.java
index 8b18f32..7a1aa1e 100644
--- a/core/java/android/os/PowerManager.java
+++ b/core/java/android/os/PowerManager.java
@@ -878,7 +878,10 @@
      * off network access to apps.  You can monitor for changes to this state with
      * {@link #ACTION_DEVICE_IDLE_MODE_CHANGED}.
      *
-     * @return Returns true if currently in low power mode, else false.
+     * @return Returns true if currently in active device idle mode, else false.  This is
+     * when idle mode restrictions are being actively applied; it will return false if the
+     * device is in a long-term idle mode but currently running a maintenance window where
+     * restrictions have been lifted.
      */
     public boolean isDeviceIdleMode() {
         try {
diff --git a/core/java/android/speech/tts/UtteranceProgressListener.java b/core/java/android/speech/tts/UtteranceProgressListener.java
index 9eb22ef..890ea3d 100644
--- a/core/java/android/speech/tts/UtteranceProgressListener.java
+++ b/core/java/android/speech/tts/UtteranceProgressListener.java
@@ -61,16 +61,16 @@
 
     /**
      * Called when an utterance has been stopped while in progress or flushed from the
-     * synthesis queue. This can happen if client calls {@link TextToSpeech#stop()}
-     * or use {@link TextToSpeech#QUEUE_FLUSH} as an argument in
+     * synthesis queue. This can happen if a client calls {@link TextToSpeech#stop()}
+     * or uses {@link TextToSpeech#QUEUE_FLUSH} as an argument with the
      * {@link TextToSpeech#speak} or {@link TextToSpeech#synthesizeToFile} methods.
      *
      * @param utteranceId the utterance ID of the utterance.
-     * @param isStarted If true, then utterance was interrupted while being synthesized
-     *        and it's output is incomplete. If it's false, then utterance was flushed
+     * @param interrupted If true, then the utterance was interrupted while being synthesized
+     *        and its output is incomplete. If false, then the utterance was flushed
      *        before the synthesis started.
      */
-    public void onStop(String utteranceId, boolean isStarted) {
+    public void onStop(String utteranceId, boolean interrupted) {
     }
 
     /**
@@ -99,7 +99,7 @@
             }
 
             @Override
-            public void onStop(String utteranceId, boolean isStarted) {
+            public void onStop(String utteranceId, boolean interrupted) {
                 listener.onUtteranceCompleted(utteranceId);
             }
         };
diff --git a/core/java/android/util/TimeUtils.java b/core/java/android/util/TimeUtils.java
index f7d28218..353388d 100644
--- a/core/java/android/util/TimeUtils.java
+++ b/core/java/android/util/TimeUtils.java
@@ -246,41 +246,65 @@
     public static final long NANOS_PER_MS = 1000000;
 
     private static final Object sFormatSync = new Object();
-    private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+5];
-
-    private static final long LARGEST_DURATION = (1000 * DateUtils.DAY_IN_MILLIS) - 1;
+    private static char[] sFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
+    private static char[] sTmpFormatStr = new char[HUNDRED_DAY_FIELD_LEN+10];
 
     static private int accumField(int amt, int suffix, boolean always, int zeropad) {
-        if (amt > 99 || (always && zeropad >= 3)) {
-            return 3+suffix;
-        }
-        if (amt > 9 || (always && zeropad >= 2)) {
-            return 2+suffix;
-        }
-        if (always || amt > 0) {
-            return 1+suffix;
+        if (amt > 999) {
+            int num = 0;
+            while (amt != 0) {
+                num++;
+                amt /= 10;
+            }
+            return num + suffix;
+        } else {
+            if (amt > 99 || (always && zeropad >= 3)) {
+                return 3+suffix;
+            }
+            if (amt > 9 || (always && zeropad >= 2)) {
+                return 2+suffix;
+            }
+            if (always || amt > 0) {
+                return 1+suffix;
+            }
         }
         return 0;
     }
 
-    static private int printField(char[] formatStr, int amt, char suffix, int pos,
+    static private int printFieldLocked(char[] formatStr, int amt, char suffix, int pos,
             boolean always, int zeropad) {
         if (always || amt > 0) {
             final int startPos = pos;
-            if ((always && zeropad >= 3) || amt > 99) {
-                int dig = amt/100;
-                formatStr[pos] = (char)(dig + '0');
+            if (amt > 999) {
+                int tmp = 0;
+                while (amt != 0 && tmp < sTmpFormatStr.length) {
+                    int dig = amt % 10;
+                    sTmpFormatStr[tmp] = (char)(dig + '0');
+                    tmp++;
+                    amt /= 10;
+                }
+                tmp--;
+                while (tmp >= 0) {
+                    formatStr[pos] = sTmpFormatStr[tmp];
+                    pos++;
+                    tmp--;
+                }
+            } else {
+                if ((always && zeropad >= 3) || amt > 99) {
+                    int dig = amt/100;
+                    formatStr[pos] = (char)(dig + '0');
+                    pos++;
+                    amt -= (dig*100);
+                }
+                if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
+                    int dig = amt/10;
+                    formatStr[pos] = (char)(dig + '0');
+                    pos++;
+                    amt -= (dig*10);
+                }
+                formatStr[pos] = (char)(amt + '0');
                 pos++;
-                amt -= (dig*100);
             }
-            if ((always && zeropad >= 2) || amt > 9 || startPos != pos) {
-                int dig = amt/10;
-                formatStr[pos] = (char)(dig + '0');
-                pos++;
-                amt -= (dig*10);
-            }
-            formatStr[pos] = (char)(amt + '0');
-            pos++;
             formatStr[pos] = suffix;
             pos++;
         }
@@ -312,10 +336,6 @@
             duration = -duration;
         }
 
-        if (duration > LARGEST_DURATION) {
-            duration = LARGEST_DURATION;
-        }
-
         int millis = (int)(duration%1000);
         int seconds = (int) Math.floor(duration / 1000);
         int days = 0, hours = 0, minutes = 0;
@@ -353,11 +373,11 @@
 
         int start = pos;
         boolean zeropad = fieldLen != 0;
-        pos = printField(formatStr, days, 'd', pos, false, 0);
-        pos = printField(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
-        pos = printField(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
-        pos = printField(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
-        pos = printField(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
+        pos = printFieldLocked(formatStr, days, 'd', pos, false, 0);
+        pos = printFieldLocked(formatStr, hours, 'h', pos, pos != start, zeropad ? 2 : 0);
+        pos = printFieldLocked(formatStr, minutes, 'm', pos, pos != start, zeropad ? 2 : 0);
+        pos = printFieldLocked(formatStr, seconds, 's', pos, pos != start, zeropad ? 2 : 0);
+        pos = printFieldLocked(formatStr, millis, 'm', pos, true, (zeropad && pos != start) ? 3 : 0);
         formatStr[pos] = 's';
         return pos + 1;
     }
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index e2f42db..8b57d96 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -663,6 +663,10 @@
         return mWindowAttributes.flags;
     }
 
+    public int getDisplayId() {
+        return mDisplay.getDisplayId();
+    }
+
     public CharSequence getTitle() {
         return mWindowAttributes.getTitle();
     }
diff --git a/core/java/android/view/ViewStructure.java b/core/java/android/view/ViewStructure.java
index 8ceb166..d06cd83 100644
--- a/core/java/android/view/ViewStructure.java
+++ b/core/java/android/view/ViewStructure.java
@@ -201,6 +201,17 @@
     public abstract void setChildCount(int num);
 
     /**
+     * Add to this view's child count.  This increases the current child count by
+     * <var>num</var> children beyond what was last set by {@link #setChildCount}
+     * or {@link #addChildCount}.  The index at which the new child starts in the child
+     * array is returned.
+     *
+     * @param num The number of new children to add.
+     * @return Returns the index in the child array at which the new children start.
+     */
+    public abstract int addChildCount(int num);
+
+    /**
      * Return the child count as set by {@link #setChildCount}.
      */
     public abstract int getChildCount();
diff --git a/core/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index 353901c..78b5d5d 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -8790,7 +8790,8 @@
     @Override
     public void onProvideStructure(ViewStructure structure) {
         super.onProvideStructure(structure);
-        final boolean isPassword = hasPasswordTransformationMethod();
+        final boolean isPassword = hasPasswordTransformationMethod()
+                || isPasswordInputType(getInputType());
         if (!isPassword) {
             structure.setText(getText(), getSelectionStart(), getSelectionEnd());
 
@@ -9244,25 +9245,25 @@
     /**
      * If provided, this ActionMode.Callback will be used to create the ActionMode when text
      * insertion is initiated in this View.
-     *
      * The standard implementation populates the menu with a subset of Select All,
      * Paste and Replace actions, depending on what this View supports.
      *
-     * A custom implementation can add new entries in the default menu in its
-     * {@link android.view.ActionMode.Callback#onPrepareActionMode(ActionMode, Menu)} method. The
-     * default actions can also be removed from the menu using
+     * <p>A custom implementation can add new entries in the default menu in its
+     * {@link android.view.ActionMode.Callback#onPrepareActionMode(android.view.ActionMode,
+     * android.view.Menu)} method. The default actions can also be removed from the menu using
      * {@link android.view.Menu#removeItem(int)} and passing {@link android.R.id#selectAll},
-     * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.
+     * {@link android.R.id#paste} or {@link android.R.id#replaceText} ids as parameters.</p>
      *
-     * Returning false from
-     * {@link android.view.ActionMode.Callback#onCreateActionMode(ActionMode, Menu)} will prevent
-     * the action mode from being started.
+     * <p>Returning false from
+     * {@link android.view.ActionMode.Callback#onCreateActionMode(android.view.ActionMode,
+     * android.view.Menu)} will prevent the action mode from being started.</p>
      *
-     * Action click events should be handled by the custom implementation of
-     * {@link android.view.ActionMode.Callback#onActionItemClicked(ActionMode, MenuItem)}.
+     * <p>Action click events should be handled by the custom implementation of
+     * {@link android.view.ActionMode.Callback#onActionItemClicked(android.view.ActionMode,
+     * android.view.MenuItem)}.</p>
      *
-     * Note that text insertion mode is not started when a TextView receives focus and the
-     * {@link android.R.attr#selectAllOnFocus} flag has been set.
+     * <p>Note that text insertion mode is not started when a TextView receives focus and the
+     * {@link android.R.attr#selectAllOnFocus} flag has been set.</p>
      */
     public void setCustomInsertionActionModeCallback(ActionMode.Callback actionModeCallback) {
         createEditorIfNeeded();
diff --git a/core/java/com/android/internal/app/WindowDecorActionBar.java b/core/java/com/android/internal/app/WindowDecorActionBar.java
index 7ae7d0f..05cfd81 100644
--- a/core/java/com/android/internal/app/WindowDecorActionBar.java
+++ b/core/java/com/android/internal/app/WindowDecorActionBar.java
@@ -47,7 +47,6 @@
 import android.graphics.drawable.Drawable;
 import android.util.TypedValue;
 import android.view.ActionMode;
-import android.view.ActionMode.Callback;
 import android.view.ContextThemeWrapper;
 import android.view.LayoutInflater;
 import android.view.Menu;
@@ -106,6 +105,10 @@
 
     private static final int INVALID_POSITION = -1;
 
+    // The fade duration for toolbar and action bar when entering/exiting action mode.
+    private static final long FADE_OUT_DURATION_MS = 100;
+    private static final long FADE_IN_DURATION_MS = 200;
+
     private int mContextDisplayMode;
     private boolean mHasEmbeddedTabs;
 
@@ -866,8 +869,21 @@
             hideForActionMode();
         }
 
-        mDecorToolbar.animateToVisibility(toActionMode ? View.GONE : View.VISIBLE);
-        mContextView.animateToVisibility(toActionMode ? View.VISIBLE : View.GONE);
+        Animator fadeIn, fadeOut;
+        if (toActionMode) {
+            fadeOut = mDecorToolbar.setupAnimatorToVisibility(View.GONE,
+                    FADE_OUT_DURATION_MS);
+            fadeIn = mContextView.setupAnimatorToVisibility(View.VISIBLE,
+                    FADE_IN_DURATION_MS);
+        } else {
+            fadeIn = mDecorToolbar.setupAnimatorToVisibility(View.VISIBLE,
+                    FADE_IN_DURATION_MS);
+            fadeOut = mContextView.setupAnimatorToVisibility(View.GONE,
+                    FADE_OUT_DURATION_MS);
+        }
+        AnimatorSet set = new AnimatorSet();
+        set.playSequentially(fadeOut, fadeIn);
+        set.start();
         // mTabScrollView's visibility is not affected by action mode.
     }
 
diff --git a/core/java/com/android/internal/widget/AbsActionBarView.java b/core/java/com/android/internal/widget/AbsActionBarView.java
index 850ea23..35eeca7 100644
--- a/core/java/com/android/internal/widget/AbsActionBarView.java
+++ b/core/java/com/android/internal/widget/AbsActionBarView.java
@@ -136,10 +136,11 @@
         return getVisibility();
     }
 
-    public void animateToVisibility(int visibility) {
+    public Animator setupAnimatorToVisibility(int visibility, long duration) {
         if (mVisibilityAnim != null) {
             mVisibilityAnim.cancel();
         }
+
         if (visibility == VISIBLE) {
             if (getVisibility() != VISIBLE) {
                 setAlpha(0);
@@ -147,38 +148,43 @@
                     mMenuView.setAlpha(0);
                 }
             }
-            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 1);
-            anim.setDuration(FADE_DURATION);
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, View.ALPHA, 1);
+            anim.setDuration(duration);
             anim.setInterpolator(sAlphaInterpolator);
             if (mSplitView != null && mMenuView != null) {
                 AnimatorSet set = new AnimatorSet();
-                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 1);
-                splitAnim.setDuration(FADE_DURATION);
+                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, View.ALPHA, 1);
+                splitAnim.setDuration(duration);
                 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
                 set.play(anim).with(splitAnim);
-                set.start();
+                return set;
             } else {
                 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
-                anim.start();
+                return anim;
             }
         } else {
-            ObjectAnimator anim = ObjectAnimator.ofFloat(this, "alpha", 0);
-            anim.setDuration(FADE_DURATION);
+            ObjectAnimator anim = ObjectAnimator.ofFloat(this, View.ALPHA, 0);
+            anim.setDuration(duration);
             anim.setInterpolator(sAlphaInterpolator);
             if (mSplitView != null && mMenuView != null) {
                 AnimatorSet set = new AnimatorSet();
-                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, "alpha", 0);
-                splitAnim.setDuration(FADE_DURATION);
+                ObjectAnimator splitAnim = ObjectAnimator.ofFloat(mMenuView, View.ALPHA, 0);
+                splitAnim.setDuration(duration);
                 set.addListener(mVisAnimListener.withFinalVisibility(visibility));
                 set.play(anim).with(splitAnim);
-                set.start();
+                return set;
             } else {
                 anim.addListener(mVisAnimListener.withFinalVisibility(visibility));
-                anim.start();
+                return anim;
             }
         }
     }
 
+    public void animateToVisibility(int visibility) {
+        Animator anim = setupAnimatorToVisibility(visibility, FADE_DURATION);
+        anim.start();
+    }
+
     @Override
     public void setVisibility(int visibility) {
         if (visibility != getVisibility()) {
diff --git a/core/java/com/android/internal/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index c5d3290..693b194 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -21,10 +21,6 @@
 import android.widget.ActionMenuView;
 import com.android.internal.view.menu.MenuBuilder;
 
-import android.animation.Animator;
-import android.animation.Animator.AnimatorListener;
-import android.animation.AnimatorSet;
-import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.content.res.TypedArray;
 import android.graphics.drawable.Drawable;
@@ -35,14 +31,13 @@
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.accessibility.AccessibilityEvent;
-import android.view.animation.DecelerateInterpolator;
 import android.widget.LinearLayout;
 import android.widget.TextView;
 
 /**
  * @hide
  */
-public class ActionBarContextView extends AbsActionBarView implements AnimatorListener {
+public class ActionBarContextView extends AbsActionBarView {
     private static final String TAG = "ActionBarContextView";
 
     private CharSequence mTitle;
@@ -59,14 +54,6 @@
     private boolean mTitleOptional;
     private int mCloseItemLayout;
 
-    private Animator mCurrentAnimation;
-    private boolean mAnimateInOnLayout;
-    private int mAnimationMode;
-
-    private static final int ANIMATE_IDLE = 0;
-    private static final int ANIMATE_IN = 1;
-    private static final int ANIMATE_OUT = 2;
-    
     public ActionBarContextView(Context context) {
         this(context, null);
     }
@@ -255,43 +242,23 @@
             mMenuView.setBackgroundDrawable(mSplitBackground);
             mSplitView.addView(mMenuView, layoutParams);
         }
-
-        mAnimateInOnLayout = true;
     }
 
     public void closeMode() {
-        if (mAnimationMode == ANIMATE_OUT) {
-            // Called again during close; just finish what we were doing.
-            return;
-        }
         if (mClose == null) {
             killMode();
             return;
         }
 
-        finishAnimation();
-        mAnimationMode = ANIMATE_OUT;
-        mCurrentAnimation = makeOutAnimation();
-        mCurrentAnimation.start();
-    }
-
-    private void finishAnimation() {
-        final Animator a = mCurrentAnimation;
-        if (a != null) {
-            mCurrentAnimation = null;
-            a.end();
-        }
     }
 
     public void killMode() {
-        finishAnimation();
         removeAllViews();
         if (mSplitView != null) {
             mSplitView.removeView(mMenuView);
         }
         mCustomView = null;
         mMenuView = null;
-        mAnimateInOnLayout = false;
     }
 
     @Override
@@ -343,7 +310,7 @@
             throw new IllegalStateException(getClass().getSimpleName() + " can only be used " +
                     "with android:layout_height=\"wrap_content\"");
         }
-        
+
         final int contentWidth = MeasureSpec.getSize(widthMeasureSpec);
 
         int maxHeight = mContentHeight > 0 ?
@@ -353,7 +320,7 @@
         int availableWidth = contentWidth - getPaddingLeft() - getPaddingRight();
         final int height = maxHeight - verticalPadding;
         final int childSpecHeight = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
-        
+
         if (mClose != null) {
             availableWidth = measureChildView(mClose, availableWidth, childSpecHeight, 0);
             MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams();
@@ -411,66 +378,13 @@
         }
     }
 
-    private Animator makeInAnimation() {
-        mClose.setTranslationX(-mClose.getWidth() -
-                ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin);
-        ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX", 0);
-        buttonAnimator.setDuration(200);
-        buttonAnimator.addListener(this);
-        buttonAnimator.setInterpolator(new DecelerateInterpolator());
-
-        AnimatorSet set = new AnimatorSet();
-        AnimatorSet.Builder b = set.play(buttonAnimator);
-
-        if (mMenuView != null) {
-            final int count = mMenuView.getChildCount();
-            if (count > 0) {
-                for (int i = count - 1, j = 0; i >= 0; i--, j++) {
-                    View child = mMenuView.getChildAt(i);
-                    child.setScaleY(0);
-                    ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0, 1);
-                    a.setDuration(300);
-                    b.with(a);
-                }
-            }
-        }
-
-        return set;
-    }
-
-    private Animator makeOutAnimation() {
-        ObjectAnimator buttonAnimator = ObjectAnimator.ofFloat(mClose, "translationX",
-                -mClose.getWidth() - ((MarginLayoutParams) mClose.getLayoutParams()).leftMargin);
-        buttonAnimator.setDuration(200);
-        buttonAnimator.addListener(this);
-        buttonAnimator.setInterpolator(new DecelerateInterpolator());
-
-        AnimatorSet set = new AnimatorSet();
-        AnimatorSet.Builder b = set.play(buttonAnimator);
-
-        if (mMenuView != null) {
-            final int count = mMenuView.getChildCount();
-            if (count > 0) {
-                for (int i = 0; i < 0; i++) {
-                    View child = mMenuView.getChildAt(i);
-                    child.setScaleY(0);
-                    ObjectAnimator a = ObjectAnimator.ofFloat(child, "scaleY", 0);
-                    a.setDuration(300);
-                    b.with(a);
-                }
-            }
-        }
-
-        return set;
-    }
-
     @Override
     protected void onLayout(boolean changed, int l, int t, int r, int b) {
         final boolean isLayoutRtl = isLayoutRtl();
         int x = isLayoutRtl ? r - l - getPaddingRight() : getPaddingLeft();
         final int y = getPaddingTop();
         final int contentHeight = b - t - getPaddingTop() - getPaddingBottom();
-        
+
         if (mClose != null && mClose.getVisibility() != GONE) {
             MarginLayoutParams lp = (MarginLayoutParams) mClose.getLayoutParams();
             final int startMargin = (isLayoutRtl ? lp.rightMargin : lp.leftMargin);
@@ -479,12 +393,6 @@
             x += positionChild(mClose, x, y, contentHeight, isLayoutRtl);
             x = next(x, endMargin, isLayoutRtl);
 
-            if (mAnimateInOnLayout) {
-                mAnimationMode = ANIMATE_IN;
-                mCurrentAnimation = makeInAnimation();
-                mCurrentAnimation.start();
-                mAnimateInOnLayout = false;
-            }
         }
 
         if (mTitleLayout != null && mCustomView == null && mTitleLayout.getVisibility() != GONE) {
@@ -503,26 +411,6 @@
     }
 
     @Override
-    public void onAnimationStart(Animator animation) {
-    }
-
-    @Override
-    public void onAnimationEnd(Animator animation) {
-        if (mAnimationMode == ANIMATE_OUT) {
-            killMode();
-        }
-        mAnimationMode = ANIMATE_IDLE;
-    }
-
-    @Override
-    public void onAnimationCancel(Animator animation) {
-    }
-
-    @Override
-    public void onAnimationRepeat(Animator animation) {
-    }
-
-    @Override
     public boolean shouldDelayChildPressedState() {
         return false;
     }
diff --git a/core/java/com/android/internal/widget/DecorToolbar.java b/core/java/com/android/internal/widget/DecorToolbar.java
index fb413b5..fe70d7b 100644
--- a/core/java/com/android/internal/widget/DecorToolbar.java
+++ b/core/java/com/android/internal/widget/DecorToolbar.java
@@ -17,6 +17,7 @@
 
 package com.android.internal.widget;
 
+import android.animation.Animator;
 import android.content.Context;
 import android.graphics.drawable.Drawable;
 import android.os.Parcelable;
@@ -87,6 +88,7 @@
     void setCustomView(View view);
     View getCustomView();
     void animateToVisibility(int visibility);
+    Animator setupAnimatorToVisibility(int visibility, long duration);
     void setNavigationIcon(Drawable icon);
     void setNavigationIcon(int resId);
     void setNavigationContentDescription(CharSequence description);
diff --git a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
index 54df87b..32aae72 100644
--- a/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
+++ b/core/java/com/android/internal/widget/ToolbarWidgetWrapper.java
@@ -19,6 +19,7 @@
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
 import android.app.ActionBar;
 import android.content.Context;
 import android.content.res.TypedArray;
@@ -59,6 +60,8 @@
 
     private static final int AFFECTS_LOGO_MASK =
             ActionBar.DISPLAY_SHOW_HOME | ActionBar.DISPLAY_USE_LOGO;
+    // Default fade duration for fading in/out tool bar.
+    private static final long DEFAULT_FADE_DURATION_MS = 200;
 
     private Toolbar mToolbar;
 
@@ -571,9 +574,19 @@
 
     @Override
     public void animateToVisibility(int visibility) {
+        Animator anim = setupAnimatorToVisibility(visibility, DEFAULT_FADE_DURATION_MS);
+        if (anim != null) {
+            anim.start();
+        }
+    }
+
+    @Override
+    public Animator setupAnimatorToVisibility(int visibility, long duration) {
+
         if (visibility == View.GONE) {
-            mToolbar.animate().alpha(0)
-                    .setListener(new AnimatorListenerAdapter() {
+            ObjectAnimator anim = ObjectAnimator.ofFloat(mToolbar, View.ALPHA, 1, 0);
+            anim.setDuration(duration);
+            anim.addListener(new AnimatorListenerAdapter() {
                         private boolean mCanceled = false;
                         @Override
                         public void onAnimationEnd(Animator animation) {
@@ -587,15 +600,19 @@
                             mCanceled = true;
                         }
                     });
+            return anim;
         } else if (visibility == View.VISIBLE) {
-            mToolbar.animate().alpha(1)
-                    .setListener(new AnimatorListenerAdapter() {
+            ObjectAnimator anim = ObjectAnimator.ofFloat(mToolbar, View.ALPHA, 0, 1);
+            anim.setDuration(duration);
+            anim.addListener(new AnimatorListenerAdapter() {
                         @Override
                         public void onAnimationStart(Animator animation) {
                             mToolbar.setVisibility(View.VISIBLE);
                         }
                     });
+            return anim;
         }
+        return null;
     }
 
     @Override
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index a13dc85..97df978e 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -58,6 +58,7 @@
                 android:layout_marginStart="4dp"
                 android:scaleType="fitCenter"
                 android:visibility="gone"
+                android:contentDescription="@string/notification_work_profile_content_description"
                 />
         </LinearLayout>
         <include
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index b677a98..7ae29fb 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -60,6 +60,7 @@
                 android:layout_marginStart="4dp"
                 android:scaleType="fitCenter"
                 android:visibility="gone"
+                android:contentDescription="@string/notification_work_profile_content_description"
                 />
         </LinearLayout>
         <ImageView
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index c109225..950ae40 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -62,6 +62,7 @@
                 android:layout_marginStart="4dp"
                 android:scaleType="fitCenter"
                 android:visibility="gone"
+                android:contentDescription="@string/notification_work_profile_content_description"
                 />
         </LinearLayout>
         <TextView android:id="@+id/inbox_text1"
diff --git a/core/res/res/layout/notification_template_part_line2.xml b/core/res/res/layout/notification_template_part_line2.xml
index aeef3ab..db43271 100644
--- a/core/res/res/layout/notification_template_part_line2.xml
+++ b/core/res/res/layout/notification_template_part_line2.xml
@@ -43,6 +43,7 @@
             android:layout_marginStart="4dp"
             android:scaleType="fitCenter"
             android:visibility="gone"
+            android:contentDescription="@string/notification_work_profile_content_description"
             />
     </LinearLayout>
     <ViewStub
diff --git a/core/res/res/layout/notification_template_part_line3.xml b/core/res/res/layout/notification_template_part_line3.xml
index 6c043a0..da3c5c5 100644
--- a/core/res/res/layout/notification_template_part_line3.xml
+++ b/core/res/res/layout/notification_template_part_line3.xml
@@ -51,5 +51,6 @@
         android:layout_marginStart="4dp"
         android:scaleType="fitCenter"
         android:visibility="gone"
+        android:contentDescription="@string/notification_work_profile_content_description"
         />
 </LinearLayout>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index a6b7e35..915a445 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4168,6 +4168,9 @@
     <string name="stk_cc_ss_to_ussd">SS request is modified to USSD request.</string>
     <string name="stk_cc_ss_to_ss">SS request is modified to new SS request.</string>
 
+    <!-- Content description of the work profile icon in the notification. -->
+    <string name="notification_work_profile_content_description">Work profile</string>
+
     <!-- User visible name for USB MIDI Peripheral port -->
     <string name="usb_midi_peripheral_name">Android USB Peripheral Port</string>
     <!-- Manufacturer name for USB MIDI Peripheral port -->
diff --git a/core/tests/notificationtests/src/android/app/NotificationStressTest.java b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
index 52ea1c4..4cb617e 100644
--- a/core/tests/notificationtests/src/android/app/NotificationStressTest.java
+++ b/core/tests/notificationtests/src/android/app/NotificationStressTest.java
@@ -77,15 +77,20 @@
     }
 
     private void sendNotification(int id, CharSequence text) {
-        // Create "typical" notification with random icon
-        Notification notification = new Notification(ICONS[mRandom.nextInt(ICONS.length)], text,
-                System.currentTimeMillis());
         // Fill in arbitrary content
         Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
         PendingIntent pendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
         CharSequence title = text + " " + id;
         CharSequence subtitle = String.valueOf(System.currentTimeMillis());
-        notification.setLatestEventInfo(mContext, title, subtitle, pendingIntent);
+        // Create "typical" notification with random icon
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(ICONS[mRandom.nextInt(ICONS.length)])
+                .setTicker(text)
+                .setWhen(System.currentTimeMillis())
+                .setContentTitle(title)
+                .setContentText(subtitle)
+                .setContentIntent(pendingIntent)
+                .build();
         mNotificationManager.notify(id, notification);
         SystemClock.sleep(10);
     }
diff --git a/graphics/java/android/graphics/drawable/Drawable.java b/graphics/java/android/graphics/drawable/Drawable.java
index e8e4664..532c888 100644
--- a/graphics/java/android/graphics/drawable/Drawable.java
+++ b/graphics/java/android/graphics/drawable/Drawable.java
@@ -809,6 +809,14 @@
      * {@link android.graphics.PixelFormat#TRANSPARENT}, or
      * {@link android.graphics.PixelFormat#OPAQUE}.
      *
+     * <p>An OPAQUE drawable is one that draws all all content within its bounds, completely
+     * covering anything behind the drawable. A TRANSPARENT drawable is one that draws nothing
+     * within its bounds, allowing everything behind it to show through. A TRANSLUCENT drawable
+     * is a drawable in any other state, where the drawable will draw some, but not all,
+     * of the content within its bounds and at least some content behind the drawable will
+     * be visible. If the visibility of the drawable's contents cannot be determined, the
+     * safest/best return value is TRANSLUCENT.
+     *
      * <p>Generally a Drawable should be as conservative as possible with the
      * value it returns.  For example, if it contains multiple child drawables
      * and only shows one of them at a time, if only one of the children is
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
index 19375a2..d2d5850 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreCipherSpiBase.java
@@ -368,7 +368,10 @@
 
         byte[] output;
         try {
-            output = mMainDataStreamer.doFinal(input, inputOffset, inputLen);
+            byte[] additionalEntropy =
+                    KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
+                            mRng, getAdditionalEntropyAmountForFinish());
+            output = mMainDataStreamer.doFinal(input, inputOffset, inputLen, additionalEntropy);
         } catch (KeyStoreException e) {
             switch (e.getErrorCode()) {
                 case KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH:
@@ -667,21 +670,37 @@
 
     /**
      * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
-     * {@code begin} operation.
+     * {@code begin} operation. This amount of entropy is typically what's consumed to generate
+     * random parameters, such as IV.
      *
-     * <p>For decryption, this should be {@code 0} because decryption should not be consuming any
-     * entropy. For encryption, this value should match (or exceed) the amount of Shannon entropy of
-     * the ciphertext produced by this cipher assuming the key, the plaintext, and all explicitly
-     * provided parameters to {@code Cipher.init} are known. For example, for AES CBC encryption
-     * with an explicitly provided IV this should be {@code 0}, whereas for the case where IV is
-     * generated by the KeyStore's {@code begin} operation this should be {@code 16}. For RSA with
-     * OAEP this should be the size of the OAEP hash output. For RSA with PKCS#1 padding this should
-     * be the size of the padding string or could be raised (for simplicity) to the size of the
-     * modulus.
+     * <p>For decryption, the return value should be {@code 0} because decryption should not be
+     * consuming any entropy. For encryption, the value combined with
+     * {@link #getAdditionalEntropyAmountForFinish()} should match (or exceed) the amount of Shannon
+     * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
+     * explicitly provided parameters to {@code Cipher.init} are known. For example, for AES CBC
+     * encryption with an explicitly provided IV the return value should be {@code 0}, whereas for
+     * the case where IV is generated by the KeyStore's {@code begin} operation it should be
+     * {@code 16}.
      */
     protected abstract int getAdditionalEntropyAmountForBegin();
 
     /**
+     * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
+     * {@code finish} operation. This amount of entropy is typically what's consumed by encryption
+     * padding scheme.
+     *
+     * <p>For decryption, the return value should be {@code 0} because decryption should not be
+     * consuming any entropy. For encryption, the value combined with
+     * {@link #getAdditionalEntropyAmountForBegin()} should match (or exceed) the amount of Shannon
+     * entropy of the ciphertext produced by this cipher assuming the key, the plaintext, and all
+     * explicitly provided parameters to {@code Cipher.init} are known. For example, for RSA with
+     * OAEP the return value should be the size of the OAEP hash output. For RSA with PKCS#1 padding
+     * the return value should be the size of the padding string or could be raised (for simplicity)
+     * to the size of the modulus.
+     */
+    protected abstract int getAdditionalEntropyAmountForFinish();
+
+    /**
      * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
      *
      * @param keymasterArgs keystore/keymaster arguments to be populated with algorithm-specific
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
index 335da07..d19a766 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreECDSASignatureSpi.java
@@ -117,7 +117,7 @@
     }
 
     @Override
-    protected int getAdditionalEntropyAmountForBegin() {
-        return (isSigning()) ? mGroupSizeBytes : 0;
+    protected int getAdditionalEntropyAmountForSign() {
+        return mGroupSizeBytes;
     }
 }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
index f31c06d..f7c184c 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreHmacSpi.java
@@ -232,7 +232,10 @@
 
         byte[] result;
         try {
-            result = mChunkedStreamer.doFinal(null, 0, 0);
+            result = mChunkedStreamer.doFinal(
+                    null, 0, 0,
+                    null // no additional entropy needed -- HMAC is deterministic
+                    );
         } catch (KeyStoreException e) {
             throw new ProviderException("Keystore operation failed", e);
         }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
index 35af34f..b93424d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java
@@ -215,14 +215,8 @@
                                     legacySpec.getKeystoreAlias(),
                                     KeyProperties.PURPOSE_SIGN
                                     | KeyProperties.PURPOSE_VERIFY);
-                            specBuilder.setDigests(
-                                    KeyProperties.DIGEST_NONE,
-                                    KeyProperties.DIGEST_MD5,
-                                    KeyProperties.DIGEST_SHA1,
-                                    KeyProperties.DIGEST_SHA224,
-                                    KeyProperties.DIGEST_SHA256,
-                                    KeyProperties.DIGEST_SHA384,
-                                    KeyProperties.DIGEST_SHA512);
+                            // Authorized to be used with any digest (including no digest).
+                            specBuilder.setDigests(KeyProperties.DIGEST_NONE);
                             break;
                         case KeymasterDefs.KM_ALGORITHM_RSA:
                             specBuilder = new KeyGenParameterSpec.Builder(
@@ -231,19 +225,13 @@
                                     | KeyProperties.PURPOSE_DECRYPT
                                     | KeyProperties.PURPOSE_SIGN
                                     | KeyProperties.PURPOSE_VERIFY);
-                            specBuilder.setDigests(
-                                    KeyProperties.DIGEST_NONE,
-                                    KeyProperties.DIGEST_MD5,
-                                    KeyProperties.DIGEST_SHA1,
-                                    KeyProperties.DIGEST_SHA224,
-                                    KeyProperties.DIGEST_SHA256,
-                                    KeyProperties.DIGEST_SHA384,
-                                    KeyProperties.DIGEST_SHA512);
+                            // Authorized to be used with any digest (including no digest).
+                            specBuilder.setDigests(KeyProperties.DIGEST_NONE);
                             specBuilder.setSignaturePaddings(
                                     KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
+                            // Authorized to be used with any padding (including no padding).
                             specBuilder.setEncryptionPaddings(
-                                    KeyProperties.ENCRYPTION_PADDING_NONE,
-                                    KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
+                                    KeyProperties.ENCRYPTION_PADDING_NONE);
                             // Disable randomized encryption requirement to support encryption
                             // padding NONE above.
                             specBuilder.setRandomizedEncryptionRequired(false);
@@ -703,6 +691,36 @@
             }
             case KeymasterDefs.KM_ALGORITHM_RSA:
             {
+                // Check whether this key is authorized for PKCS#1 signature padding.
+                // We use Bouncy Castle to generate self-signed RSA certificates. Bouncy Castle
+                // only supports RSA certificates signed using PKCS#1 padding scheme. The key needs
+                // to be authorized for PKCS#1 padding or padding NONE which means any padding.
+                boolean pkcs1SignaturePaddingSupported = false;
+                for (int keymasterPadding : KeyProperties.SignaturePadding.allToKeymaster(
+                        spec.getSignaturePaddings())) {
+                    if ((keymasterPadding == KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_SIGN)
+                            || (keymasterPadding == KeymasterDefs.KM_PAD_NONE)) {
+                        pkcs1SignaturePaddingSupported = true;
+                        break;
+                    }
+                }
+                if (!pkcs1SignaturePaddingSupported) {
+                    // Keymaster doesn't distinguish between encryption padding NONE and signature
+                    // padding NONE. In the Android Keystore API only encryption padding NONE is
+                    // exposed.
+                    for (int keymasterPadding : KeyProperties.EncryptionPadding.allToKeymaster(
+                            spec.getEncryptionPaddings())) {
+                        if (keymasterPadding == KeymasterDefs.KM_PAD_NONE) {
+                            pkcs1SignaturePaddingSupported = true;
+                            break;
+                        }
+                    }
+                }
+                if (!pkcs1SignaturePaddingSupported) {
+                    // Key not authorized for PKCS#1 signature padding -- can't sign
+                    return null;
+                }
+
                 Set<Integer> availableKeymasterDigests = getAvailableKeymasterSignatureDigests(
                         spec.getDigests(),
                         AndroidKeyStoreBCWorkaroundProvider.getSupportedEcdsaSignatureDigests());
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
index d33692a..6abdf19 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSACipherSpi.java
@@ -99,6 +99,11 @@
         }
 
         @Override
+        protected final int getAdditionalEntropyAmountForFinish() {
+            return 0;
+        }
+
+        @Override
         @NonNull
         protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
                 KeyStore keyStore, IBinder operationToken) {
@@ -142,7 +147,8 @@
             }
 
             @Override
-            public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
+            public byte[] doFinal(byte[] input, int inputOffset, int inputLength,
+                    byte[] additionalEntropy)
                     throws KeyStoreException {
                 if (inputLength > 0) {
                     mInputBuffer.write(input, inputOffset, inputLength);
@@ -165,7 +171,7 @@
                             "Message size (" + bufferedInput.length + " bytes) must be smaller than"
                             + " modulus (" + mModulusSizeBytes + " bytes)");
                 }
-                return mDelegate.doFinal(paddedInput, 0, paddedInput.length);
+                return mDelegate.doFinal(paddedInput, 0, paddedInput.length, additionalEntropy);
             }
         }
     }
@@ -207,6 +213,11 @@
 
         @Override
         protected final int getAdditionalEntropyAmountForBegin() {
+            return 0;
+        }
+
+        @Override
+        protected final int getAdditionalEntropyAmountForFinish() {
             return (isEncrypting()) ? getModulusSizeBytes() : 0;
         }
     }
@@ -361,6 +372,11 @@
 
         @Override
         protected final int getAdditionalEntropyAmountForBegin() {
+            return 0;
+        }
+
+        @Override
+        protected final int getAdditionalEntropyAmountForFinish() {
             return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
         }
     }
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
index 898336d..954b71a 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreRSASignatureSpi.java
@@ -36,7 +36,7 @@
         }
 
         @Override
-        protected final int getAdditionalEntropyAmountForBegin() {
+        protected final int getAdditionalEntropyAmountForSign() {
             // No entropy required for this deterministic signature scheme.
             return 0;
         }
@@ -92,8 +92,8 @@
         }
 
         @Override
-        protected final int getAdditionalEntropyAmountForBegin() {
-            return (isSigning()) ? SALT_LENGTH_BYTES : 0;
+        protected final int getAdditionalEntropyAmountForSign() {
+            return SALT_LENGTH_BYTES;
         }
     }
 
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
index f072ae7..5cdcc41 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSignatureSpiBase.java
@@ -198,15 +198,14 @@
 
         KeymasterArguments keymasterInputArgs = new KeymasterArguments();
         addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
-        byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
-                appRandom, getAdditionalEntropyAmountForBegin());
 
         OperationResult opResult = mKeyStore.begin(
                 mKey.getAlias(),
                 mSigning ? KeymasterDefs.KM_PURPOSE_SIGN : KeymasterDefs.KM_PURPOSE_VERIFY,
                 true, // permit aborting this operation if keystore runs out of resources
                 keymasterInputArgs,
-                additionalEntropy);
+                null // no additional entropy for begin -- only finish might need some
+                );
         if (opResult == null) {
             throw new KeyStoreConnectException();
         }
@@ -311,7 +310,11 @@
         byte[] signature;
         try {
             ensureKeystoreOperationInitialized();
-            signature = mMessageStreamer.doFinal(EmptyArray.BYTE, 0, 0);
+
+            byte[] additionalEntropy =
+                    KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(
+                            appRandom, getAdditionalEntropyAmountForSign());
+            signature = mMessageStreamer.doFinal(EmptyArray.BYTE, 0, 0, additionalEntropy);
         } catch (InvalidKeyException | KeyStoreException e) {
             throw new SignatureException(e);
         }
@@ -388,15 +391,14 @@
 
     /**
      * Returns the amount of additional entropy (in bytes) to be provided to the KeyStore's
-     * {@code begin} operation.
+     * {@code finish} operation when generating a signature.
      *
-     * <p>For signature verification, this should be {@code 0} because verification should not be
-     * consuming any entropy. For signature generation, this value should match (or exceed) the
-     * amount of Shannon entropy of the produced signature assuming the key and the message are
-     * known. For example, for ECDSA signature this should be the size of {@code R}, whereas for the
-     * RSA signature with PKCS#1 padding this should be {@code 0}.
+     * <p>This value should match (or exceed) the amount of Shannon entropy of the produced
+     * signature assuming the key and the message are known. For example, for ECDSA signature this
+     * should be the size of {@code R}, whereas for the RSA signature with PKCS#1 padding this
+     * should be {@code 0}.
      */
-    protected abstract int getAdditionalEntropyAmountForBegin();
+    protected abstract int getAdditionalEntropyAmountForSign();
 
     /**
      * Invoked to add algorithm-specific parameters for the KeyStore's {@code begin} operation.
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 831a106..3bd9d1d 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -247,14 +247,8 @@
             specBuilder =
                     new KeyProtection.Builder(
                             KeyProperties.PURPOSE_SIGN | KeyProperties.PURPOSE_VERIFY);
-            specBuilder.setDigests(
-                    KeyProperties.DIGEST_NONE,
-                    KeyProperties.DIGEST_MD5,
-                    KeyProperties.DIGEST_SHA1,
-                    KeyProperties.DIGEST_SHA224,
-                    KeyProperties.DIGEST_SHA256,
-                    KeyProperties.DIGEST_SHA384,
-                    KeyProperties.DIGEST_SHA512);
+            // Authorized to be used with any digest (including no digest).
+            specBuilder.setDigests(KeyProperties.DIGEST_NONE);
         } else if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(keyAlgorithm)) {
             specBuilder =
                     new KeyProtection.Builder(
@@ -262,19 +256,13 @@
                             | KeyProperties.PURPOSE_DECRYPT
                             | KeyProperties.PURPOSE_SIGN
                             | KeyProperties.PURPOSE_VERIFY);
-            specBuilder.setDigests(
-                    KeyProperties.DIGEST_NONE,
-                    KeyProperties.DIGEST_MD5,
-                    KeyProperties.DIGEST_SHA1,
-                    KeyProperties.DIGEST_SHA224,
-                    KeyProperties.DIGEST_SHA256,
-                    KeyProperties.DIGEST_SHA384,
-                    KeyProperties.DIGEST_SHA512);
+            // Authorized to be used with any digest (including no digest).
+            specBuilder.setDigests(KeyProperties.DIGEST_NONE);
             specBuilder.setSignaturePaddings(
                     KeyProperties.SIGNATURE_PADDING_RSA_PKCS1);
+            // Authorized to be used with any padding (including no padding).
             specBuilder.setEncryptionPaddings(
-                    KeyProperties.ENCRYPTION_PADDING_NONE,
-                    KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1);
+                    KeyProperties.ENCRYPTION_PADDING_NONE);
             // Disable randomized encryption requirement to support encryption padding NONE
             // above.
             specBuilder.setRandomizedEncryptionRequired(false);
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
index 47cd1d1..76804a9 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
@@ -210,6 +210,11 @@
     }
 
     @Override
+    protected final int getAdditionalEntropyAmountForFinish() {
+        return 0;
+    }
+
+    @Override
     protected final void addAlgorithmSpecificParametersToBegin(
             @NonNull KeymasterArguments keymasterArgs) {
         if ((isEncrypting()) && (mIvRequired) && (mIvHasBeenUsed)) {
diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
index 68c9c79..47aab74 100644
--- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java
+++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java
@@ -611,9 +611,14 @@
          *
          * <p>This must be specified for keys which are used for signing/verification. For HMAC
          * keys, the set of digests defaults to the digest associated with the key algorithm (e.g.,
-         * {@code SHA-256} for key algorithm {@code HmacSHA256}
+         * {@code SHA-256} for key algorithm {@code HmacSHA256}).
          *
-         * @see KeyProperties.Digest
+         * <p>For private keys used for TLS/SSL client or server authentication it is usually
+         * necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
+         * because TLS/SSL stacks typically generate the necessary digest(s) themselves and then use
+         * a private key to sign it.
+         *
+         * <p>See {@link KeyProperties}.{@code DIGEST} constants.
          */
         @NonNull
         public Builder setDigests(@KeyProperties.DigestEnum String... digests) {
@@ -629,6 +634,12 @@
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
          *
+         * <p>For RSA private keys used by TLS/SSL servers to authenticate themselves to clients it
+         * is usually necessary to authorize the use of no/any padding
+         * ({@link KeyProperties#ENCRYPTION_PADDING_NONE}). This is because RSA decryption is
+         * required by some cipher suites, and some stacks request decryption using no padding
+         * whereas others request PKCS#1 padding.
+         *
          * <p>See {@link KeyProperties}.{@code ENCRYPTION_PADDING} constants.
          */
         @NonNull
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java
index 5af4181..403e814 100644
--- a/keystore/java/android/security/keystore/KeyProperties.java
+++ b/keystore/java/android/security/keystore/KeyProperties.java
@@ -368,6 +368,9 @@
 
     /**
      * No encryption padding.
+     *
+     * <p><b>NOTE</b>: If a key is authorized to be used with no padding, then it can be used with
+     * any padding scheme.
      */
     public static final String ENCRYPTION_PADDING_NONE = "NoPadding";
 
@@ -514,6 +517,9 @@
 
     /**
      * No digest: sign/authenticate the raw message.
+     *
+     * <p><b>NOTE</b>: If a key is authorized to be used with no digest, then it can be used with
+     * any digest.
      */
     public static final String DIGEST_NONE = "NONE";
 
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 48c0ed0f..432fc12 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -374,6 +374,12 @@
          *
          * <p>This must be specified for keys which are used for encryption/decryption.
          *
+         * <p>For RSA private keys used by TLS/SSL servers to authenticate themselves to clients it
+         * is usually necessary to authorize the use of no/any padding
+         * ({@link KeyProperties#ENCRYPTION_PADDING_NONE}). This is because RSA decryption is
+         * required by some cipher suites, and some stacks request decryption using no padding
+         * whereas others request PKCS#1 padding.
+         *
          * <p>See {@link KeyProperties}.{@code ENCRYPTION_PADDING} constants.
          */
         @NonNull
@@ -408,6 +414,11 @@
          * {@link Key#getAlgorithm()}. For asymmetric signing keys the set of digest algorithms
          * must be specified.
          *
+         * <p>For private keys used for TLS/SSL client or server authentication it is usually
+         * necessary to authorize the use of no digest ({@link KeyProperties#DIGEST_NONE}). This is
+         * because TLS/SSL stacks typically generate the necessary digest(s) themselves and then use
+         * a private key to sign it.
+         *
          * <p>See {@link KeyProperties}.{@code DIGEST} constants.
          */
         @NonNull
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
index 47b4996..9957e79 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationChunkedStreamer.java
@@ -35,8 +35,8 @@
  * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
  * operation may consume less data than provided, in which case the caller has to buffer the
  * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
- * {@link #doFinal(byte[], int, int) doFinal} operations which can be used to conveniently implement
- * various JCA crypto primitives.
+ * {@link #doFinal(byte[], int, int, byte[]) doFinal} operations which can be used to conveniently
+ * implement various JCA crypto primitives.
  *
  * <p>Bidirectional chunked streaming of data via a KeyStore crypto operation is abstracted away as
  * a {@link Stream} to avoid having this class deal with operation tokens and occasional additional
@@ -60,7 +60,7 @@
          * Returns the result of the KeyStore {@code finish} operation or null if keystore couldn't
          * be reached.
          */
-        OperationResult finish();
+        OperationResult finish(byte[] additionalEntropy);
     }
 
     // Binder buffer is about 1MB, but it's shared between all active transactions of the process.
@@ -192,7 +192,7 @@
     }
 
     @Override
-    public byte[] doFinal(byte[] input, int inputOffset, int inputLength)
+    public byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] additionalEntropy)
             throws KeyStoreException {
         if (inputLength == 0) {
             // No input provided -- simplify the rest of the code
@@ -204,7 +204,7 @@
         byte[] output = update(input, inputOffset, inputLength);
         output = ArrayUtils.concat(output, flush());
 
-        OperationResult opResult = mKeyStoreStream.finish();
+        OperationResult opResult = mKeyStoreStream.finish(additionalEntropy);
         if (opResult == null) {
             throw new KeyStoreConnectException();
         } else if (opResult.resultCode != KeyStore.NO_ERROR) {
@@ -268,8 +268,8 @@
         }
 
         @Override
-        public OperationResult finish() {
-            return mKeyStore.finish(mOperationToken, null, null);
+        public OperationResult finish(byte[] additionalEntropy) {
+            return mKeyStore.finish(mOperationToken, null, null, additionalEntropy);
         }
     }
 }
diff --git a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
index 2fb8f20..1c6de2d 100644
--- a/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
+++ b/keystore/java/android/security/keystore/KeyStoreCryptoOperationStreamer.java
@@ -28,12 +28,13 @@
  * amount of data in one go because the operations are marshalled via Binder. Secondly, the update
  * operation may consume less data than provided, in which case the caller has to buffer the
  * remainder for next time. The helper exposes {@link #update(byte[], int, int) update} and
- * {@link #doFinal(byte[], int, int) doFinal} operations which can be used to conveniently implement
- * various JCA crypto primitives.
+ * {@link #doFinal(byte[], int, int, byte[]) doFinal} operations which can be used to conveniently
+ * implement various JCA crypto primitives.
  *
  * @hide
  */
 interface KeyStoreCryptoOperationStreamer {
     byte[] update(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
-    byte[] doFinal(byte[] input, int inputOffset, int inputLength) throws KeyStoreException;
+    byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] additionalEntropy)
+            throws KeyStoreException;
 }
diff --git a/libs/hwui/DeferredDisplayList.cpp b/libs/hwui/DeferredDisplayList.cpp
index b077a85..f05857c 100644
--- a/libs/hwui/DeferredDisplayList.cpp
+++ b/libs/hwui/DeferredDisplayList.cpp
@@ -494,7 +494,9 @@
     // complex clip has a complex set of expectations on the renderer state - for now, avoid taking
     // the merge path in those cases
     deferInfo.mergeable &= !recordingComplexClip();
-    deferInfo.opaqueOverBounds &= !recordingComplexClip() && mSaveStack.isEmpty();
+    deferInfo.opaqueOverBounds &= !recordingComplexClip()
+            && mSaveStack.isEmpty()
+            && !state->mRoundRectClipState;
 
     if (CC_LIKELY(mAvoidOverdraw) && mBatches.size() &&
             state->mClipSideFlags != kClipSide_ConservativeFull &&
diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp
index b7cdaa2..288fed3 100644
--- a/libs/hwui/GlopBuilder.cpp
+++ b/libs/hwui/GlopBuilder.cpp
@@ -29,8 +29,9 @@
 #include <GLES2/gl2.h>
 #include <SkPaint.h>
 
-namespace android {
-namespace uirenderer {
+#define DEBUG_GLOP_BUILDER 0
+
+#if DEBUG_GLOP_BUILDER
 
 #define TRIGGER_STAGE(stageFlag) \
     LOG_ALWAYS_FATAL_IF((stageFlag) & mStageFlags, "Stage %d cannot be run twice", (stageFlag)); \
@@ -40,6 +41,16 @@
     LOG_ALWAYS_FATAL_IF((mStageFlags & (requiredFlags)) != (requiredFlags), \
             "not prepared for current stage")
 
+#else
+
+#define TRIGGER_STAGE(stageFlag) ((void)0)
+#define REQUIRE_STAGES(requiredFlags) ((void)0)
+
+#endif
+
+namespace android {
+namespace uirenderer {
+
 static void setUnitQuadTextureCoords(Rect uvs, TextureVertex* quadVertex) {
     quadVertex[0] = {0, 0, uvs.left, uvs.top};
     quadVertex[1] = {1, 0, uvs.right, uvs.top};
@@ -301,7 +312,7 @@
 GlopBuilder& GlopBuilder::setFillTexturePaint(Texture& texture,
         const int textureFillFlags, const SkPaint* paint, float alphaScale) {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     GLenum filter = (textureFillFlags & TextureFillFlags::ForceFilter)
             ? GL_LINEAR : PaintUtils::getFilter(paint);
@@ -345,7 +356,7 @@
 
 GlopBuilder& GlopBuilder::setFillPaint(const SkPaint& paint, float alphaScale) {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
 
@@ -359,7 +370,7 @@
 GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture,
         const SkPaint& paint, float alphaScale) {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     //specify invalid filter/clamp, since these are always static for PathTextures
     mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
@@ -376,7 +387,7 @@
 GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor,
         const SkPaint& paint, float alphaScale) {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     //specify invalid filter/clamp, since these are always static for ShadowTextures
     mOutGlop->fill.texture = { &texture, GL_TEXTURE_2D, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
@@ -399,7 +410,7 @@
 
 GlopBuilder& GlopBuilder::setFillBlack() {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
     setFill(SK_ColorBLACK, 1.0f, SkXfermode::kSrcOver_Mode, Blend::ModeOrderSwap::NoSwap,
@@ -409,7 +420,7 @@
 
 GlopBuilder& GlopBuilder::setFillClear() {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { nullptr, GL_INVALID_ENUM, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr };
     setFill(SK_ColorBLACK, 1.0f, SkXfermode::kClear_Mode, Blend::ModeOrderSwap::NoSwap,
@@ -420,7 +431,7 @@
 GlopBuilder& GlopBuilder::setFillLayer(Texture& texture, const SkColorFilter* colorFilter,
         float alpha, SkXfermode::Mode mode, Blend::ModeOrderSwap modeUsage) {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { &texture,
             GL_TEXTURE_2D, GL_LINEAR, GL_CLAMP_TO_EDGE, nullptr };
@@ -434,7 +445,7 @@
 
 GlopBuilder& GlopBuilder::setFillTextureLayer(Layer& layer, float alpha) {
     TRIGGER_STAGE(kFillStage);
-    REQUIRE_STAGES(kMeshStage);
+    REQUIRE_STAGES(kMeshStage | kRoundRectClipStage);
 
     mOutGlop->fill.texture = { &(layer.getTexture()),
             layer.getRenderTarget(), GL_LINEAR, GL_CLAMP_TO_EDGE, &layer.getTexTransform() };
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index 5769376..433e178 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -847,11 +847,11 @@
             && layer->getHeight() == (uint32_t) rect.getHeight();
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedUvQuad(nullptr, Rect(0, 1, 1, 0)) // TODO: simplify with VBO
             .setFillTextureLayer(*layer, getLayerAlpha(layer))
             .setTransform(*currentSnapshot(), TransformFlags::None)
             .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -859,12 +859,12 @@
 void OpenGLRenderer::composeLayerRectSwapped(Layer* layer, const Rect& rect) {
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedUvQuad(nullptr, layer->texCoords)
             .setFillLayer(layer->getTexture(), layer->getColorFilter(),
                     getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::Swap)
             .setTransform(*currentSnapshot(), TransformFlags::MeshIgnoresCanvasTransform)
             .setModelViewMapUnitToRect(rect)
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -880,11 +880,11 @@
                 && layer->getHeight() == static_cast<uint32_t>(rect.getHeight());
         Glop glop;
         GlopBuilder(mRenderState, mCaches, &glop)
+                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                 .setMeshTexturedUvQuad(nullptr, layer->texCoords)
                 .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
                 .setTransform(*currentSnapshot(), TransformFlags::None)
                 .setModelViewMapUnitToRectOptionalSnap(tryToSnap, rect)
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                 .build();
         renderGlop(glop);
     }
@@ -1021,11 +1021,11 @@
     Rect modelRect = Rect(rect.getWidth(), rect.getHeight());
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedIndexedQuads(&quadVertices[0], count * 6)
             .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewOffsetRectSnap(rect.left, rect.top, modelRect)
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 
@@ -1140,11 +1140,11 @@
         const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
         Glop glop;
         GlopBuilder(mRenderState, mCaches, &glop)
+                .setRoundRectClipState(nullptr) // clear ignores clip state
                 .setMeshIndexedQuads(&mesh[0], quadCount)
                 .setFillClear()
                 .setTransform(*currentSnapshot(), transformFlags)
                 .setModelViewOffsetRect(0, 0, Rect(currentSnapshot()->getClipRect()))
-                .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                 .build();
         renderGlop(glop, false);
 
@@ -1330,11 +1330,11 @@
     Glop glop;
     Vertex* vertices = &rectangleVertices[0];
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshIndexedQuads(vertices, rectangleVertices.size() / 4)
             .setFillBlack()
             .setTransform(*currentSnapshot(), transformFlags)
             .setModelViewOffsetRect(0, 0, scissorBox)
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1534,11 +1534,11 @@
     const int transformFlags = TransformFlags::MeshIgnoresCanvasTransform;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedMesh(vertices, bitmapCount * 6)
             .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(), transformFlags)
             .setModelViewOffsetRectOptionalSnap(snap, x, y, Rect(0, 0, bounds.getWidth(), bounds.getHeight()))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1557,11 +1557,11 @@
             ? TextureFillFlags::IsAlphaMaskTexture : TextureFillFlags::None;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedUnitQuad(texture->uvMapper)
             .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewMapUnitToRectSnap(Rect(0, 0, texture->width, texture->height))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1647,11 +1647,11 @@
     const int textureFillFlags = TextureFillFlags::None;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshColoredTexturedMesh(mesh.get(), elementCount)
             .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1676,11 +1676,11 @@
             && MathUtils::areEqual(src.getHeight(), dst.getHeight());
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedUvQuad(texture->uvMapper, uv)
             .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewMapUnitToRectOptionalSnap(tryToSnap, dst)
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1702,11 +1702,11 @@
     }
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshPatchQuads(*mesh)
             .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewOffsetRectSnap(left, top, Rect(0, 0, right - left, bottom - top)) // TODO: get minimal bounds from patch
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1732,11 +1732,11 @@
     }
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedIndexedQuads(vertices, elementCount)
             .setFillTexturePaint(*texture, textureFillFlags, paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(), transformFlags)
             .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -1753,11 +1753,11 @@
     const int transformFlags = TransformFlags::OffsetByFudgeFactor;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshVertexBuffer(vertexBuffer, shadowInterp)
             .setFillPaint(*paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(), transformFlags)
             .setModelViewOffsetRect(translateX, translateY, vertexBuffer.getBounds())
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -2039,11 +2039,11 @@
 
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedUnitQuad(nullptr)
             .setFillShadowTexturePaint(*texture, textShadow.color, *paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width, sy + texture->height))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -2364,11 +2364,11 @@
         } else if (layer->mesh) {
             Glop glop;
             GlopBuilder(mRenderState, mCaches, &glop)
+                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                     .setMeshTexturedIndexedQuads(layer->mesh, layer->meshElementCount)
                     .setFillLayer(layer->getTexture(), layer->getColorFilter(), getLayerAlpha(layer), layer->getMode(), Blend::ModeOrderSwap::NoSwap)
                     .setTransform(*currentSnapshot(),  TransformFlags::None)
                     .setModelViewOffsetRectSnap(x, y, Rect(0, 0, layer->layer.getWidth(), layer->layer.getHeight()))
-                    .setRoundRectClipState(currentSnapshot()->roundRectClipState)
                     .build();
             DRAW_DOUBLE_STENCIL_IF(!layer->hasDrawnSinceUpdate, renderGlop(glop));
 #if DEBUG_LAYERS_AS_REGIONS
@@ -2422,11 +2422,11 @@
 
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshTexturedUnitQuad(nullptr)
             .setFillPathTexturePaint(*texture, *paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(),  TransformFlags::None)
             .setModelViewMapUnitToRect(Rect(x, y, x + texture->width, y + texture->height))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -2560,11 +2560,11 @@
             ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshIndexedQuads(&mesh[0], count / 4)
             .setFillPaint(*paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(), transformFlags)
             .setModelViewOffsetRect(0, 0, Rect(left, top, right, bottom))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
@@ -2575,11 +2575,11 @@
             ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None;
     Glop glop;
     GlopBuilder(mRenderState, mCaches, &glop)
+            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .setMeshUnitQuad()
             .setFillPaint(*paint, currentSnapshot()->alpha)
             .setTransform(*currentSnapshot(), transformFlags)
             .setModelViewMapUnitToRect(Rect(left, top, right, bottom))
-            .setRoundRectClipState(currentSnapshot()->roundRectClipState)
             .build();
     renderGlop(glop);
 }
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 4ac4362..75e700a 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -392,11 +392,27 @@
         if (isLayer) {
             clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
         }
-        LOG_ALWAYS_FATAL_IF(!isLayer && properties().getHasOverlappingRendering());
-        renderer.scaleAlpha(properties().getAlpha());
+        if (CC_LIKELY(isLayer || !properties().getHasOverlappingRendering())) {
+            // simply scale rendering content's alpha
+            renderer.scaleAlpha(properties().getAlpha());
+        } else {
+            // savelayer needed to create an offscreen buffer
+            Rect layerBounds(0, 0, getWidth(), getHeight());
+            if (clipFlags) {
+                properties().getClippingRectForFlags(clipFlags, &layerBounds);
+                clipFlags = 0; // all clipping done by savelayer
+            }
+            SaveLayerOp* op = new (handler.allocator()) SaveLayerOp(
+                    layerBounds.left, layerBounds.top,
+                    layerBounds.right, layerBounds.bottom,
+                    (int) (properties().getAlpha() * 255),
+                    SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kClipToLayer_SaveFlag);
+            handler(op, PROPERTY_SAVECOUNT, properties().getClipToBounds());
+        }
 
         if (CC_UNLIKELY(ATRACE_ENABLED() && properties().promotedToLayer())) {
-            // pretend to cause savelayer to warn about performance problem affecting old versions
+            // pretend alpha always causes savelayer to warn about
+            // performance problem affecting old versions
             ATRACE_FORMAT("%s alpha caused saveLayer %dx%d", getName(),
                     static_cast<int>(getWidth()),
                     static_cast<int>(getHeight()));
diff --git a/libs/hwui/RenderProperties.cpp b/libs/hwui/RenderProperties.cpp
index 07b8ce6..4f6ef4e 100644
--- a/libs/hwui/RenderProperties.cpp
+++ b/libs/hwui/RenderProperties.cpp
@@ -152,7 +152,24 @@
             clipFlags &= ~CLIP_TO_BOUNDS; // bounds clipping done by layer
         }
 
-        ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha);
+        if (CC_LIKELY(isLayer || !getHasOverlappingRendering())) {
+            // simply scale rendering content's alpha
+            ALOGD("%*sScaleAlpha %.2f", level * 2, "", mPrimitiveFields.mAlpha);
+        } else {
+            // savelayeralpha to create an offscreen buffer to apply alpha
+            Rect layerBounds(0, 0, getWidth(), getHeight());
+            if (clipFlags) {
+                getClippingRectForFlags(clipFlags, &layerBounds);
+                clipFlags = 0; // all clipping done by savelayer
+            }
+            ALOGD("%*sSaveLayerAlpha %d, %d, %d, %d, %d, 0x%x", level * 2, "",
+                    (int)layerBounds.left, (int)layerBounds.top,
+                    (int)layerBounds.right, (int)layerBounds.bottom,
+                    (int)(mPrimitiveFields.mAlpha * 255),
+                    SkCanvas::kHasAlphaLayer_SaveFlag | SkCanvas::kClipToLayer_SaveFlag);
+        }
+
+
     }
     if (clipFlags) {
         Rect clipRect;
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 98029a8..65c1c4a 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -28,6 +28,7 @@
 #include <SkRegion.h>
 #include <SkXfermode.h>
 
+#include "Caches.h"
 #include "Rect.h"
 #include "RevealClip.h"
 #include "Outline.h"
@@ -577,10 +578,13 @@
     }
 
     bool promotedToLayer() const {
+        const int maxTextureSize = Caches::getInstance().maxTextureSize;
         return mLayerProperties.mType == LayerType::None
                 && !MathUtils::isZero(mPrimitiveFields.mAlpha)
                 && mPrimitiveFields.mAlpha < 1
-                && mPrimitiveFields.mHasOverlappingRendering;
+                && mPrimitiveFields.mHasOverlappingRendering
+                && mPrimitiveFields.mWidth <= maxTextureSize
+                && mPrimitiveFields.mHeight <= maxTextureSize;
     }
 
     LayerType effectiveLayerType() const {
diff --git a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
index 95b3eb3..260f380 100644
--- a/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
+++ b/location/java/com/android/internal/location/GpsNetInitiatedHandler.java
@@ -172,7 +172,7 @@
      * <p>
      * This is lazily created, so use {@link #setNINotification()}.
      */
-    private Notification mNiNotification;
+    private Notification.Builder mNiNotificationBuilder;
 
     public GpsNetInitiatedHandler(Context context,
                                   INetInitiatedListener netInitiatedListener,
@@ -367,29 +367,31 @@
                 ", message: " + message);
 
         // Construct Notification
-        if (mNiNotification == null) {
-            mNiNotification = new Notification();
-            mNiNotification.icon = com.android.internal.R.drawable.stat_sys_gps_on; /* Change notification icon here */
-            mNiNotification.when = 0;
+        if (mNiNotificationBuilder == null) {
+            mNiNotificationBuilder = new Notification.Builder(mContext)
+                    .setSmallIcon(com.android.internal.R.drawable.stat_sys_gps_on)
+                    .setWhen(0)
+                    .setOngoing(true)
+                    .setAutoCancel(true)
+                    .setColor(mContext.getColor(
+                            com.android.internal.R.color.system_notification_accent_color));
         }
 
         if (mPlaySounds) {
-            mNiNotification.defaults |= Notification.DEFAULT_SOUND;
+            mNiNotificationBuilder.setDefaults(Notification.DEFAULT_SOUND);
         } else {
-            mNiNotification.defaults &= ~Notification.DEFAULT_SOUND;
+            mNiNotificationBuilder.setDefaults(0);
         }
 
-        mNiNotification.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_AUTO_CANCEL;
-        mNiNotification.tickerText = getNotifTicker(notif, mContext);
-
         // if not to popup dialog immediately, pending intent will open the dialog
         Intent intent = !mPopupImmediately ? getDlgIntent(notif) : new Intent();
         PendingIntent pi = PendingIntent.getBroadcast(mContext, 0, intent, 0);
-        mNiNotification.color = mContext.getColor(
-                com.android.internal.R.color.system_notification_accent_color);
-        mNiNotification.setLatestEventInfo(mContext, title, message, pi);
+        mNiNotificationBuilder.setTicker(getNotifTicker(notif, mContext))
+                .setContentTitle(title)
+                .setContentText(message)
+                .setContentIntent(pi);
 
-        notificationManager.notifyAsUser(null, notif.notificationId, mNiNotification,
+        notificationManager.notifyAsUser(null, notif.notificationId, mNiNotificationBuilder.build(),
                 UserHandle.ALL);
     }
 
diff --git a/media/java/android/media/midi/IMidiDeviceServer.aidl b/media/java/android/media/midi/IMidiDeviceServer.aidl
index e30796d..c2cc2b9 100644
--- a/media/java/android/media/midi/IMidiDeviceServer.aidl
+++ b/media/java/android/media/midi/IMidiDeviceServer.aidl
@@ -31,4 +31,5 @@
     void connectPorts(IBinder token, in ParcelFileDescriptor pfd, int outputPortNumber);
 
     MidiDeviceInfo getDeviceInfo();
+    void setDeviceInfo(in MidiDeviceInfo deviceInfo);
 }
diff --git a/media/java/android/media/midi/MidiDeviceServer.java b/media/java/android/media/midi/MidiDeviceServer.java
index 1b56e1c..1212b64 100644
--- a/media/java/android/media/midi/MidiDeviceServer.java
+++ b/media/java/android/media/midi/MidiDeviceServer.java
@@ -269,8 +269,20 @@
         public MidiDeviceInfo getDeviceInfo() {
             return mDeviceInfo;
         }
+
+        @Override
+        public void setDeviceInfo(MidiDeviceInfo deviceInfo) {
+            if (Binder.getCallingUid() != Process.SYSTEM_UID) {
+                throw new SecurityException("setDeviceInfo should only be called by MidiService");
+            }
+            if (mDeviceInfo != null) {
+                throw new IllegalStateException("setDeviceInfo should only be called once");
+            }
+            mDeviceInfo = deviceInfo;
+        }
     };
 
+    // Constructor for MidiManager.createDeviceServer()
     /* package */ MidiDeviceServer(IMidiManager midiManager, MidiReceiver[] inputPortReceivers,
             int numOutputPorts, Callback callback) {
         mMidiManager = midiManager;
@@ -292,6 +304,13 @@
         mGuard.open("close");
     }
 
+    // Constructor for MidiDeviceService.onCreate()
+    /* package */ MidiDeviceServer(IMidiManager midiManager, MidiReceiver[] inputPortReceivers,
+           MidiDeviceInfo deviceInfo, Callback callback) {
+        this(midiManager, inputPortReceivers, deviceInfo.getOutputPortCount(), callback);
+        mDeviceInfo = deviceInfo;
+    }
+
     /* package */ IMidiDeviceServer getBinderInterface() {
         return mServer;
     }
@@ -300,13 +319,6 @@
         return mServer.asBinder();
     }
 
-    /* package */ void setDeviceInfo(MidiDeviceInfo deviceInfo) {
-        if (mDeviceInfo != null) {
-            throw new IllegalStateException("setDeviceInfo should only be called once");
-        }
-        mDeviceInfo = deviceInfo;
-    }
-
     private void updateDeviceStatus() {
         // clear calling identity, since we may be in a Binder call from one of our clients
         long identityToken = Binder.clearCallingIdentity();
diff --git a/media/java/android/media/midi/MidiDeviceService.java b/media/java/android/media/midi/MidiDeviceService.java
index d897ad2..388d95b 100644
--- a/media/java/android/media/midi/MidiDeviceService.java
+++ b/media/java/android/media/midi/MidiDeviceService.java
@@ -83,9 +83,7 @@
             if (inputPortReceivers == null) {
                 inputPortReceivers = new MidiReceiver[0];
             }
-            server = new MidiDeviceServer(mMidiManager, inputPortReceivers,
-                    deviceInfo.getOutputPortCount(), mCallback);
-            server.setDeviceInfo(deviceInfo);
+            server = new MidiDeviceServer(mMidiManager, inputPortReceivers, deviceInfo, mCallback);
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in IMidiManager.getServiceDeviceInfo");
             server = null;
diff --git a/media/java/android/media/midi/MidiManager.java b/media/java/android/media/midi/MidiManager.java
index 0beb9a4..89230fe 100644
--- a/media/java/android/media/midi/MidiManager.java
+++ b/media/java/android/media/midi/MidiManager.java
@@ -318,7 +318,6 @@
                 Log.e(TAG, "registerVirtualDevice failed");
                 return null;
             }
-            server.setDeviceInfo(deviceInfo);
             return server;
         } catch (RemoteException e) {
             Log.e(TAG, "RemoteException in createVirtualDevice");
diff --git a/media/java/android/media/tv/TvInputService.java b/media/java/android/media/tv/TvInputService.java
index 50a215c..f52ccc9 100644
--- a/media/java/android/media/tv/TvInputService.java
+++ b/media/java/android/media/tv/TvInputService.java
@@ -434,9 +434,12 @@
         }
 
         /**
-         * Informs the application that the video is now available for watching. This is primarily
-         * used to signal the application to unblock the screen. The TV input service must call this
-         * method as soon as the content rendered onto its surface gets ready for viewing.
+         * Informs the application that the video is now available for watching. Video is blocked
+         * until this method is called.
+         *
+         * <p>The TV input service must call this method as soon as the content rendered onto its
+         * surface is ready for viewing. This method must be called each time {@link #onTune(Uri)}
+         * is called.
          *
          * @see #notifyVideoUnavailable
          */
@@ -761,9 +764,11 @@
         public abstract void onSetStreamVolume(float volume);
 
         /**
-         * Tunes to a given channel. When the video is available, {@link #notifyVideoAvailable()}
-         * should be called. Also, {@link #notifyVideoUnavailable(int)} should be called when the TV
-         * input cannot continue playing the given channel.
+         * Tunes to a given channel.
+         *
+         * <p>No video will be displayed until {@link #notifyVideoAvailable()} is called.
+         * Also, {@link #notifyVideoUnavailable(int)} should be called when the TV input cannot
+         * continue playing the given channel.
          *
          * @param channelUri The URI of the channel.
          * @return {@code true} if the tuning was successful, {@code false} otherwise.
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 742f570..26ece72 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -47,6 +47,7 @@
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.SparseBooleanArray;
+import android.util.SparseLongArray;
 import android.util.TimeUtils;
 
 import java.io.ByteArrayOutputStream;
@@ -84,6 +85,12 @@
     // Minimum alarm recurrence interval
     private static final long MIN_INTERVAL = 60 * 1000;  // one minute, in millis
 
+    // Minimum time between ALLOW_WHILE_IDLE alarms when system is not idle.
+    private static final long ALLOW_WHILE_IDLE_SHORT_TIME = 60*1000;
+
+    // Minimum time between ALLOW_WHILE_IDLE alarms when system is idling.
+    private static final long ALLOW_WHILE_IDLE_LONG_TIME = 15*60*1000;
+
     private static final int RTC_WAKEUP_MASK = 1 << RTC_WAKEUP;
     private static final int RTC_MASK = 1 << RTC;
     private static final int ELAPSED_REALTIME_WAKEUP_MASK = 1 << ELAPSED_REALTIME_WAKEUP;
@@ -123,8 +130,8 @@
     int mBroadcastRefCount = 0;
     PowerManager.WakeLock mWakeLock;
     boolean mLastWakeLockUnimportantForLogging;
-    ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<Alarm>();
-    ArrayList<InFlight> mInFlight = new ArrayList<InFlight>();
+    ArrayList<Alarm> mPendingNonWakeupAlarms = new ArrayList<>();
+    ArrayList<InFlight> mInFlight = new ArrayList<>();
     final AlarmHandler mHandler = new AlarmHandler();
     ClockReceiver mClockReceiver;
     InteractiveStateReceiver mInteractiveStateReceiver;
@@ -141,8 +148,15 @@
     long mNextNonWakeupDeliveryTime;
     long mLastTimeChangeClockTime;
     long mLastTimeChangeRealtime;
+    long mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_SHORT_TIME;
     int mNumTimeChanged;
 
+    /**
+     * For each uid, this is the last time we dispatched an "allow while idle" alarm,
+     * used to determine the earliest we can dispatch the next such alarm.
+     */
+    final SparseLongArray mLastAllowWhileIdleDispatch = new SparseLongArray();
+
     private final SparseArray<AlarmManager.AlarmClockInfo> mNextAlarmClockForUser =
             new SparseArray<>();
     private final SparseArray<AlarmManager.AlarmClockInfo> mTmpSparseAlarmClockArray =
@@ -552,7 +566,7 @@
         a.when = a.origWhen;
         long whenElapsed = convertToElapsed(a.when, a.type);
         final long maxElapsed;
-        if (a.whenElapsed == a.maxWhenElapsed) {
+        if (a.windowLength == AlarmManager.WINDOW_EXACT) {
             // Exact
             maxElapsed = whenElapsed;
         } else {
@@ -580,6 +594,9 @@
             }
         }
 
+        // Make sure we are using the correct ALLOW_WHILE_IDLE min time.
+        mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_SHORT_TIME;
+
         // Reschedule everything.
         rescheduleKernelAlarmsLocked();
         updateNextAlarmClockLocked();
@@ -632,7 +649,7 @@
             mTag = tag;
         }
     }
-    
+
     static final class BroadcastStats {
         final int mUid;
         final String mPackageName;
@@ -649,7 +666,7 @@
             mPackageName = packageName;
         }
     }
-    
+
     final SparseArray<ArrayMap<String, BroadcastStats>> mBroadcastStats
             = new SparseArray<ArrayMap<String, BroadcastStats>>();
 
@@ -751,7 +768,7 @@
 
     void setImpl(int type, long triggerAtTime, long windowLength, long interval,
             PendingIntent operation, int flags, WorkSource workSource,
-            AlarmManager.AlarmClockInfo alarmClock) {
+            AlarmManager.AlarmClockInfo alarmClock, int callingUid) {
         if (operation == null) {
             Slog.w(TAG, "set/setRepeating ignored because there is no intent");
             return;
@@ -779,9 +796,8 @@
         }
 
         if (triggerAtTime < 0) {
-            final long who = Binder.getCallingUid();
             final long what = Binder.getCallingPid();
-            Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + who
+            Slog.w(TAG, "Invalid alarm trigger time! " + triggerAtTime + " from uid=" + callingUid
                     + " pid=" + what);
             triggerAtTime = 0;
         }
@@ -797,12 +813,12 @@
             maxElapsed = triggerElapsed;
         } else if (windowLength < 0) {
             maxElapsed = maxTriggerTime(nowElapsed, triggerElapsed, interval);
+            // Fix this window in place, so that as time approaches we don't collapse it.
+            windowLength = maxElapsed - triggerElapsed;
         } else {
             maxElapsed = triggerElapsed + windowLength;
         }
 
-        final int userId = UserHandle.getCallingUserId();
-
         synchronized (mLock) {
             if (DEBUG_BATCH) {
                 Slog.v(TAG, "set(" + operation + ") : type=" + type
@@ -811,26 +827,20 @@
                         + " interval=" + interval + " flags=0x" + Integer.toHexString(flags));
             }
             setImplLocked(type, triggerAtTime, triggerElapsed, windowLength, maxElapsed,
-                    interval, operation, flags, true, workSource, alarmClock, userId);
+                    interval, operation, flags, true, workSource, alarmClock, callingUid);
         }
     }
 
     private void setImplLocked(int type, long when, long whenElapsed, long windowLength,
             long maxWhen, long interval, PendingIntent operation, int flags,
             boolean doValidate, WorkSource workSource, AlarmManager.AlarmClockInfo alarmClock,
-            int userId) {
+            int uid) {
         Alarm a = new Alarm(type, when, whenElapsed, windowLength, maxWhen, interval,
-                operation, workSource, flags, alarmClock, userId);
+                operation, workSource, flags, alarmClock, uid);
         removeLocked(operation);
         setImplLocked(a, false, doValidate);
     }
 
-    private void updateNextWakeFromIdleFuzzLocked() {
-        if (mNextWakeFromIdle != null) {
-
-        }
-    }
-
     private void setImplLocked(Alarm a, boolean rebatching, boolean doValidate) {
         if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
             // This is a special alarm that will put the system into idle until it goes off.
@@ -862,7 +872,9 @@
         } else if (mPendingIdleUntil != null) {
             // We currently have an idle until alarm scheduled; if the new alarm has
             // not explicitly stated it wants to run while idle, then put it on hold.
-            if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE|AlarmManager.FLAG_WAKE_FROM_IDLE))
+            if ((a.flags&(AlarmManager.FLAG_ALLOW_WHILE_IDLE
+                    | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED
+                    | AlarmManager.FLAG_WAKE_FROM_IDLE))
                     == 0) {
                 mPendingWhileIdleAlarms.add(a);
                 return;
@@ -892,6 +904,7 @@
 
         if ((a.flags&AlarmManager.FLAG_IDLE_UNTIL) != 0) {
             mPendingIdleUntil = a;
+            mAllowWhileIdleMinTime = ALLOW_WHILE_IDLE_LONG_TIME;
             needRebatch = true;
         } else if ((a.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
             if (mNextWakeFromIdle == null || mNextWakeFromIdle.whenElapsed > a.whenElapsed) {
@@ -933,23 +946,45 @@
         public void set(int type, long triggerAtTime, long windowLength, long interval, int flags,
                 PendingIntent operation, WorkSource workSource,
                 AlarmManager.AlarmClockInfo alarmClock) {
+            final int callingUid = Binder.getCallingUid();
             if (workSource != null) {
-                getContext().enforceCallingPermission(
+                getContext().enforcePermission(
                         android.Manifest.permission.UPDATE_DEVICE_STATS,
-                        "AlarmManager.set");
+                        Binder.getCallingPid(), callingUid, "AlarmManager.set");
             }
 
+            // No incoming callers can request either WAKE_FROM_IDLE or
+            // ALLOW_WHILE_IDLE_UNRESTRICTED -- we will apply those later as appropriate.
+            flags &= ~(AlarmManager.FLAG_WAKE_FROM_IDLE
+                    | AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED);
+
+            // Only the system can use FLAG_IDLE_UNTIL -- this is used to tell the alarm
+            // manager when to come out of idle mode, which is only for DeviceIdleController.
+            if (callingUid != Process.SYSTEM_UID) {
+                flags &= ~AlarmManager.FLAG_IDLE_UNTIL;
+            }
+
+            // If the caller is a core system component, and not calling to do work on behalf
+            // of someone else, then always set ALLOW_WHILE_IDLE_UNRESTRICTED.  This means we
+            // will allow these alarms to go off as normal even while idle, with no timing
+            // restrictions.
+            if (callingUid < Process.FIRST_APPLICATION_UID && workSource == null) {
+                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE_UNRESTRICTED;
+            }
+
+            // If this is an exact time alarm, then it can't be batched with other alarms.
             if (windowLength == AlarmManager.WINDOW_EXACT) {
                 flags |= AlarmManager.FLAG_STANDALONE;
             }
+
+            // If this alarm is for an alarm clock, then it must be standalone and we will
+            // use it to wake early from idle if needed.
             if (alarmClock != null) {
                 flags |= AlarmManager.FLAG_WAKE_FROM_IDLE | AlarmManager.FLAG_STANDALONE;
             }
-            if (Binder.getCallingUid() < Process.FIRST_APPLICATION_UID) {
-                flags |= AlarmManager.FLAG_ALLOW_WHILE_IDLE;
-            }
+
             setImpl(type, triggerAtTime, windowLength, interval, operation,
-                    flags, workSource, alarmClock);
+                    flags, workSource, alarmClock, callingUid);
         }
 
         @Override
@@ -1126,6 +1161,22 @@
             pw.print("  Broadcast ref count: "); pw.println(mBroadcastRefCount);
             pw.println();
 
+            pw.print("mAllowWhileIdleMinTime=");
+            TimeUtils.formatDuration(mAllowWhileIdleMinTime, pw);
+            pw.println();
+            if (mLastAllowWhileIdleDispatch.size() > 0) {
+                pw.println("Last allow while idle dispatch times:");
+                for (int i=0; i<mLastAllowWhileIdleDispatch.size(); i++) {
+                    pw.print("  UID ");
+                    UserHandle.formatUid(pw, mLastAllowWhileIdleDispatch.keyAt(i));
+                    pw.print(": ");
+                    TimeUtils.formatDuration(mLastAllowWhileIdleDispatch.valueAt(i),
+                            nowELAPSED, pw);
+                    pw.println();
+                }
+            }
+            pw.println();
+
             if (mLog.dump(pw, "  Recent problems", "    ")) {
                 pw.println();
             }
@@ -1322,7 +1373,7 @@
             for (int j = 0; j < M; j++) {
                 Alarm a = alarms.get(j);
                 if (a.alarmClock != null) {
-                    final int userId = a.userId;
+                    final int userId = UserHandle.getUserId(a.uid);
 
                     if (DEBUG_ALARM_CLOCK) {
                         Log.v(TAG, "Found AlarmClockInfo at " +
@@ -1531,6 +1582,11 @@
                 mPendingWhileIdleAlarms.remove(i);
             }
         }
+        for (int i = mLastAllowWhileIdleDispatch.size() - 1; i >= 0; i--) {
+            if (UserHandle.getUserId(mLastAllowWhileIdleDispatch.keyAt(i)) == userHandle) {
+                mLastAllowWhileIdleDispatch.removeAt(i);
+            }
+        }
 
         if (didRemove) {
             if (DEBUG_BATCH) {
@@ -1666,6 +1722,25 @@
             final int N = batch.size();
             for (int i = 0; i < N; i++) {
                 Alarm alarm = batch.get(i);
+
+                if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+                    // If this is an ALLOW_WHILE_IDLE alarm, we constrain how frequently the app can
+                    // schedule such alarms.
+                    long lastTime = mLastAllowWhileIdleDispatch.get(alarm.uid, 0);
+                    long minTime = lastTime + mAllowWhileIdleMinTime;
+                    if (nowELAPSED < minTime) {
+                        // Whoops, it hasn't been long enough since the last ALLOW_WHILE_IDLE
+                        // alarm went off for this app.  Reschedule the alarm to be in the
+                        // correct time period.
+                        alarm.whenElapsed = minTime;
+                        if (alarm.maxWhenElapsed < minTime) {
+                            alarm.maxWhenElapsed = minTime;
+                        }
+                        setImplLocked(alarm, true, false);
+                        continue;
+                    }
+                }
+
                 alarm.count = 1;
                 triggerList.add(alarm);
                 if ((alarm.flags&AlarmManager.FLAG_WAKE_FROM_IDLE) != 0) {
@@ -1695,7 +1770,7 @@
                     setImplLocked(alarm.type, alarm.when + delta, nextElapsed, alarm.windowLength,
                             maxTriggerTime(nowELAPSED, nextElapsed, alarm.repeatInterval),
                             alarm.repeatInterval, alarm.operation, alarm.flags, true,
-                            alarm.workSource, alarm.alarmClock, alarm.userId);
+                            alarm.workSource, alarm.alarmClock, alarm.uid);
                 }
 
                 if (alarm.wakeup) {
@@ -1749,19 +1824,19 @@
         public final String tag;
         public final WorkSource workSource;
         public final int flags;
+        public final AlarmManager.AlarmClockInfo alarmClock;
+        public final int uid;
         public int count;
         public long when;
         public long windowLength;
         public long whenElapsed;    // 'when' in the elapsed time base
         public long maxWhenElapsed; // also in the elapsed time base
         public long repeatInterval;
-        public final AlarmManager.AlarmClockInfo alarmClock;
-        public final int userId;
         public PriorityClass priorityClass;
 
         public Alarm(int _type, long _when, long _whenElapsed, long _windowLength, long _maxWhen,
                 long _interval, PendingIntent _op, WorkSource _ws, int _flags,
-                AlarmManager.AlarmClockInfo _info, int _userId) {
+                AlarmManager.AlarmClockInfo _info, int _uid) {
             type = _type;
             origWhen = _when;
             wakeup = _type == AlarmManager.ELAPSED_REALTIME_WAKEUP
@@ -1776,7 +1851,7 @@
             workSource = _ws;
             flags = _flags;
             alarmClock = _info;
-            userId = _userId;
+            uid = _uid;
         }
 
         public static String makeTag(PendingIntent pi, int type) {
@@ -1812,7 +1887,7 @@
                         pw.print(" when="); TimeUtils.formatDuration(when, nowELAPSED, pw);
                     }
                     pw.println();
-            pw.print(prefix); pw.print("window="); pw.print(windowLength);
+            pw.print(prefix); pw.print("window="); TimeUtils.formatDuration(windowLength, pw);
                     pw.print(" repeatInterval="); pw.print(repeatInterval);
                     pw.print(" count="); pw.print(count);
                     pw.print(" flags=0x"); pw.println(Integer.toHexString(flags));
@@ -1925,6 +2000,11 @@
                 mInFlight.add(inflight);
                 mBroadcastRefCount++;
 
+                if ((alarm.flags&AlarmManager.FLAG_ALLOW_WHILE_IDLE) != 0) {
+                    // Record the last time this uid handled an ALLOW_WHILE_IDLE alarm.
+                    mLastAllowWhileIdleDispatch.put(alarm.uid, nowELAPSED);
+                }
+
                 final BroadcastStats bs = inflight.mBroadcastStats;
                 bs.count++;
                 if (bs.nesting == 0) {
@@ -2196,7 +2276,8 @@
 
             final WorkSource workSource = null; // Let system take blame for time tick events.
             setImpl(ELAPSED_REALTIME, SystemClock.elapsedRealtime() + tickEventDelay, 0,
-                    0, mTimeTickSender, AlarmManager.FLAG_STANDALONE, workSource, null);
+                    0, mTimeTickSender, AlarmManager.FLAG_STANDALONE, workSource, null,
+                    Process.myUid());
         }
 
         public void scheduleDateChangedEvent() {
@@ -2210,7 +2291,7 @@
 
             final WorkSource workSource = null; // Let system take blame for date change events.
             setImpl(RTC, calendar.getTimeInMillis(), 0, 0, mDateChangeSender,
-                    AlarmManager.FLAG_STANDALONE, workSource, null);
+                    AlarmManager.FLAG_STANDALONE, workSource, null, Process.myUid());
         }
     }
     
@@ -2243,6 +2324,7 @@
             IntentFilter sdFilter = new IntentFilter();
             sdFilter.addAction(Intent.ACTION_EXTERNAL_APPLICATIONS_UNAVAILABLE);
             sdFilter.addAction(Intent.ACTION_USER_STOPPED);
+            sdFilter.addAction(Intent.ACTION_UID_REMOVED);
             getContext().registerReceiver(this, sdFilter);
         }
         
@@ -2267,6 +2349,11 @@
                     if (userHandle >= 0) {
                         removeUserLocked(userHandle);
                     }
+                } else if (Intent.ACTION_UID_REMOVED.equals(action)) {
+                    int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
+                    if (uid >= 0) {
+                        mLastAllowWhileIdleDispatch.delete(uid);
+                    }
                 } else {
                     if (Intent.ACTION_PACKAGE_REMOVED.equals(action)
                             && intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) {
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 66fd36f..fbb6dc9 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -21,8 +21,8 @@
 import android.bluetooth.BluetoothAdapter;
 import android.bluetooth.BluetoothProfile;
 import android.bluetooth.IBluetooth;
-import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothGatt;
 import android.bluetooth.IBluetoothHeadset;
 import android.bluetooth.IBluetoothManager;
 import android.bluetooth.IBluetoothManagerCallback;
@@ -37,6 +37,7 @@
 import android.content.ServiceConnection;
 import android.content.pm.PackageManager;
 import android.content.pm.UserInfo;
+import android.database.ContentObserver;
 import android.os.Binder;
 import android.os.Handler;
 import android.os.IBinder;
@@ -56,11 +57,8 @@
 import java.io.FileDescriptor;
 import java.io.IOException;
 import java.io.PrintWriter;
-
 import java.util.HashMap;
 import java.util.Map;
-
-import java.util.*;
 class BluetoothManagerService extends IBluetoothManager.Stub {
     private static final String TAG = "BluetoothManagerService";
     private static final boolean DBG = true;
@@ -259,6 +257,8 @@
         mName = null;
         mErrorRecoveryRetryCounter = 0;
         mContentResolver = context.getContentResolver();
+        // Observe BLE scan only mode settings change.
+        registerForBleScanModeChange();
         mCallbacks = new RemoteCallbackList<IBluetoothManagerCallback>();
         mStateChangeCallbacks = new RemoteCallbackList<IBluetoothStateChangeCallback>();
         IntentFilter filter = new IntentFilter(Intent.ACTION_BOOT_COMPLETED);
@@ -458,6 +458,40 @@
         return false;
     }
 
+    // Monitor change of BLE scan only mode settings.
+    private void registerForBleScanModeChange() {
+        ContentObserver contentObserver = new ContentObserver(null) {
+            @Override
+            public void onChange(boolean selfChange) {
+                if (!isBleScanAlwaysAvailable()) {
+                    disableBleScanMode();
+                    clearBleApps();
+                    try {
+                        if (mBluetooth != null) mBluetooth.onBrEdrDown();
+                    } catch (RemoteException e) {
+                        Log.e(TAG, "error when disabling bluetooth", e);
+                    }
+                }
+            }
+        };
+
+        mContentResolver.registerContentObserver(
+                Settings.Global.getUriFor(Settings.Global.BLE_SCAN_ALWAYS_AVAILABLE),
+                false, contentObserver);
+    }
+
+    // Disable ble scan only mode.
+    private void disableBleScanMode() {
+        try {
+            if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
+                if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable");
+                mEnable = false;
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "getState()", e);
+        }
+    }
+
     public int updateBleAppCount(IBinder token, boolean enable) {
         if (enable) {
             ClientDeathRecipient r = mBleApps.get(token);
@@ -478,11 +512,8 @@
         } else  {
             ClientDeathRecipient r = mBleApps.get(token);
             if (r != null) {
-                try {
-                    token.linkToDeath(r, 0);
-                } catch (RemoteException ex) {
-                    throw new IllegalArgumentException("Wake lock is already dead.");
-                }
+                // Unregister death recipient as the app goes away.
+                token.unlinkToDeath(r, 0);
                 mBleApps.remove(token);
                 synchronized (this) {
                     if (mBleAppCount > 0) --mBleAppCount;
@@ -492,18 +523,19 @@
         }
         if (DBG) Log.d(TAG, "Updated BleAppCount" + mBleAppCount);
         if (mBleAppCount == 0 && mEnable) {
-            try {
-                if (mBluetooth != null && (mBluetooth.getState() != BluetoothAdapter.STATE_ON)) {
-                    if (DBG) Log.d(TAG, "Reseting the mEnable flag for clean disable");
-                    mEnable = false;
-                }
-            } catch (RemoteException e) {
-                Log.e(TAG, "getState()", e);
-            }
+            disableBleScanMode();
         }
         return mBleAppCount;
     }
 
+    // Clear all apps using BLE scan only mode.
+    private void clearBleApps() {
+        synchronized (this) {
+            mBleApps.clear();
+            mBleAppCount = 0;
+        }
+    }
+
     /** @hide*/
     public boolean isBleAppPresent() {
         if (DBG) Log.d(TAG, "isBleAppPresent() count: " + mBleAppCount);
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 9c6e16f..f645764 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3289,7 +3289,6 @@
             CharSequence title;
             CharSequence details;
             int icon;
-            Notification notification = new Notification();
             if (notifyType == NotificationType.NO_INTERNET &&
                     networkType == ConnectivityManager.TYPE_WIFI) {
                 title = r.getString(R.string.wifi_no_internet, 0);
@@ -3324,14 +3323,17 @@
                 return;
             }
 
-            notification.when = 0;
-            notification.icon = icon;
-            notification.flags = Notification.FLAG_AUTO_CANCEL;
-            notification.tickerText = title;
-            notification.color = mContext.getColor(
-                    com.android.internal.R.color.system_notification_accent_color);
-            notification.setLatestEventInfo(mContext, title, details, notification.contentIntent);
-            notification.contentIntent = intent;
+            Notification notification = new Notification.Builder(mContext)
+                    .setWhen(0)
+                    .setSmallIcon(icon)
+                    .setAutoCancel(true)
+                    .setTicker(title)
+                    .setColor(mContext.getColor(
+                            com.android.internal.R.color.system_notification_accent_color))
+                    .setContentTitle(title)
+                    .setContentText(details)
+                    .setContentIntent(intent)
+                    .build();
 
             try {
                 notificationManager.notify(NOTIFICATION_ID, id, notification);
diff --git a/services/core/java/com/android/server/InputMethodManagerService.java b/services/core/java/com/android/server/InputMethodManagerService.java
index 6e6fb7f..a5d536e 100644
--- a/services/core/java/com/android/server/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/InputMethodManagerService.java
@@ -71,6 +71,7 @@
 import android.inputmethodservice.InputMethodService;
 import android.net.Uri;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.Environment;
 import android.os.Handler;
 import android.os.IBinder;
@@ -212,7 +213,7 @@
     private NotificationManager mNotificationManager;
     private KeyguardManager mKeyguardManager;
     private StatusBarManagerService mStatusBar;
-    private Notification mImeSwitcherNotification;
+    private Notification.Builder mImeSwitcherNotification;
     private PendingIntent mImeSwitchPendingIntent;
     private boolean mShowOngoingImeSwitcherForPhones;
     private boolean mNotificationShown;
@@ -798,18 +799,15 @@
         mHasFeature = context.getPackageManager().hasSystemFeature(
                 PackageManager.FEATURE_INPUT_METHODS);
 
-        mImeSwitcherNotification = new Notification();
-        mImeSwitcherNotification.icon = com.android.internal.R.drawable.ic_notification_ime_default;
-        mImeSwitcherNotification.when = 0;
-        mImeSwitcherNotification.flags = Notification.FLAG_ONGOING_EVENT;
-        mImeSwitcherNotification.tickerText = null;
-        mImeSwitcherNotification.defaults = 0; // please be quiet
-        mImeSwitcherNotification.sound = null;
-        mImeSwitcherNotification.vibrate = null;
-
-        // Tag this notification specially so SystemUI knows it's important
-        mImeSwitcherNotification.extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
-        mImeSwitcherNotification.category = Notification.CATEGORY_SYSTEM;
+        Bundle extras = new Bundle();
+        extras.putBoolean(Notification.EXTRA_ALLOW_DURING_SETUP, true);
+        mImeSwitcherNotification = new Notification.Builder(mContext)
+            .setSmallIcon(com.android.internal.R.drawable.ic_notification_ime_default)
+            .setWhen(0)
+            .setOngoing(true)
+            .addExtras(extras)
+            .setCategory(Notification.CATEGORY_SYSTEM)
+            .setColor(com.android.internal.R.color.system_notification_accent_color);
 
         Intent intent = new Intent(Settings.ACTION_SHOW_INPUT_METHOD_PICKER);
         mImeSwitchPendingIntent = PendingIntent.getBroadcast(mContext, 0, intent, 0);
@@ -1766,11 +1764,9 @@
                         com.android.internal.R.string.select_input_method);
                 final CharSequence summary = InputMethodUtils.getImeAndSubtypeDisplayName(
                         mContext, imi, mCurrentSubtype);
-
-                mImeSwitcherNotification.color = mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color);
-                mImeSwitcherNotification.setLatestEventInfo(
-                        mContext, title, summary, mImeSwitchPendingIntent);
+                mImeSwitcherNotification.setContentTitle(title)
+                        .setContentText(summary)
+                        .setContentIntent(mImeSwitchPendingIntent);
                 if ((mNotificationManager != null)
                         && !mWindowManagerService.hasNavigationBar()) {
                     if (DEBUG) {
@@ -1778,7 +1774,7 @@
                     }
                     mNotificationManager.notifyAsUser(null,
                             com.android.internal.R.string.select_input_method,
-                            mImeSwitcherNotification, UserHandle.ALL);
+                            mImeSwitcherNotification.build(), UserHandle.ALL);
                     mNotificationShown = true;
                 }
             } else {
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index aa7d1f8..f69626d 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -993,6 +993,7 @@
     private void onDiskScannedLocked(DiskInfo disk) {
         final Intent intent = new Intent(DiskInfo.ACTION_DISK_SCANNED);
         intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+        intent.putExtra(DiskInfo.EXTRA_DISK_ID, disk.id);
         mContext.sendBroadcastAsUser(intent, UserHandle.ALL,
                 android.Manifest.permission.WRITE_MEDIA_STORAGE);
 
diff --git a/services/core/java/com/android/server/UiModeManagerService.java b/services/core/java/com/android/server/UiModeManagerService.java
index 64f3070..0b67ad8 100644
--- a/services/core/java/com/android/server/UiModeManagerService.java
+++ b/services/core/java/com/android/server/UiModeManagerService.java
@@ -601,21 +601,22 @@
             if (mCarModeEnabled) {
                 Intent carModeOffIntent = new Intent(context, DisableCarModeActivity.class);
 
-                Notification n = new Notification();
-                n.icon = R.drawable.stat_notify_car_mode;
-                n.defaults = Notification.DEFAULT_LIGHTS;
-                n.flags = Notification.FLAG_ONGOING_EVENT;
-                n.when = 0;
-                n.color = context.getColor(
-                        com.android.internal.R.color.system_notification_accent_color);
-                n.setLatestEventInfo(
-                        context,
-                        context.getString(R.string.car_mode_disable_notification_title),
-                        context.getString(R.string.car_mode_disable_notification_message),
-                        PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
-                                null, UserHandle.CURRENT));
+                Notification.Builder n = new Notification.Builder(context)
+                        .setSmallIcon(R.drawable.stat_notify_car_mode)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .setOngoing(true)
+                        .setWhen(0)
+                        .setColor(context.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                        .setContentTitle(
+                                context.getString(R.string.car_mode_disable_notification_title))
+                        .setContentText(
+                                context.getString(R.string.car_mode_disable_notification_message))
+                        .setContentIntent(
+                                PendingIntent.getActivityAsUser(context, 0, carModeOffIntent, 0,
+                                        null, UserHandle.CURRENT));
                 mNotificationManager.notifyAsUser(null,
-                        R.string.car_mode_disable_notification_title, n, UserHandle.ALL);
+                        R.string.car_mode_disable_notification_title, n.build(), UserHandle.ALL);
             } else {
                 mNotificationManager.cancelAsUser(null,
                         R.string.car_mode_disable_notification_title, UserHandle.ALL);
diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java
index 49d9988..3456dbc 100644
--- a/services/core/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/core/java/com/android/server/accounts/AccountManagerService.java
@@ -2005,8 +2005,6 @@
         String authTokenLabel = intent.getStringExtra(
                 GrantCredentialsPermissionActivity.EXTRAS_AUTH_TOKEN_LABEL);
 
-        Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
-                0 /* when */);
         final String titleAndSubtitle =
                 mContext.getString(R.string.permission_request_notification_with_subtitle,
                 account.name);
@@ -2019,11 +2017,16 @@
         }
         UserHandle user = new UserHandle(userId);
         Context contextForUser = getContextForUser(user);
-        n.color = contextForUser.getColor(
-                com.android.internal.R.color.system_notification_accent_color);
-        n.setLatestEventInfo(contextForUser, title, subtitle,
-                PendingIntent.getActivityAsUser(mContext, 0, intent,
-                        PendingIntent.FLAG_CANCEL_CURRENT, null, user));
+        Notification n = new Notification.Builder(contextForUser)
+                .setSmallIcon(android.R.drawable.stat_sys_warning)
+                .setWhen(0)
+                .setColor(contextForUser.getColor(
+                        com.android.internal.R.color.system_notification_accent_color))
+                .setContentTitle(title)
+                .setContentText(subtitle)
+                .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0, intent,
+                        PendingIntent.FLAG_CANCEL_CURRENT, null, user))
+                .build();
         installNotification(getCredentialPermissionNotificationId(
                 account, authTokenType, uid), n, user);
     }
@@ -3542,19 +3545,21 @@
             } else {
                 final Integer notificationId = getSigninRequiredNotificationId(accounts, account);
                 intent.addCategory(String.valueOf(notificationId));
-                Notification n = new Notification(android.R.drawable.stat_sys_warning, null,
-                        0 /* when */);
                 UserHandle user = new UserHandle(userId);
                 Context contextForUser = getContextForUser(user);
                 final String notificationTitleFormat =
                         contextForUser.getText(R.string.notification_title).toString();
-                n.color = contextForUser.getColor(
-                        com.android.internal.R.color.system_notification_accent_color);
-                n.setLatestEventInfo(contextForUser,
-                        String.format(notificationTitleFormat, account.name),
-                        message, PendingIntent.getActivityAsUser(
-                        mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
-                        null, user));
+                Notification n = new Notification.Builder(contextForUser)
+                        .setWhen(0)
+                        .setSmallIcon(android.R.drawable.stat_sys_warning)
+                        .setColor(contextForUser.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                        .setContentTitle(String.format(notificationTitleFormat, account.name))
+                        .setContentText(message)
+                        .setContentIntent(PendingIntent.getActivityAsUser(
+                                mContext, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT,
+                                null, user))
+                        .build();
                 installNotification(notificationId, n, user);
             }
         } finally {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 6496ba2..421ba86 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -1714,22 +1714,20 @@
                     Context context = mContext.createPackageContext(process.info.packageName, 0);
                     String text = mContext.getString(R.string.heavy_weight_notification,
                             context.getApplicationInfo().loadLabel(context.getPackageManager()));
-                    Notification notification = new Notification();
-                    notification.icon = com.android.internal.R.drawable.stat_sys_adb; //context.getApplicationInfo().icon;
-                    notification.when = 0;
-                    notification.flags = Notification.FLAG_ONGOING_EVENT;
-                    notification.tickerText = text;
-                    notification.defaults = 0; // please be quiet
-                    notification.sound = null;
-                    notification.vibrate = null;
-                    notification.color = mContext.getColor(
-                            com.android.internal.R.color.system_notification_accent_color);
-                    notification.setLatestEventInfo(context, text,
-                            mContext.getText(R.string.heavy_weight_notification_detail),
-                            PendingIntent.getActivityAsUser(mContext, 0, root.intent,
-                                    PendingIntent.FLAG_CANCEL_CURRENT, null,
-                                    new UserHandle(root.userId)));
-
+                    Notification notification = new Notification.Builder(context)
+                            .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                            .setWhen(0)
+                            .setOngoing(true)
+                            .setTicker(text)
+                            .setColor(mContext.getColor(
+                                    com.android.internal.R.color.system_notification_accent_color))
+                            .setContentTitle(text)
+                            .setContentText(
+                                    mContext.getText(R.string.heavy_weight_notification_detail))
+                            .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+                                    root.intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+                                    new UserHandle(root.userId)))
+                            .build();
                     try {
                         int[] outId = new int[1];
                         inm.enqueueNotificationWithTag("android", "android", null,
@@ -1948,20 +1946,10 @@
                 }
 
                 String text = mContext.getString(R.string.dump_heap_notification, procName);
-                Notification notification = new Notification();
-                notification.icon = com.android.internal.R.drawable.stat_sys_adb;
-                notification.when = 0;
-                notification.flags = Notification.FLAG_ONGOING_EVENT|Notification.FLAG_AUTO_CANCEL;
-                notification.tickerText = text;
-                notification.defaults = 0; // please be quiet
-                notification.sound = null;
-                notification.vibrate = null;
-                notification.color = mContext.getColor(
-                        com.android.internal.R.color.system_notification_accent_color);
+
+
                 Intent deleteIntent = new Intent();
                 deleteIntent.setAction(DumpHeapActivity.ACTION_DELETE_DUMPHEAP);
-                notification.deleteIntent = PendingIntent.getBroadcastAsUser(mContext, 0,
-                        deleteIntent, 0, UserHandle.OWNER);
                 Intent intent = new Intent();
                 intent.setClassName("android", DumpHeapActivity.class.getName());
                 intent.putExtra(DumpHeapActivity.KEY_PROCESS, procName);
@@ -1970,11 +1958,23 @@
                     intent.putExtra(DumpHeapActivity.KEY_DIRECT_LAUNCH, reportPackage);
                 }
                 int userId = UserHandle.getUserId(uid);
-                notification.setLatestEventInfo(mContext, text,
-                        mContext.getText(R.string.dump_heap_notification_detail),
-                        PendingIntent.getActivityAsUser(mContext, 0, intent,
-                                PendingIntent.FLAG_CANCEL_CURRENT, null,
-                                new UserHandle(userId)));
+                Notification notification = new Notification.Builder(mContext)
+                        .setSmallIcon(com.android.internal.R.drawable.stat_sys_adb)
+                        .setWhen(0)
+                        .setOngoing(true)
+                        .setAutoCancel(true)
+                        .setTicker(text)
+                        .setColor(mContext.getColor(
+                                com.android.internal.R.color.system_notification_accent_color))
+                        .setContentTitle(text)
+                        .setContentText(
+                                mContext.getText(R.string.dump_heap_notification_detail))
+                        .setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
+                                intent, PendingIntent.FLAG_CANCEL_CURRENT, null,
+                                new UserHandle(userId)))
+                        .setDeleteIntent(PendingIntent.getBroadcastAsUser(mContext, 0,
+                                deleteIntent, 0, UserHandle.OWNER))
+                        .build();
 
                 try {
                     int[] outId = new int[1];
@@ -19382,15 +19382,16 @@
             enforceCallingPermission(android.Manifest.permission.SET_DEBUG_APP,
                     "setDumpHeapDebugLimit()");
         } else {
-            if (!Build.IS_DEBUGGABLE) {
-                throw new SecurityException("Not running a debuggable build");
-            }
             synchronized (mPidsSelfLocked) {
                 ProcessRecord proc = mPidsSelfLocked.get(Binder.getCallingPid());
                 if (proc == null) {
                     throw new SecurityException("No process found for calling pid "
                             + Binder.getCallingPid());
                 }
+                if (!Build.IS_DEBUGGABLE
+                        && (proc.info.flags&ApplicationInfo.FLAG_DEBUGGABLE) == 0) {
+                    throw new SecurityException("Not running a debuggable build");
+                }
                 processName = proc.processName;
                 uid = proc.uid;
                 if (reportPackage != null && !proc.pkgList.containsKey(reportPackage)) {
diff --git a/services/core/java/com/android/server/audio/AudioService.java b/services/core/java/com/android/server/audio/AudioService.java
index cd467bd..d39b25f 100644
--- a/services/core/java/com/android/server/audio/AudioService.java
+++ b/services/core/java/com/android/server/audio/AudioService.java
@@ -2852,6 +2852,49 @@
         }
     }
 
+    void setBtScoDeviceConnectionState(BluetoothDevice btDevice, int state) {
+        if (btDevice == null) {
+            return;
+        }
+
+        String address = btDevice.getAddress();
+        BluetoothClass btClass = btDevice.getBluetoothClass();
+        int outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
+        int inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
+        if (btClass != null) {
+            switch (btClass.getDeviceClass()) {
+            case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
+            case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
+                outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
+                break;
+            case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
+                outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
+                break;
+            }
+        }
+
+        if (!BluetoothAdapter.checkBluetoothAddress(address)) {
+            address = "";
+        }
+
+        boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
+
+        String btDeviceName =  btDevice.getName();
+        boolean success =
+            handleDeviceConnection(connected, outDevice, address, btDeviceName) &&
+            handleDeviceConnection(connected, inDevice, address, btDeviceName);
+        if (success) {
+            synchronized (mScoClients) {
+                if (connected) {
+                    mBluetoothHeadsetDevice = btDevice;
+                } else {
+                    mBluetoothHeadsetDevice = null;
+                    resetBluetoothSco();
+                }
+            }
+        }
+    }
+
     private BluetoothProfile.ServiceListener mBluetoothProfileServiceListener =
         new BluetoothProfile.ServiceListener() {
         public void onServiceConnected(int profile, BluetoothProfile proxy) {
@@ -3002,6 +3045,10 @@
 
             case BluetoothProfile.HEADSET:
                 synchronized (mScoClients) {
+                    if (mBluetoothHeadsetDevice != null) {
+                        setBtScoDeviceConnectionState(mBluetoothHeadsetDevice,
+                                BluetoothProfile.STATE_DISCONNECTED);
+                    }
                     mBluetoothHeadset = null;
                 }
                 break;
@@ -4894,49 +4941,9 @@
             } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) {
                 state = intent.getIntExtra(BluetoothProfile.EXTRA_STATE,
                                                BluetoothProfile.STATE_DISCONNECTED);
-                outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO;
-                inDevice = AudioSystem.DEVICE_IN_BLUETOOTH_SCO_HEADSET;
-                String address = null;
-
                 BluetoothDevice btDevice = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
-                if (btDevice == null) {
-                    return;
-                }
 
-                address = btDevice.getAddress();
-                BluetoothClass btClass = btDevice.getBluetoothClass();
-                if (btClass != null) {
-                    switch (btClass.getDeviceClass()) {
-                    case BluetoothClass.Device.AUDIO_VIDEO_WEARABLE_HEADSET:
-                    case BluetoothClass.Device.AUDIO_VIDEO_HANDSFREE:
-                        outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_HEADSET;
-                        break;
-                    case BluetoothClass.Device.AUDIO_VIDEO_CAR_AUDIO:
-                        outDevice = AudioSystem.DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
-                        break;
-                    }
-                }
-
-                if (!BluetoothAdapter.checkBluetoothAddress(address)) {
-                    address = "";
-                }
-
-                boolean connected = (state == BluetoothProfile.STATE_CONNECTED);
-
-                String btDeviceName =  btDevice.getName();
-                boolean success =
-                    handleDeviceConnection(connected, outDevice, address, btDeviceName) &&
-                    handleDeviceConnection(connected, inDevice, address, btDeviceName);
-                if (success) {
-                    synchronized (mScoClients) {
-                        if (connected) {
-                            mBluetoothHeadsetDevice = btDevice;
-                        } else {
-                            mBluetoothHeadsetDevice = null;
-                            resetBluetoothSco();
-                        }
-                    }
-                }
+                setBtScoDeviceConnectionState(btDevice, state);
             } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) {
                 boolean broadcast = false;
                 int scoAudioState = AudioManager.SCO_AUDIO_STATE_ERROR;
diff --git a/services/core/java/com/android/server/connectivity/Tethering.java b/services/core/java/com/android/server/connectivity/Tethering.java
index 897300f..c1aaf07 100644
--- a/services/core/java/com/android/server/connectivity/Tethering.java
+++ b/services/core/java/com/android/server/connectivity/Tethering.java
@@ -130,7 +130,8 @@
 
     private StateMachine mTetherMasterSM;
 
-    private Notification mTetheredNotification;
+    private Notification.Builder mTetheredNotificationBuilder;
+    private int mLastNotificationId;
 
     private boolean mRndisEnabled;       // track the RNDIS function enabled state
     private boolean mUsbTetherRequested; // true if USB tethering should be started
@@ -450,12 +451,13 @@
             return;
         }
 
-        if (mTetheredNotification != null) {
-            if (mTetheredNotification.icon == icon) {
+        if (mLastNotificationId != 0) {
+            if (mLastNotificationId == icon) {
                 return;
             }
-            notificationManager.cancelAsUser(null, mTetheredNotification.icon,
+            notificationManager.cancelAsUser(null, mLastNotificationId,
                     UserHandle.ALL);
+            mLastNotificationId = 0;
         }
 
         Intent intent = new Intent();
@@ -470,31 +472,32 @@
         CharSequence message = r.getText(com.android.internal.R.string.
                 tethered_notification_message);
 
-        if (mTetheredNotification == null) {
-            mTetheredNotification = new Notification();
-            mTetheredNotification.when = 0;
+        if (mTetheredNotificationBuilder == null) {
+            mTetheredNotificationBuilder = new Notification.Builder(mContext);
+            mTetheredNotificationBuilder.setWhen(0)
+                    .setOngoing(true)
+                    .setColor(mContext.getColor(
+                            com.android.internal.R.color.system_notification_accent_color))
+                    .setVisibility(Notification.VISIBILITY_PUBLIC)
+                    .setCategory(Notification.CATEGORY_STATUS);
         }
-        mTetheredNotification.icon = icon;
-        mTetheredNotification.defaults &= ~Notification.DEFAULT_SOUND;
-        mTetheredNotification.flags = Notification.FLAG_ONGOING_EVENT;
-        mTetheredNotification.tickerText = title;
-        mTetheredNotification.visibility = Notification.VISIBILITY_PUBLIC;
-        mTetheredNotification.color = mContext.getColor(
-                com.android.internal.R.color.system_notification_accent_color);
-        mTetheredNotification.setLatestEventInfo(mContext, title, message, pi);
-        mTetheredNotification.category = Notification.CATEGORY_STATUS;
+        mTetheredNotificationBuilder.setSmallIcon(icon)
+                .setContentTitle(title)
+                .setContentText(message)
+                .setContentIntent(pi);
+        mLastNotificationId = icon;
 
-        notificationManager.notifyAsUser(null, mTetheredNotification.icon,
-                mTetheredNotification, UserHandle.ALL);
+        notificationManager.notifyAsUser(null, mLastNotificationId,
+                mTetheredNotificationBuilder.build(), UserHandle.ALL);
     }
 
     private void clearTetheredNotification() {
         NotificationManager notificationManager =
             (NotificationManager)mContext.getSystemService(Context.NOTIFICATION_SERVICE);
-        if (notificationManager != null && mTetheredNotification != null) {
-            notificationManager.cancelAsUser(null, mTetheredNotification.icon,
+        if (notificationManager != null && mLastNotificationId != 0) {
+            notificationManager.cancelAsUser(null, mLastNotificationId,
                     UserHandle.ALL);
-            mTetheredNotification = null;
+            mLastNotificationId = 0;
         }
     }
 
diff --git a/services/core/java/com/android/server/content/SyncManager.java b/services/core/java/com/android/server/content/SyncManager.java
index 3dc282b..f222dba 100644
--- a/services/core/java/com/android/server/content/SyncManager.java
+++ b/services/core/java/com/android/server/content/SyncManager.java
@@ -3260,16 +3260,18 @@
                     R.string.contentServiceTooManyDeletesNotificationDesc);
 
             Context contextForUser = getContextForUser(user);
-            Notification notification =
-                new Notification(R.drawable.stat_notify_sync_error,
-                        mContext.getString(R.string.contentServiceSync),
-                        System.currentTimeMillis());
-            notification.color = contextForUser.getColor(
-                    com.android.internal.R.color.system_notification_accent_color);
-            notification.setLatestEventInfo(contextForUser,
-                    contextForUser.getString(R.string.contentServiceSyncNotificationTitle),
-                    String.format(tooManyDeletesDescFormat.toString(), authorityName),
-                    pendingIntent);
+            Notification notification = new Notification.Builder(contextForUser)
+                    .setSmallIcon(R.drawable.stat_notify_sync_error)
+                    .setTicker(mContext.getString(R.string.contentServiceSync))
+                    .setWhen(System.currentTimeMillis())
+                    .setColor(contextForUser.getColor(
+                            com.android.internal.R.color.system_notification_accent_color))
+                    .setContentTitle(contextForUser.getString(
+                            R.string.contentServiceSyncNotificationTitle))
+                    .setContentText(
+                            String.format(tooManyDeletesDescFormat.toString(), authorityName))
+                    .setContentIntent(pendingIntent)
+                    .build();
             notification.flags |= Notification.FLAG_ONGOING_EVENT;
             mNotificationMgr.notifyAsUser(null, account.hashCode() ^ authority.hashCode(),
                     notification, user);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index 7673af4..81ef4d5 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -376,8 +376,13 @@
 
     void updatePowerSaveTempWhitelistLocked() {
         try {
+            // Clear the states of the current whitelist
+            final int N = mPowerSaveTempWhitelistAppIds.size();
+            for (int i = 0; i < N; i++) {
+                mPowerSaveTempWhitelistAppIds.setValueAt(i, false);
+            }
+            // Update the states with the new whitelist
             final int[] whitelist = mDeviceIdleController.getAppIdTempWhitelist();
-            mPowerSaveTempWhitelistAppIds.clear();
             if (whitelist != null) {
                 for (int uid : whitelist) {
                     mPowerSaveTempWhitelistAppIds.put(uid, true);
@@ -387,6 +392,18 @@
         }
     }
 
+    /**
+     * Remove unnecessary entries in the temp whitelist
+     */
+    void purgePowerSaveTempWhitelistLocked() {
+        final int N = mPowerSaveTempWhitelistAppIds.size();
+        for (int i = N - 1; i >= 0; i--) {
+            if (mPowerSaveTempWhitelistAppIds.valueAt(i) == false) {
+                mPowerSaveTempWhitelistAppIds.removeAt(i);
+            }
+        }
+    }
+
     public void systemReady() {
         if (!isBandwidthControlEnabled()) {
             Slog.w(TAG, "bandwidth controls disabled, unable to enforce policy");
@@ -521,6 +538,7 @@
                 } else {
                     updatePowerSaveTempWhitelistLocked();
                     updateRulesForTempWhitelistChangeLocked();
+                    purgePowerSaveTempWhitelistLocked();
                 }
             }
         }
diff --git a/services/core/java/com/android/server/pm/BackgroundDexOptService.java b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
index 7e66cd1..7b1ac5ca 100644
--- a/services/core/java/com/android/server/pm/BackgroundDexOptService.java
+++ b/services/core/java/com/android/server/pm/BackgroundDexOptService.java
@@ -16,6 +16,7 @@
 
 package com.android.server.pm;
 
+import android.app.AlarmManager;
 import android.app.job.JobInfo;
 import android.app.job.JobParameters;
 import android.app.job.JobScheduler;
@@ -34,6 +35,8 @@
 public class BackgroundDexOptService extends JobService {
     static final String TAG = "BackgroundDexOptService";
 
+    static final long RETRY_LATENCY = 4 * AlarmManager.INTERVAL_HOUR;
+
     static final int BACKGROUND_DEXOPT_JOB = 800;
     private static ComponentName sDexoptServiceName = new ComponentName(
             "android",
@@ -46,11 +49,12 @@
 
     final AtomicBoolean mIdleTime = new AtomicBoolean(false);
 
-    public static void schedule(Context context) {
+    public static void schedule(Context context, long minLatency) {
         JobScheduler js = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
         JobInfo job = new JobInfo.Builder(BACKGROUND_DEXOPT_JOB, sDexoptServiceName)
                 .setRequiresDeviceIdle(true)
                 .setRequiresCharging(true)
+                .setMinimumLatency(minLatency)
                 .build();
         js.schedule(job);
     }
@@ -62,6 +66,7 @@
                 (PackageManagerService)ServiceManager.getService("package");
 
         if (pm.isStorageLow()) {
+            schedule(BackgroundDexOptService.this, RETRY_LATENCY);
             return false;
         }
         final ArraySet<String> pkgs = pm.getPackagesThatNeedDexOpt();
@@ -77,7 +82,7 @@
                 for (String pkg : pkgs) {
                     if (!mIdleTime.get()) {
                         // stopped while still working, so we need to reschedule
-                        schedule(BackgroundDexOptService.this);
+                        schedule(BackgroundDexOptService.this, 0);
                         return;
                     }
                     if (sFailedPackageNames.contains(pkg)) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 25ca167..dbcfa19 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -243,7 +243,7 @@
     }
 
     /** Amount of time (in milliseconds) to wait for windows drawn before powering on. */
-    static final int WAITING_FOR_DRAWN_TIMEOUT = 1000;
+    static final int WAITING_FOR_DRAWN_TIMEOUT = 500;
 
     /**
      * Lock protecting internal state.  Must not call out into window
@@ -836,13 +836,18 @@
             // If sensor is turned off or nonexistent for some reason
             return;
         }
-        //Could have been invoked due to screen turning on or off or
-        //change of the currently visible window's orientation
+        // Could have been invoked due to screen turning on or off or
+        // change of the currently visible window's orientation.
         if (localLOGV) Slog.v(TAG, "mScreenOnEarly=" + mScreenOnEarly
                 + ", mAwake=" + mAwake + ", mCurrentAppOrientation=" + mCurrentAppOrientation
-                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled);
+                + ", mOrientationSensorEnabled=" + mOrientationSensorEnabled
+                + ", mKeyguardDrawComplete=" + mKeyguardDrawComplete
+                + ", mWindowManagerDrawComplete=" + mWindowManagerDrawComplete);
         boolean disable = true;
-        if (mScreenOnEarly && mAwake) {
+        // Note: We postpone the rotating of the screen until the keyguard as well as the
+        // window manager have reported a draw complete.
+        if (mScreenOnEarly && mAwake &&
+                mKeyguardDrawComplete && mWindowManagerDrawComplete) {
             if (needSensorRunningLp()) {
                 disable = false;
                 //enable listener if not already enabled
@@ -5369,7 +5374,7 @@
     private void finishKeyguardDrawn() {
         synchronized (mLock) {
             if (!mAwake || mKeyguardDrawComplete) {
-                return; // spurious
+                return; // We are not awake yet or we have already informed of this event.
             }
 
             mKeyguardDrawComplete = true;
@@ -5407,18 +5412,18 @@
             mScreenOnFully = false;
             mWindowManagerDrawComplete = false;
             mScreenOnListener = screenOnListener;
-            updateOrientationListenerLp();
         }
 
         mWindowManagerInternal.waitForAllWindowsDrawn(mWindowManagerDrawCallback,
                 WAITING_FOR_DRAWN_TIMEOUT);
-        // ... eventually calls finishWindowsDrawn
+        // ... eventually calls finishWindowsDrawn which will finalize our screen turn on
+        // as well as enabling the orientation change logic/sensor.
     }
 
     private void finishWindowsDrawn() {
         synchronized (mLock) {
             if (!mScreenOnEarly || mWindowManagerDrawComplete) {
-                return; // spurious
+                return; // Screen is not turned on or we did already handle this case earlier.
             }
 
             mWindowManagerDrawComplete = true;
@@ -5428,6 +5433,11 @@
     }
 
     private void finishScreenTurningOn() {
+        synchronized (mLock) {
+            // We have just finished drawing screen content. Since the orientation listener
+            // gets only installed when all windows are drawn, we try to install it again.
+            updateOrientationListenerLp();
+        }
         final ScreenOnListener listener;
         final boolean enableScreen;
         synchronized (mLock) {
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 925a609..29c65db 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -958,7 +958,7 @@
 
                 try {
                     Slog.i(TAG, "BackgroundDexOptService");
-                    BackgroundDexOptService.schedule(context);
+                    BackgroundDexOptService.schedule(context, 0);
                 } catch (Throwable e) {
                     reportWtf("starting BackgroundDexOptService", e);
                 }
diff --git a/services/midi/java/com/android/server/midi/MidiService.java b/services/midi/java/com/android/server/midi/MidiService.java
index d1bbbfc..3ecfd55 100644
--- a/services/midi/java/com/android/server/midi/MidiService.java
+++ b/services/midi/java/com/android/server/midi/MidiService.java
@@ -741,6 +741,15 @@
         MidiDeviceInfo deviceInfo = new MidiDeviceInfo(type, id, numInputPorts, numOutputPorts,
                 inputPortNames, outputPortNames, properties, isPrivate);
 
+        if (server != null) {
+            try {
+                server.setDeviceInfo(deviceInfo);
+            } catch (RemoteException e) {
+                Log.e(TAG, "RemoteException in setDeviceInfo()");
+                return null;
+            }
+        }
+
         Device device = null;
         BluetoothDevice bluetoothDevice = null;
         if (type == MidiDeviceInfo.TYPE_BLUETOOTH) {
diff --git a/services/usage/java/com/android/server/usage/AppIdleHistory.java b/services/usage/java/com/android/server/usage/AppIdleHistory.java
index 9d3db16..e3c0868 100644
--- a/services/usage/java/com/android/server/usage/AppIdleHistory.java
+++ b/services/usage/java/com/android/server/usage/AppIdleHistory.java
@@ -27,34 +27,27 @@
  */
 public class AppIdleHistory {
 
-    private SparseArray<ArrayMap<String,byte[]>> idleHistory = new SparseArray<>();
+    private SparseArray<ArrayMap<String,byte[]>> mIdleHistory = new SparseArray<>();
     private long lastPeriod = 0;
     private static final long ONE_MINUTE = 60 * 1000;
     private static final int HISTORY_SIZE = 100;
     private static final int FLAG_LAST_STATE = 2;
     private static final int FLAG_PARTIAL_ACTIVE = 1;
-    private static final long PERIOD_DURATION = UsageStatsService.DEBUG ? ONE_MINUTE
+    private static final long PERIOD_DURATION = UsageStatsService.COMPRESS_TIME ? ONE_MINUTE
             : 60 * ONE_MINUTE;
 
     public void addEntry(String packageName, int userId, boolean idle, long timeNow) {
-        ArrayMap<String, byte[]> userHistory = idleHistory.get(userId);
-        if (userHistory == null) {
-            userHistory = new ArrayMap<>();
-            idleHistory.put(userId, userHistory);
-        }
-        byte[] packageHistory = userHistory.get(packageName);
-        if (packageHistory == null) {
-            packageHistory = new byte[HISTORY_SIZE];
-            userHistory.put(packageName, packageHistory);
-        }
+        ArrayMap<String, byte[]> userHistory = getUserHistory(userId);
+        byte[] packageHistory = getPackageHistory(userHistory, packageName);
+
         long thisPeriod = timeNow / PERIOD_DURATION;
         // Has the period switched over? Slide all users' package histories
         if (lastPeriod != 0 && lastPeriod < thisPeriod
                 && (thisPeriod - lastPeriod) < HISTORY_SIZE - 1) {
             int diff = (int) (thisPeriod - lastPeriod);
-            final int NUSERS = idleHistory.size();
+            final int NUSERS = mIdleHistory.size();
             for (int u = 0; u < NUSERS; u++) {
-                userHistory = idleHistory.valueAt(u);
+                userHistory = mIdleHistory.valueAt(u);
                 for (byte[] history : userHistory.values()) {
                     // Shift left
                     System.arraycopy(history, diff, history, 0, HISTORY_SIZE - diff);
@@ -74,12 +67,36 @@
         }
     }
 
+    private ArrayMap<String, byte[]> getUserHistory(int userId) {
+        ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId);
+        if (userHistory == null) {
+            userHistory = new ArrayMap<>();
+            mIdleHistory.put(userId, userHistory);
+        }
+        return userHistory;
+    }
+
+    private byte[] getPackageHistory(ArrayMap<String, byte[]> userHistory, String packageName) {
+        byte[] packageHistory = userHistory.get(packageName);
+        if (packageHistory == null) {
+            packageHistory = new byte[HISTORY_SIZE];
+            userHistory.put(packageName, packageHistory);
+        }
+        return packageHistory;
+    }
+
     public void removeUser(int userId) {
-        idleHistory.remove(userId);
+        mIdleHistory.remove(userId);
+    }
+
+    public boolean isIdle(int userId, String packageName) {
+        ArrayMap<String, byte[]> userHistory = getUserHistory(userId);
+        byte[] packageHistory = getPackageHistory(userHistory, packageName);
+        return (packageHistory[HISTORY_SIZE - 1] & FLAG_LAST_STATE) == 0;
     }
 
     public void dump(IndentingPrintWriter idpw, int userId) {
-        ArrayMap<String, byte[]> userHistory = idleHistory.get(userId);
+        ArrayMap<String, byte[]> userHistory = mIdleHistory.get(userId);
         if (userHistory == null) return;
         final int P = userHistory.size();
         for (int p = 0; p < P; p++) {
diff --git a/services/usage/java/com/android/server/usage/UsageStatsService.java b/services/usage/java/com/android/server/usage/UsageStatsService.java
index 7a34757..8e1895e 100644
--- a/services/usage/java/com/android/server/usage/UsageStatsService.java
+++ b/services/usage/java/com/android/server/usage/UsageStatsService.java
@@ -43,6 +43,7 @@
 import android.hardware.display.DisplayManager;
 import android.net.Uri;
 import android.os.BatteryManager;
+import android.os.BatteryStats;
 import android.os.Binder;
 import android.os.Environment;
 import android.os.Handler;
@@ -65,6 +66,7 @@
 import android.view.Display;
 
 import com.android.internal.annotations.GuardedBy;
+import com.android.internal.app.IBatteryStats;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.server.DeviceIdleController;
@@ -91,7 +93,7 @@
     static final String TAG = "UsageStatsService";
 
     static final boolean DEBUG = false;
-    private static final boolean COMPRESS_TIME = false;
+    static final boolean COMPRESS_TIME = false;
 
     private static final long TEN_SECONDS = 10 * 1000;
     private static final long ONE_MINUTE = 60 * 1000;
@@ -128,6 +130,7 @@
     IDeviceIdleController mDeviceIdleController;
     private DisplayManager mDisplayManager;
     private PowerManager mPowerManager;
+    private IBatteryStats mBatteryStats;
 
     private final SparseArray<UserUsageStatsService> mUserState = new SparseArray<>();
     private File mUsageStatsDir;
@@ -200,6 +203,8 @@
             mAppWidgetManager = getContext().getSystemService(AppWidgetManager.class);
             mDeviceIdleController = IDeviceIdleController.Stub.asInterface(
                     ServiceManager.getService(DeviceIdleController.SERVICE_NAME));
+            mBatteryStats = IBatteryStats.Stub.asInterface(
+                    ServiceManager.getService(BatteryStats.SERVICE_NAME));
             mDisplayManager = (DisplayManager) getContext().getSystemService(
                     Context.DISPLAY_SERVICE);
             mPowerManager = getContext().getSystemService(PowerManager.class);
@@ -228,7 +233,7 @@
                 }
             } else if (Intent.ACTION_USER_STARTED.equals(intent.getAction())) {
                 if (userId >=0) {
-                    postCheckIdleStates();
+                    postCheckIdleStates(userId);
                 }
             }
         }
@@ -307,7 +312,7 @@
                     mLastAppIdleParoledTime = checkAndGetTimeLocked();
                     postNextParoleTimeout();
                 }
-                postCheckIdleStates();
+                postCheckIdleStates(UserHandle.USER_ALL);
             }
         }
     }
@@ -332,22 +337,25 @@
         mHandler.sendEmptyMessageDelayed(MSG_PAROLE_END_TIMEOUT, DEFAULT_PAROLE_DURATION);
     }
 
-    void postCheckIdleStates() {
-        mHandler.removeMessages(MSG_CHECK_IDLE_STATES);
-        mHandler.sendEmptyMessage(MSG_CHECK_IDLE_STATES);
+    void postCheckIdleStates(int userId) {
+        mHandler.sendMessage(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, userId, 0));
     }
 
-    /** Check all running users' apps to see if they enter an idle state. */
-    void checkIdleStates() {
-        final int[] runningUsers;
+    /** Check all running users' or specified user's apps to see if they enter an idle state. */
+    void checkIdleStates(int checkUserId) {
+        final int[] userIds;
         try {
-            runningUsers = ActivityManagerNative.getDefault().getRunningUserIds();
+            if (checkUserId == UserHandle.USER_ALL) {
+                userIds = ActivityManagerNative.getDefault().getRunningUserIds();
+            } else {
+                userIds = new int[] { checkUserId };
+            }
         } catch (RemoteException re) {
             return;
         }
 
-        for (int i = 0; i < runningUsers.length; i++) {
-            final int userId = runningUsers[i];
+        for (int i = 0; i < userIds.length; i++) {
+            final int userId = userIds[i];
             List<PackageInfo> packages =
                     getContext().getPackageManager().getInstalledPackages(
                             PackageManager.GET_DISABLED_COMPONENTS
@@ -355,17 +363,22 @@
                             userId);
             synchronized (mLock) {
                 final long timeNow = checkAndGetTimeLocked();
+                final long screenOnTime = getScreenOnTimeLocked(timeNow);
+                UserUsageStatsService service = getUserDataAndInitializeIfNeededLocked(userId,
+                        timeNow);
                 final int packageCount = packages.size();
                 for (int p = 0; p < packageCount; p++) {
                     final String packageName = packages.get(p).packageName;
-                    final boolean isIdle = isAppIdleFiltered(packageName, userId, timeNow);
+                    final boolean isIdle = isAppIdleFiltered(packageName, userId, service, timeNow,
+                            screenOnTime);
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS,
                             userId, isIdle ? 1 : 0, packageName));
                     mAppIdleHistory.addEntry(packageName, userId, isIdle, timeNow);
                 }
             }
         }
-        mHandler.sendEmptyMessageDelayed(MSG_CHECK_IDLE_STATES, mCheckIdleIntervalMillis);
+        mHandler.sendMessageDelayed(mHandler.obtainMessage(MSG_CHECK_IDLE_STATES, checkUserId, 0),
+                mCheckIdleIntervalMillis);
     }
 
     /** Check if it's been a while since last parole and let idle apps do some work */
@@ -386,6 +399,20 @@
         }
     }
 
+    private void notifyBatteryStats(String packageName, int userId, boolean idle) {
+        try {
+            int uid = AppGlobals.getPackageManager().getPackageUid(packageName, userId);
+            if (idle) {
+                mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_INACTIVE,
+                        packageName, uid);
+            } else {
+                mBatteryStats.noteEvent(BatteryStats.HistoryItem.EVENT_PACKAGE_ACTIVE,
+                        packageName, uid);
+            }
+        } catch (RemoteException re) {
+        }
+    }
+
     void updateDisplayLocked() {
         boolean screenOn = mDisplayManager.getDisplay(Display.DEFAULT_DISPLAY).getState()
                 == Display.STATE_ON;
@@ -545,7 +572,7 @@
             final long lastUsedTime = service.getSystemLastUsedTime(event.mPackage);
             final boolean previouslyIdle = hasPassedIdleTimeoutLocked(beginIdleTime,
                     lastUsedTime, screenOnTime, timeNow);
-            service.reportEvent(event, getScreenOnTimeLocked(timeNow));
+            service.reportEvent(event, screenOnTime);
             // Inform listeners if necessary
             if ((event.mEventType == Event.MOVE_TO_FOREGROUND
                     || event.mEventType == Event.MOVE_TO_BACKGROUND
@@ -555,6 +582,7 @@
                     // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
                     mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                             /* idle = */ 0, event.mPackage));
+                    notifyBatteryStats(event.mPackage, userId, false);
                     mAppIdleHistory.addEntry(event.mPackage, userId, false, timeNow);
                 }
             }
@@ -586,6 +614,9 @@
                 // Slog.d(TAG, "Informing listeners of out-of-idle " + event.mPackage);
                 mHandler.sendMessage(mHandler.obtainMessage(MSG_INFORM_LISTENERS, userId,
                         /* idle = */ idle ? 1 : 0, packageName));
+                if (!idle) {
+                    notifyBatteryStats(packageName, userId, idle);
+                }
                 mAppIdleHistory.addEntry(packageName, userId, idle, timeNow);
             }
         }
@@ -660,19 +691,20 @@
         }
     }
 
-    private boolean isAppIdleUnfiltered(String packageName, int userId, long timeNow) {
+    private boolean isAppIdleUnfiltered(String packageName, UserUsageStatsService userService,
+            long timeNow, long screenOnTime) {
         synchronized (mLock) {
-            final long screenOnTime = getScreenOnTimeLocked(timeNow);
-            final UserUsageStatsService service =
-                    getUserDataAndInitializeIfNeededLocked(userId, timeNow);
-            long beginIdleTime = service.getBeginIdleTime(packageName);
-            long lastUsedTime = service.getSystemLastUsedTime(packageName);
-            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime, timeNow);
+            long beginIdleTime = userService.getBeginIdleTime(packageName);
+            long lastUsedTime = userService.getSystemLastUsedTime(packageName);
+            return hasPassedIdleTimeoutLocked(beginIdleTime, lastUsedTime, screenOnTime,
+                    timeNow);
         }
     }
 
     /**
-     * @param timestamp when the app was last used in device usage timebase
+     * @param beginIdleTime when the app was last used in device usage timebase
+     * @param lastUsedTime wallclock time of when the app was last used
+     * @param screenOnTime screen-on timebase time
      * @param currentTime current time in device usage timebase
      * @return whether it's been used far enough in the past to be considered inactive
      */
@@ -696,18 +728,29 @@
         }
     }
 
+    boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
+        final UserUsageStatsService userService;
+        final long screenOnTime;
+        synchronized (mLock) {
+            if (timeNow == -1) {
+                timeNow = checkAndGetTimeLocked();
+            }
+            userService = getUserDataAndInitializeIfNeededLocked(userId, timeNow);
+            screenOnTime = getScreenOnTimeLocked(timeNow);
+        }
+        return isAppIdleFiltered(packageName, userId, userService, timeNow, screenOnTime);
+    }
+
     /**
      * Checks if an app has been idle for a while and filters out apps that are excluded.
      * It returns false if the current system state allows all apps to be considered active.
      * This happens if the device is plugged in or temporarily allowed to make exceptions.
      * Called by interface impls.
      */
-    boolean isAppIdleFiltered(String packageName, int userId, long timeNow) {
+    private boolean isAppIdleFiltered(String packageName, int userId,
+            UserUsageStatsService userService, long timeNow, long screenOnTime) {
         if (packageName == null) return false;
         synchronized (mLock) {
-            if (timeNow == -1) {
-                timeNow = checkAndGetTimeLocked();
-            }
             // Temporary exemption, probably due to device charging or occasional allowance to
             // be allowed to sync, etc.
             if (mAppIdleParoled) {
@@ -735,7 +778,7 @@
             return false;
         }
 
-        return isAppIdleUnfiltered(packageName, userId, timeNow);
+        return isAppIdleUnfiltered(packageName, userService, timeNow, screenOnTime);
     }
 
     void setAppIdle(String packageName, boolean idle, int userId) {
@@ -844,7 +887,7 @@
                     break;
 
                 case MSG_CHECK_IDLE_STATES:
-                    checkIdleStates();
+                    checkIdleStates(msg.arg1);
                     break;
 
                 case MSG_CHECK_PAROLE_TIMEOUT:
@@ -884,7 +927,7 @@
                     UserHandle.USER_OWNER);
             mCheckIdleIntervalMillis = Math.min(DEFAULT_CHECK_IDLE_INTERVAL,
                     mAppIdleDurationMillis / 4);
-            postCheckIdleStates();
+            postCheckIdleStates(UserHandle.USER_ALL);
         }
     }
 
diff --git a/telecomm/java/android/telecom/Call.java b/telecomm/java/android/telecom/Call.java
index a2e0706..e756a57 100644
--- a/telecomm/java/android/telecom/Call.java
+++ b/telecomm/java/android/telecom/Call.java
@@ -380,7 +380,7 @@
                 builder.append(" PROPERTY_HIGH_DEF_AUDIO");
             }
             if (hasProperty(properties, PROPERTY_EMERGENCY_CALLBACK_MODE)) {
-                builder.append(" EMERGENCY_CALLBACK_MODE");
+                builder.append(" PROPERTY_EMERGENCY_CALLBACK_MODE");
             }
             builder.append("]");
             return builder.toString();
diff --git a/telecomm/java/android/telecom/Connection.java b/telecomm/java/android/telecom/Connection.java
index 9a63aa3..91566f8 100644
--- a/telecomm/java/android/telecom/Connection.java
+++ b/telecomm/java/android/telecom/Connection.java
@@ -448,8 +448,13 @@
 
         /**
          * Stores a list of the video callbacks, keyed by IBinder.
+         *
+         * ConcurrentHashMap constructor params: 8 is initial table size, 0.9f is
+         * load factor before resizing, 1 means we only expect a single thread to
+         * access the map so make only a single shard
          */
-        private HashMap<IBinder, IVideoCallback> mVideoCallbacks = new HashMap<>();
+        private ConcurrentHashMap<IBinder, IVideoCallback> mVideoCallbacks =
+                new ConcurrentHashMap<IBinder, IVideoCallback>(8, 0.9f, 1);
 
         /**
          * Default handler used to consolidate binder method calls onto a single thread.
@@ -470,12 +475,16 @@
                         IBinder binder = (IBinder) msg.obj;
                         IVideoCallback callback = IVideoCallback.Stub
                                 .asInterface((IBinder) msg.obj);
+                        if (callback == null) {
+                            Log.w(this, "addVideoProvider - skipped; callback is null.");
+                            break;
+                        }
+
                         if (mVideoCallbacks.containsKey(binder)) {
                             Log.i(this, "addVideoProvider - skipped; already present.");
                             break;
                         }
                         mVideoCallbacks.put(binder, callback);
-                        Log.i(this, "addVideoProvider  "+ mVideoCallbacks.size());
                         break;
                     }
                     case MSG_REMOVE_VIDEO_CALLBACK: {
@@ -594,7 +603,7 @@
 
         public VideoProvider() {
             mBinder = new VideoProvider.VideoProviderBinder();
-            mMessageHandler = new VideoProvider.VideoProviderHandler();
+            mMessageHandler = new VideoProvider.VideoProviderHandler(Looper.getMainLooper());
         }
 
         /**
@@ -763,11 +772,12 @@
          */
         public void receiveSessionModifyRequest(VideoProfile videoProfile) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.receiveSessionModifyRequest(videoProfile);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "receiveSessionModifyRequest callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
@@ -793,12 +803,13 @@
         public void receiveSessionModifyResponse(int status,
                 VideoProfile requestedProfile, VideoProfile responseProfile) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.receiveSessionModifyResponse(status, requestedProfile,
                                 responseProfile);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "receiveSessionModifyResponse callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
@@ -819,11 +830,12 @@
          */
         public void handleCallSessionEvent(int event) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.handleCallSessionEvent(event);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "handleCallSessionEvent callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
@@ -843,11 +855,12 @@
          */
         public void changePeerDimensions(int width, int height) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.changePeerDimensions(width, height);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "changePeerDimensions callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
@@ -869,11 +882,12 @@
          */
         public void setCallDataUsage(long dataUsage) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.changeCallDataUsage(dataUsage);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "setCallDataUsage callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
@@ -905,11 +919,12 @@
          */
         public void changeCameraCapabilities(VideoProfile.CameraCapabilities cameraCapabilities) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.changeCameraCapabilities(cameraCapabilities);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "changeCameraCapabilities callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
@@ -929,11 +944,12 @@
          */
         public void changeVideoQuality(int videoQuality) {
             if (mVideoCallbacks != null) {
-                try {
-                    for (IVideoCallback callback : mVideoCallbacks.values()) {
+                for (IVideoCallback callback : mVideoCallbacks.values()) {
+                    try {
                         callback.changeVideoQuality(videoQuality);
+                    } catch (RemoteException ignored) {
+                        Log.w(this, "changeVideoQuality callback failed", ignored);
                     }
-                } catch (RemoteException ignored) {
                 }
             }
         }
diff --git a/tests/ActivityTests/AndroidManifest.xml b/tests/ActivityTests/AndroidManifest.xml
index c105491..dae7cc5 100644
--- a/tests/ActivityTests/AndroidManifest.xml
+++ b/tests/ActivityTests/AndroidManifest.xml
@@ -76,5 +76,6 @@
             android:authorities="com.google.android.test.activity.single_user"
             android:singleUser="true" android:exported="true" />
         <receiver android:name="TrackTimeReceiver" />
+        <receiver android:name="AlarmSpamReceiver" />
     </application>
 </manifest>
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
index ddcfd9e..94cbabf 100644
--- a/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
+++ b/tests/ActivityTests/src/com/google/android/test/activity/ActivityTestMain.java
@@ -22,6 +22,7 @@
 import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
+import android.app.AlarmManager;
 import android.app.AlertDialog;
 import android.app.PendingIntent;
 import android.content.ActivityNotFoundException;
@@ -36,6 +37,7 @@
 import android.os.IBinder;
 import android.os.Message;
 import android.os.RemoteException;
+import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.graphics.Bitmap;
@@ -58,6 +60,7 @@
     static final String KEY_CONFIGURATION = "configuration";
 
     ActivityManager mAm;
+    AlarmManager mAlarm;
     Configuration mOverrideConfig;
     int mSecondUser;
 
@@ -66,6 +69,7 @@
     ServiceConnection mIsolatedConnection;
 
     static final int MSG_SPAM = 1;
+    static final int MSG_SPAM_ALARM = 2;
 
     final Handler mHandler = new Handler() {
         @Override
@@ -82,6 +86,15 @@
                     startActivity(intent, options);
                     scheduleSpam(!fg);
                 } break;
+                case MSG_SPAM_ALARM: {
+                    long when = SystemClock.elapsedRealtime();
+                    Intent intent = new Intent(ActivityTestMain.this, AlarmSpamReceiver.class);
+                    intent.setAction("com.example.SPAM_ALARM=" + when);
+                    PendingIntent pi = PendingIntent.getBroadcast(ActivityTestMain.this,
+                            0, intent, 0);
+                    mAlarm.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME, when+(30*1000), pi);
+                    scheduleSpamAlarm(30*1000);
+                } break;
             }
             super.handleMessage(msg);
         }
@@ -146,6 +159,7 @@
         Log.i(TAG, "Referrer: " + getReferrer());
 
         mAm = (ActivityManager)getSystemService(ACTIVITY_SERVICE);
+        mAlarm = (AlarmManager)getSystemService(ALARM_SERVICE);
         if (savedInstanceState != null) {
             mOverrideConfig = savedInstanceState.getParcelable(KEY_CONFIGURATION);
             if (mOverrideConfig != null) {
@@ -436,6 +450,13 @@
                 return true;
             }
         });
+        menu.add("Spam idle alarm").setOnMenuItemClickListener(
+                new MenuItem.OnMenuItemClickListener() {
+            @Override public boolean onMenuItemClick(MenuItem item) {
+                scheduleSpamAlarm(0);
+                return true;
+            }
+        });
         return true;
     }
 
@@ -467,6 +488,7 @@
     @Override
     protected void onStop() {
         super.onStop();
+        mHandler.removeMessages(MSG_SPAM_ALARM);
         for (ServiceConnection conn : mConnections) {
             unbindService(conn);
         }
@@ -536,6 +558,12 @@
         mHandler.sendMessageDelayed(msg, 500);
     }
 
+    void scheduleSpamAlarm(long delay) {
+        mHandler.removeMessages(MSG_SPAM_ALARM);
+        Message msg = mHandler.obtainMessage(MSG_SPAM_ALARM);
+        mHandler.sendMessageDelayed(msg, delay);
+    }
+
     private View scrollWrap(View view) {
         ScrollView scroller = new ScrollView(this);
         scroller.addView(view, new ScrollView.LayoutParams(ScrollView.LayoutParams.MATCH_PARENT,
diff --git a/tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java b/tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java
new file mode 100644
index 0000000..0cb1ffb
--- /dev/null
+++ b/tests/ActivityTests/src/com/google/android/test/activity/AlarmSpamReceiver.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 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 com.google.android.test.activity;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.UserHandle;
+import android.util.Log;
+
+public class AlarmSpamReceiver extends BroadcastReceiver {
+    @Override
+    public void onReceive(Context context, Intent intent) {
+        Log.i("AlarmSpamReceiver", "Received spam = " + intent);
+    }
+}
diff --git a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
index 947ea78..2e51570 100644
--- a/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
+++ b/tests/FixVibrateSetting/src/com/android/fixvibratesetting/FixVibrateSetting.java
@@ -109,14 +109,20 @@
     }
 
     private void test() {
-        Notification n = new Notification(R.drawable.stat_sys_warning, "Test notification",
-                        System.currentTimeMillis());
         Intent intent = new Intent(this, FixVibrateSetting.class);
         PendingIntent pending = PendingIntent.getActivity(this, 0, intent, 0);
-        n.setLatestEventInfo(this, "Test notification", "Test notification", pending);
 
-        n.vibrate = new long[] { 0, 700, 500, 1000 };
-        n.flags |= Notification.FLAG_AUTO_CANCEL;
+        Notification n = new Notification.Builder(this)
+                .setSmallIcon(R.drawable.stat_sys_warning)
+                .setTicker("Test notification")
+                .setWhen(System.currentTimeMillis())
+                .setContentTitle("Test notification")
+                .setContentText("Test notification")
+                .setContentIntent(pending)
+                .setVibrate(new long[] { 0, 700, 500, 1000 })
+                .setAutoCancel(true)
+                .build();
+
         mNotificationManager.notify(1, n);
     }
 }
diff --git a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
index 7691e64..fc3f390 100644
--- a/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
+++ b/tests/FrameworkPerf/src/com/android/frameworkperf/SchedulerService.java
@@ -26,15 +26,18 @@
 
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        Notification status = new Notification(R.drawable.stat_happy, null,
-                System.currentTimeMillis());
-        status.flags |= Notification.FLAG_ONGOING_EVENT;
-        status.setLatestEventInfo(this, "Scheduler Test running",
-                "Scheduler Test running", PendingIntent.getActivity(this, 0,
-                    new Intent(this, FrameworkPerfActivity.class)
-                    .setAction(Intent.ACTION_MAIN)
-                    .addCategory(Intent.CATEGORY_LAUNCHER)
-                    .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0));
+        Notification status = new Notification.Builder(this)
+                .setSmallIcon(R.drawable.stat_happy)
+                .setWhen(System.currentTimeMillis())
+                .setContentTitle("Scheduler Test running")
+                .setContentText("Scheduler Test running")
+                .setContentIntent(PendingIntent.getActivity(this, 0,
+                        new Intent(this, FrameworkPerfActivity.class)
+                                .setAction(Intent.ACTION_MAIN)
+                                .addCategory(Intent.CATEGORY_LAUNCHER)
+                                .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK), 0))
+                .setOngoing(true)
+                .build();
         startForeground(1, status);
         return START_STICKY;
     }
diff --git a/tests/StatusBar/res/drawable-hdpi/stat_sys_warning.png b/tests/StatusBar/res/drawable-hdpi/stat_sys_warning.png
new file mode 100644
index 0000000..dbaf944
--- /dev/null
+++ b/tests/StatusBar/res/drawable-hdpi/stat_sys_warning.png
Binary files differ
diff --git a/tests/StatusBar/res/drawable-mdpi/stat_sys_warning.png b/tests/StatusBar/res/drawable-mdpi/stat_sys_warning.png
new file mode 100644
index 0000000..168f8f6
--- /dev/null
+++ b/tests/StatusBar/res/drawable-mdpi/stat_sys_warning.png
Binary files differ
diff --git a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
index ba160b18..67b9d77 100644
--- a/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
+++ b/tests/StatusBar/src/com/android/statusbartest/NotificationTestList.java
@@ -25,7 +25,6 @@
 import android.graphics.Bitmap;
 import android.graphics.drawable.BitmapDrawable;
 import android.os.Bundle;
-import android.os.Environment;
 import android.os.Vibrator;
 import android.os.Handler;
 import android.os.UserHandle;
@@ -85,7 +84,7 @@
     }
 
     private Test[] mTests = new Test[] {
-        new Test("Off and sound") {
+        new Test("Off") {
             public void run() {
                 PowerManager pm = (PowerManager)NotificationTestList.this.getSystemService(Context.POWER_SERVICE);
                 PowerManager.WakeLock wl = 
@@ -94,9 +93,12 @@
 
                 pm.goToSleep(SystemClock.uptimeMillis());
 
-                Notification n = new Notification();
-                n.sound = Uri.parse("file://" + Environment.getExternalStorageDirectory() +
-                        "/virtual-void.mp3");
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.stat_sys_phone)
+                        .setContentTitle(name)
+                        .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                                        getPackageName() + "/raw/ringer"))
+                        .build();
                 Log.d(TAG, "n.sound=" + n.sound);
 
                 mNM.notify(1, n);
@@ -114,122 +116,120 @@
             }
         },
 
-        new Test("Button") {
+        new Test("Custom Button") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon1, null,
-                        mActivityCreateTime);
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setOngoing(true)
+                        .build();
                 n.contentView = new RemoteViews(getPackageName(), R.layout.button_notification);
-                n.flags |= Notification.FLAG_ONGOING_EVENT;
-                n.contentIntent = makeIntent();
                 n.contentView.setOnClickPendingIntent(R.id.button, makeIntent2());
 
                 mNM.notify(1, n);
             }
         },
 
-        new Test("custom intent on text view") {
+        new Test("Action Button") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon1, null,
-                        mActivityCreateTime);
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is a notification!!!", null);
-                n.contentView.setOnClickPendingIntent(com.android.internal.R.id.text,
-                        makeIntent2());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setOngoing(true)
+                        .addAction(R.drawable.ic_statusbar_chat, "Button", makeIntent2())
+                        .build();
+
                 mNM.notify(1, n);
             }
         },
 
-        new Test("Ticker 1 line") {
+        new Test("with intent") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon1, "tick tick tick",
-                        mActivityCreateTime);
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is a notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle("Persistent #1")
+                        .setContentText("This is a notification!!!")
+                        .setContentIntent(makeIntent2())
+                        .setOngoing(true)
+                        .build();
+
                 mNM.notify(1, n);
             }
         },
 
-        new Test("No view") {
-            public void run() {
-                Notification n = new Notification(R.drawable.icon1, "No view",
-                        System.currentTimeMillis());
-                mNM.notify(1, n);
-            }
-        },
-
-        new Test("No intent") {
-            public void run() {
-                Notification n = new Notification(R.drawable.icon1, "No intent",
-                        System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "No intent",
-                            "No intent", null);
-                mNM.notify(1, n);
-            }
-        },
-
-        new Test("Layout") {
+        new Test("Whens") {
             public void run()
             {
-                Notification n;
+                Notification.Builder n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setContentTitle(name)
+                        .setOngoing(true);
 
-                n = new Notification(NotificationTestList.this,
-                            R.drawable.ic_statusbar_missedcall,
-                            null, System.currentTimeMillis()-(1000*60*60*24),
-                            "(453) 123-2328",
-                            "", null);
-                n.flags |= Notification.FLAG_ONGOING_EVENT;
+                mNM.notify(1, n.setContentTitle("(453) 123-2328")
+                .setWhen(System.currentTimeMillis()-(1000*60*60*24))
+                .build());
 
-                mNM.notify(1, n);
+                mNM.notify(1, n.setContentTitle("Mark Willem, Me (2)")
+                .setWhen(System.currentTimeMillis())
+                .build());
 
-                mNM.notify(2, new Notification(NotificationTestList.this,
-                            R.drawable.ic_statusbar_email,
-                            null, System.currentTimeMillis(),
-                            "Mark Willem, Me (2)",
-                            "Re: Didn't you get the memo?", null));
-
-                mNM.notify(3, new Notification(NotificationTestList.this,
-                            R.drawable.ic_statusbar_chat,
-                            null, System.currentTimeMillis()+(1000*60*60*24),
-                            "Sophia Winterlanden",
-                            "Lorem ipsum dolor sit amet.", null));
+                mNM.notify(1, n.setContentTitle("Sophia Winterlanden")
+                        .setWhen(System.currentTimeMillis() + (1000 * 60 * 60 * 24))
+                        .build());
             }
         },
 
         new Test("Bad Icon #1 (when=create)") {
             public void run() {
-                Notification n = new Notification(R.layout.chrono_notification /* not an icon */,
-                        null, mActivityCreateTime);
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is the same notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.layout.chrono_notification /* not an icon */)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle("Persistent #1")
+                        .setContentText("This is the same notification!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(1, n);
             }
         },
 
         new Test("Bad Icon #1 (when=now)") {
             public void run() {
-                Notification n = new Notification(R.layout.chrono_notification /* not an icon */,
-                        null, System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is the same notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.layout.chrono_notification /* not an icon */)
+                        .setWhen(System.currentTimeMillis())
+                        .setContentTitle("Persistent #1")
+                        .setContentText("This is the same notification!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(1, n);
             }
         },
 
         new Test("Null Icon #1 (when=now)") {
             public void run() {
-                Notification n = new Notification(0, null, System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is the same notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(0)
+                        .setWhen(System.currentTimeMillis())
+                        .setContentTitle("Persistent #1")
+                        .setContentText("This is the same notification!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(1, n);
             }
         },
 
         new Test("Bad resource #1 (when=create)") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2,
-                        null, mActivityCreateTime);
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is the same notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle("Persistent #1")
+                        .setContentText("This is the same notification!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 n.contentView.setInt(1 /*bogus*/, "bogus method", 666);
                 mNM.notify(1, n);
             }
@@ -237,29 +237,18 @@
 
         new Test("Bad resource #1 (when=now)") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2,
-                        null, System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is the same notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setWhen(System.currentTimeMillis())
+                        .setContentTitle("Persistent #1")
+                        .setContentText("This is the same notification!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 n.contentView.setInt(1 /*bogus*/, "bogus method", 666);
                 mNM.notify(1, n);
             }
         },
 
-
-        new Test("Bad resource #3") {
-            public void run()
-            {
-                Notification n = new Notification(NotificationTestList.this,
-                            R.drawable.ic_statusbar_missedcall,
-                            null, System.currentTimeMillis()-(1000*60*60*24),
-                            "(453) 123-2328",
-                            "", null);
-                n.contentView.setInt(1 /*bogus*/, "bogus method", 666);
-                mNM.notify(3, n);
-            }
-        },
-
         new Test("Times") {
             public void run()
             {
@@ -278,22 +267,25 @@
                 new Runnable() {
                     public void run() {
                         Log.d(TAG, "Stress - Ongoing/Latest 0");
-                        Notification n = new Notification(NotificationTestList.this,
-                                R.drawable.icon3,
-                                null, System.currentTimeMillis(), "Stress - Ongoing",
-                                "Notify me!!!", null);
-                        n.flags |= Notification.FLAG_ONGOING_EVENT;
+                        Notification n = new Notification.Builder(NotificationTestList.this)
+                                .setSmallIcon(R.drawable.icon3)
+                                .setWhen(System.currentTimeMillis())
+                                .setContentTitle("Stress - Ongoing")
+                                .setContentText("Notify me!!!")
+                                .setOngoing(true)
+                                .build();
                         mNM.notify(1, n);
                     }
                 },
                 new Runnable() {
                     public void run() {
                         Log.d(TAG, "Stress - Ongoing/Latest 1");
-                        Notification n = new Notification(NotificationTestList.this,
-                                R.drawable.icon4,
-                                null, System.currentTimeMillis(), "Stress - Latest",
-                                "Notify me!!!", null);
-                        //n.flags |= Notification.FLAG_ONGOING_EVENT;
+                        Notification n = new Notification.Builder(NotificationTestList.this)
+                                .setSmallIcon(R.drawable.icon4)
+                                .setWhen(System.currentTimeMillis())
+                                .setContentTitle("Stress - Latest")
+                                .setContentText("Notify me!!!")
+                                .build();
                         mNM.notify(1, n);
                     }
                 }
@@ -302,12 +294,15 @@
         new Test("Long") {
             public void run()
             {
-                Notification n = new Notification();
-                n.defaults |= Notification.DEFAULT_SOUND ;
-                n.vibrate = new long[] {
-                        300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
-                        300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 
-                        300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 };
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setContentTitle(name)
+                        .setDefaults(Notification.DEFAULT_SOUND)
+                        .setVibrate(new long[] {
+                                300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+                                300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400,
+                                300, 400, 300, 400, 300, 400, 300, 400, 300, 400, 300, 400 })
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -320,21 +315,19 @@
                 Thread t = new Thread() {
                     public void run() {
                         int x = 0;
+                        final Notification.Builder n = new Notification.Builder(NotificationTestList.this)
+                                .setSmallIcon(R.drawable.icon1)
+                                .setContentTitle(name)
+                                .setOngoing(true);
+
                         while (!mProgressDone) {
-                            Notification n = new Notification(R.drawable.icon1, null,
-                                    PROGRESS_UPDATES_WHEN
+                            n.setWhen(PROGRESS_UPDATES_WHEN
                                     ? System.currentTimeMillis()
                                     : mActivityCreateTime);
-                            RemoteViews v = new RemoteViews(getPackageName(),
-                                    R.layout.progress_notification);
-                            
-                            v.setProgressBar(R.id.progress_bar, 100, x, false);
-                            v.setTextViewText(R.id.status_text, "Progress: " + x + "%");
-                    
-                            n.contentView = v;
-                            n.flags |= Notification.FLAG_ONGOING_EVENT;
+                            n.setProgress(100, x, false);
+                            n.setContentText("Progress: " + x + "%");
 
-                            mNM.notify(500, n);
+                            mNM.notify(500, n.build());
                             x = (x + 7) % 100;
 
                             try {
@@ -359,11 +352,12 @@
         new Test("Blue Lights") {
             public void run()
             {
-                Notification n = new Notification();
-                n.flags |= Notification.FLAG_SHOW_LIGHTS;
-                n.ledARGB = 0xff0000ff;
-                n.ledOnMS = 1;
-                n.ledOffMS = 0;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setLights(0xff0000ff, 1, 0)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -371,11 +365,12 @@
         new Test("Red Lights") {
             public void run()
             {
-                Notification n = new Notification();
-                n.flags |= Notification.FLAG_SHOW_LIGHTS;
-                n.ledARGB = 0xffff0000;
-                n.ledOnMS = 1;
-                n.ledOffMS = 0;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setLights(0xffff0000, 1, 0)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -383,11 +378,12 @@
         new Test("Yellow Lights") {
             public void run()
             {
-                Notification n = new Notification();
-                n.flags |= Notification.FLAG_SHOW_LIGHTS;
-                n.ledARGB = 0xffffff00;
-                n.ledOnMS = 1;
-                n.ledOffMS = 0;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setLights(0xffffff00, 1, 0)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -395,11 +391,12 @@
         new Test("Lights off") {
             public void run()
             {
-                Notification n = new Notification();
-                n.flags |= Notification.FLAG_SHOW_LIGHTS;
-                n.ledARGB = 0x00000000;
-                n.ledOnMS = 0;
-                n.ledOffMS = 0;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setLights(0x00000000, 0, 0)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -407,11 +404,12 @@
         new Test("Blue Blinking Slow") {
             public void run()
             {
-                Notification n = new Notification();
-                n.flags |= Notification.FLAG_SHOW_LIGHTS;
-                n.ledARGB = 0xff0000ff;
-                n.ledOnMS = 1300;
-                n.ledOffMS = 1300;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setLights(0xff0000ff, 1300, 1300)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -419,11 +417,12 @@
         new Test("Blue Blinking Fast") {
             public void run()
             {
-                Notification n = new Notification();
-                n.flags |= Notification.FLAG_SHOW_LIGHTS;
-                n.ledARGB = 0xff0000ff;
-                n.ledOnMS = 300;
-                n.ledOffMS = 300;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setLights(0xff0000ff, 300, 300)
+                        .setDefaults(Notification.DEFAULT_LIGHTS)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -431,8 +430,11 @@
         new Test("Default All") {
             public void run()
             {
-                Notification n = new Notification();
-                n.defaults |= Notification.DEFAULT_ALL;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setDefaults(Notification.DEFAULT_ALL)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -440,20 +442,12 @@
         new Test("Default All, once") {
             public void run()
             {
-                Notification n = new Notification();
-                n.defaults |= Notification.DEFAULT_ALL;
-                n.flags |= Notification.FLAG_ONLY_ALERT_ONCE ;
-                mNM.notify(1, n);
-            }
-        },
-
-        new Test("Content Sound") {
-            public void run()
-            {
-                Notification n = new Notification();
-                n.sound = Uri.parse(
-                        "content://media/internal/audio/media/7");
-
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setContentTitle(name)
+                        .setOnlyAlertOnce(true)
+                        .setDefaults(Notification.DEFAULT_ALL)
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -461,10 +455,12 @@
         new Test("Resource Sound") {
             public void run()
             {
-                Notification n = new Notification();
-                n.sound = Uri.parse(
-                        ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
-                        getPackageName() + "/raw/ringer");
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.stat_sys_phone)
+                        .setContentTitle(name)
+                        .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                                getPackageName() + "/raw/ringer"))
+                        .build();
                 Log.d(TAG, "n.sound=" + n.sound);
 
                 mNM.notify(1, n);
@@ -474,9 +470,13 @@
         new Test("Sound and Cancel") {
             public void run()
             {
-                Notification n = new Notification();
-                n.sound = Uri.parse(
-                            "content://media/internal/audio/media/7");
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.stat_sys_phone)
+                        .setContentTitle(name)
+                        .setSound(Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" +
+                                getPackageName() + "/raw/ringer"))
+                        .build();
+                Log.d(TAG, "n.sound=" + n.sound);
 
                 mNM.notify(1, n);
                 SystemClock.sleep(200);
@@ -487,8 +487,11 @@
         new Test("Vibrate") {
             public void run()
             {
-                Notification n = new Notification();
-                    n.vibrate = new long[] { 0, 700, 500, 1000 };
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.stat_sys_phone)
+                        .setContentTitle(name)
+                        .setVibrate(new long[]{0, 700, 500, 1000})
+                        .build();
 
                 mNM.notify(1, n);
             }
@@ -497,8 +500,11 @@
         new Test("Vibrate and cancel") {
             public void run()
             {
-                Notification n = new Notification();
-                    n.vibrate = new long[] { 0, 700, 500, 1000 };
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.stat_sys_phone)
+                        .setContentTitle(name)
+                        .setVibrate(new long[]{0, 700, 500, 1000})
+                        .build();
 
                 mNM.notify(1, n);
                 SystemClock.sleep(500);
@@ -566,10 +572,13 @@
 
         new Test("Persistent #1") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon1, "tick tick tick",
-                        mActivityCreateTime);
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is a notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setContentText("This is a notification!!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(1, n);
             }
         },
@@ -578,18 +587,19 @@
             public void run() {
                 mHandler.postDelayed(new Runnable() {
                             public void run() {
-                                Notification n = new Notification(R.drawable.icon1,
-                                        "            "
+                                String message = "            "
                                         + "tick tock tick tock\n\nSometimes notifications can "
                                         + "be really long and wrap to more than one line.\n"
                                         + "Sometimes."
                                         + "Ohandwhathappensifwehaveonereallylongstringarewesure"
-                                        + "thatwesegmentitcorrectly?\n",
-                                        System.currentTimeMillis());
-                                n.setLatestEventInfo(NotificationTestList.this,
-                                        "Still Persistent #1",
-                                        "This is still a notification!!!",
-                                        makeIntent());
+                                        + "thatwesegmentitcorrectly?\n";
+                                Notification n = new Notification.Builder(NotificationTestList.this)
+                                        .setSmallIcon(R.drawable.icon1)
+                                        .setContentTitle(name)
+                                        .setContentText("This is still a notification!!!")
+                                        .setContentIntent(makeIntent())
+                                        .setStyle(new Notification.BigTextStyle().bigText(message))
+                                        .build();
                                 mNM.notify(1, n);
                             }
                         }, 3000);
@@ -598,54 +608,67 @@
 
         new Test("Persistent #2") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2, "tock tock tock",
-                        System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #2",
-                            "Notify me!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setContentText("This is a notification!!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(2, n);
             }
         },
 
         new Test("Persistent #3") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2, "tock tock tock\nmooooo",
-                        System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #3",
-                            "Notify me!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setContentText("This is a notification!!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(3, n);
             }
         },
 
         new Test("Persistent #2 Vibrate") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2, "tock tock tock",
-                        System.currentTimeMillis());
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #2",
-                            "Notify me!!!", makeIntent());
-                n.defaults = Notification.DEFAULT_VIBRATE;
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setContentText("This is a notification!!!")
+                        .setContentIntent(makeIntent())
+                        .setDefaults(Notification.DEFAULT_VIBRATE)
+                        .build();
                 mNM.notify(2, n);
             }
         },
 
         new Test("Persistent #1 - different icon") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2, null,
-                        mActivityCreateTime);
-                n.setLatestEventInfo(NotificationTestList.this, "Persistent #1",
-                            "This is the same notification!!!", makeIntent());
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon2)
+                        .setWhen(mActivityCreateTime)
+                        .setContentTitle(name)
+                        .setContentText("This is a notification!!!")
+                        .setContentIntent(makeIntent())
+                        .build();
                 mNM.notify(1, n);
             }
         },
 
         new Test("Chronometer Start") {
             public void run() {
-                Notification n = new Notification(R.drawable.icon2, "me me me me",
-                                                    System.currentTimeMillis());
-                n.contentView = new RemoteViews(getPackageName(), R.layout.chrono_notification);
-                mChronometerBase = SystemClock.elapsedRealtime();
-                n.contentView.setChronometer(R.id.time, mChronometerBase, "Yay! (%s)", true);
-                n.flags |= Notification.FLAG_ONGOING_EVENT;
-                n.contentIntent = makeIntent();
+                Notification n = new Notification.Builder(NotificationTestList.this)
+                        .setSmallIcon(R.drawable.icon1)
+                        .setWhen(System.currentTimeMillis())
+                        .setContentTitle(name)
+                        .setContentIntent(makeIntent())
+                        .setOngoing(true)
+                        .setUsesChronometer(true)
+                        .build();
                 mNM.notify(2, n);
             }
         },
@@ -655,12 +678,12 @@
                 mHandler.postDelayed(new Runnable() {
                         public void run() {
                             Log.d(TAG, "Chronometer Stop");
-                            Notification n = new Notification();
-                            n.icon = R.drawable.icon1;
-                            n.contentView = new RemoteViews(getPackageName(),
-                                                             R.layout.chrono_notification);
-                            n.contentView.setChronometer(R.id.time, mChronometerBase, null, false);
-                            n.contentIntent = makeIntent();
+                            Notification n = new Notification.Builder(NotificationTestList.this)
+                                    .setSmallIcon(R.drawable.icon1)
+                                    .setWhen(System.currentTimeMillis())
+                                    .setContentTitle(name)
+                                    .setContentIntent(makeIntent())
+                                    .build();
                             mNM.notify(2, n);
                         }
                     }, 3000);
@@ -669,29 +692,29 @@
 
         new Test("Sequential Persistent") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(1));
-                mNM.notify(2, notificationWithNumbers(2));
+                mNM.notify(1, notificationWithNumbers(name, 1));
+                mNM.notify(2, notificationWithNumbers(name, 2));
             }
         },
 
         new Test("Replace Persistent") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(1));
-                mNM.notify(1, notificationWithNumbers(1));
+                mNM.notify(1, notificationWithNumbers(name, 1));
+                mNM.notify(1, notificationWithNumbers(name, 1));
             }
         },
 
         new Test("Run and Cancel (n=1)") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(1));
+                mNM.notify(1, notificationWithNumbers(name, 1));
                 mNM.cancel(1);
             }
         },
 
         new Test("Run an Cancel (n=2)") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(1));
-                mNM.notify(2, notificationWithNumbers(2));
+                mNM.notify(1, notificationWithNumbers(name, 1));
+                mNM.notify(2, notificationWithNumbers(name, 2));
                 mNM.cancel(2);
             }
         },
@@ -701,8 +724,8 @@
             public void run() {
                 for (int i = 0; i < 10; i++) {
                   Log.d(TAG, "Add two notifications");
-                  mNM.notify(1, notificationWithNumbers(1));
-                  mNM.notify(2, notificationWithNumbers(2));
+                  mNM.notify(1, notificationWithNumbers(name, 1));
+                  mNM.notify(2, notificationWithNumbers(name, 2));
                   Log.d(TAG, "Cancel two notifications");
                   mNM.cancel(1);
                   mNM.cancel(2);
@@ -712,29 +735,14 @@
 
         new Test("Ten Notifications") {
             public void run() {
-                for (int i = 0; i < 2; i++) {
-                    Notification n = new Notification(
-                            kNumberedIconResIDs[i],
-                            null, System.currentTimeMillis());
-                    n.number = i;
-                    n.setLatestEventInfo(
-                            NotificationTestList.this,
-                            "Persistent #" + i,
-                            "Notify me!!!" + i, 
-                            null);
-                    n.flags |= Notification.FLAG_ONGOING_EVENT;
-                    mNM.notify((i+1)*10, n);
-                }
-                for (int i = 2; i < 10; i++) {
-                    Notification n = new Notification(
-                            kNumberedIconResIDs[i],
-                            null, System.currentTimeMillis());
-                    n.number = i;
-                    n.setLatestEventInfo(
-                            NotificationTestList.this,
-                            "Persistent #" + i,
-                            "Notify me!!!" + i, 
-                            null);
+                for (int i = 0; i < 10; i++) {
+                    Notification n = new Notification.Builder(NotificationTestList.this)
+                            .setSmallIcon(kNumberedIconResIDs[i])
+                            .setContentTitle("Persistent #" + i)
+                            .setContentText("Notify me!!!" + i)
+                            .setOngoing(i < 2)
+                            .setNumber(i)
+                            .build();
                     mNM.notify((i+1)*10, n);
                 }
             }
@@ -757,25 +765,25 @@
         
         new Test("Persistent with numbers 1") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(1));
+                mNM.notify(1, notificationWithNumbers(name, 1));
             }
         },
 
         new Test("Persistent with numbers 22") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(22));
+                mNM.notify(1, notificationWithNumbers(name, 22));
             }
         },
 
         new Test("Persistent with numbers 333") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(333));
+                mNM.notify(1, notificationWithNumbers(name, 333));
             }
         },
 
         new Test("Persistent with numbers 4444") {
             public void run() {
-                mNM.notify(1, notificationWithNumbers(4444));
+                mNM.notify(1, notificationWithNumbers(name, 4444));
             }
         },
 
@@ -786,7 +794,7 @@
                     .setContentTitle("High priority")
                     .setContentText("This should appear before all others")
                     .setPriority(Notification.PRIORITY_HIGH)
-                    .getNotification();
+                    .build();
 
                 int[] idOut = new int[1];
                 try {
@@ -812,7 +820,7 @@
                     .setContentTitle("MAX priority")
                     .setContentText("This might appear as an intruder alert")
                     .setPriority(Notification.PRIORITY_MAX)
-                    .getNotification();
+                    .build();
 
                 int[] idOut = new int[1];
                 try {
@@ -838,7 +846,7 @@
                     .setContentTitle("MIN priority")
                     .setContentText("You should not see this")
                     .setPriority(Notification.PRIORITY_MIN)
-                    .getNotification();
+                    .build();
 
                 int[] idOut = new int[1];
                 try {
@@ -875,16 +883,15 @@
 
     };
 
-    private Notification notificationWithNumbers(int num) {
-        Notification n = new Notification(this,
-                (num >= 0 && num < kNumberedIconResIDs.length)
-                    ? kNumberedIconResIDs[num]
-                    : kUnnumberedIconResID,
-                null,
-                System.currentTimeMillis(),
-                "Notification", "Number=" + num,
-                null);
-        n.number = num;
+    private Notification notificationWithNumbers(String name, int num) {
+        Notification n = new Notification.Builder(NotificationTestList.this)
+                .setSmallIcon((num >= 0 && num < kNumberedIconResIDs.length)
+                        ? kNumberedIconResIDs[num]
+                        : kUnnumberedIconResID)
+                .setContentTitle(name)
+                .setContentText("Number=" + num)
+                .setNumber(num)
+                .build();
         return n;
     }
 
@@ -932,9 +939,12 @@
     }
 
     void timeNotification(int n, String label, long time) {
-        mNM.notify(n, new Notification(NotificationTestList.this,
-                    R.drawable.ic_statusbar_missedcall, null,
-                    time, label, "" + new java.util.Date(time), null));
+        mNM.notify(n, new Notification.Builder(NotificationTestList.this)
+                .setSmallIcon(R.drawable.ic_statusbar_missedcall)
+                .setWhen(time)
+                .setContentTitle(label)
+                .setContentText(new java.util.Date(time).toString())
+                .build());
 
     }
 
diff --git a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
index 50f98b8..cd04c2e 100644
--- a/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
+++ b/tests/StatusBar/src/com/android/statusbartest/StatusBarTest.java
@@ -153,25 +153,24 @@
         },
         new Test("Priority notification") {
             public void run() {
-                Notification not = new Notification();
-                not.icon = R.drawable.stat_sys_phone;
-                not.when = System.currentTimeMillis()-(1000*60*60*24);
-                not.setLatestEventInfo(StatusBarTest.this,
-                                "Incoming call",
-                                "from: Imperious Leader",
-                                null
-                                );
-                not.flags |= Notification.FLAG_HIGH_PRIORITY;
                 Intent fullScreenIntent = new Intent(StatusBarTest.this, TestAlertActivity.class);
                 int id = (int)System.currentTimeMillis(); // XXX HAX
                 fullScreenIntent.putExtra("id", id);
-                not.fullScreenIntent = PendingIntent.getActivity(
+                PendingIntent pi = PendingIntent.getActivity(
                     StatusBarTest.this,
                     0,
                     fullScreenIntent,
                     PendingIntent.FLAG_CANCEL_CURRENT);
-                // if you tap on it you should get the original alert box
-                not.contentIntent = not.fullScreenIntent;
+                Notification not = new Notification.Builder(StatusBarTest.this)
+                        .setSmallIcon(R.drawable.stat_sys_phone)
+                        .setWhen(System.currentTimeMillis() - (1000 * 60 * 60 * 24))
+                        .setContentTitle("Incoming call")
+                        .setContentText("from: Imperious Leader")
+                        .setContentIntent(pi)
+                        .setFullScreenIntent(pi, true)
+                        .setPriority(Notification.PRIORITY_HIGH)
+                        .build();
+
                 mNotificationManager.notify(id, not);
             }
         },