Merge "Update Javadocs to reflect meaning of digest and padding NONE." into mnc-dev
diff --git a/api/current.txt b/api/current.txt
index 43c1ade9..3e0a1b3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -176,6 +176,7 @@
     field public static final java.lang.String SENSORS = "android.permission-group.SENSORS";
     field public static final java.lang.String SMS = "android.permission-group.SMS";
     field public static final java.lang.String SOCIAL_INFO = "android.permission-group.SOCIAL_INFO";
+    field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
     field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
   }
 
@@ -3999,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);
@@ -4057,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();
@@ -5808,19 +5811,19 @@
     field public static final java.lang.String EXTRA_DEVICE_ADMIN = "android.app.extra.DEVICE_ADMIN";
     field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
     field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
     field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
@@ -8456,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
   }
@@ -37053,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 2345ef6..a61b9fb53 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -250,6 +250,7 @@
     field public static final java.lang.String SENSORS = "android.permission-group.SENSORS";
     field public static final java.lang.String SMS = "android.permission-group.SMS";
     field public static final java.lang.String SOCIAL_INFO = "android.permission-group.SOCIAL_INFO";
+    field public static final java.lang.String STORAGE = "android.permission-group.STORAGE";
     field public static final java.lang.String USER_DICTIONARY = "android.permission-group.USER_DICTIONARY";
   }
 
@@ -4095,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);
@@ -4153,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();
@@ -5920,19 +5923,19 @@
     field public static final java.lang.String EXTRA_PROFILE_OWNER_NAME = "android.app.extra.PROFILE_OWNER_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_ACCOUNT_TO_MIGRATE = "android.app.extra.PROVISIONING_ACCOUNT_TO_MIGRATE";
     field public static final java.lang.String EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE = "android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_ADMIN_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION";
     field public static final deprecated java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_NAME";
-    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_COMPONENT_NAME";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_MINIMUM_VERSION_CODE";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_COOKIE_HEADER";
     field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION";
+    field public static final java.lang.String EXTRA_PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM";
     field public static final java.lang.String EXTRA_PROVISIONING_EMAIL_ADDRESS = "android.app.extra.PROVISIONING_EMAIL_ADDRESS";
     field public static final java.lang.String EXTRA_PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED = "android.app.extra.PROVISIONING_LEAVE_ALL_SYSTEM_APPS_ENABLED";
     field public static final java.lang.String EXTRA_PROVISIONING_LOCALE = "android.app.extra.PROVISIONING_LOCALE";
@@ -8688,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
   }
@@ -39330,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 996748a..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";
@@ -400,7 +406,7 @@
      * A String extra holding the URL-safe base64 encoded SHA-1 checksum of the file at download
      * location specified in {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
-     * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM} should be
+     * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM} should be
      * present. The provided checksum should match the checksum of the file at the download
      * location. If the checksum doesn't match an error will be shown to the user and the user will
      * be asked to factory reset the device.
@@ -412,24 +418,24 @@
         = "android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any certificate of the
+     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
      * android package archive at the download location specified in {@link
      * #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION}.
      *
-     * <p>The certificates of an android package archive can be obtained using
+     * <p>The signatures of an android package archive can be obtained using
      * {@link android.content.pm.PackageManager#getPackageArchiveInfo} with flag
      * {@link android.content.pm.PackageManager#GET_SIGNATURES}.
      *
      * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM} should be
-     * present. The provided checksum should match the checksum of any certificate of the file at
+     * present. The provided checksum should match the checksum of any signature of the file at
      * the download location. If the checksum does not match an error will be shown to the user and
      * the user will be asked to factory reset the device.
      *
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC} that starts device owner
      * provisioning via an NFC bump.
      */
-    public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM
-        = "android.app.extra.PROVISIONING_DEVICE_ADMIN_CERTIFICATE_CHECKSUM";
+    public static final String EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM
+        = "android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM";
 
     /**
      * Broadcast Action: This broadcast is sent to indicate that provisioning of a managed profile
@@ -508,7 +514,7 @@
      * location specified in
      * {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
-     * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM}
+     * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM}
      * should be present. The provided checksum should match the checksum of the file at the
      * download location. If the checksum doesn't match an error will be shown to the user and the
      * user will be asked to factory reset the device.
@@ -520,24 +526,24 @@
         = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM";
 
     /**
-     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any certificate of the
+     * A String extra holding the URL-safe base64 encoded SHA-1 checksum of any signature of the
      * android package archive at the download location specified in {@link
      * #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_DOWNLOAD_LOCATION}.
      *
-     * <p>The certificates of an android package archive can be obtained using
+     * <p>The signatures of an android package archive can be obtained using
      * {@link android.content.pm.PackageManager#getPackageArchiveInfo} with flag
      * {@link android.content.pm.PackageManager#GET_SIGNATURES}.
      *
      * <p>Either this extra or {@link #EXTRA_PROVISIONING_DEVICE_INITIALIZER_PACKAGE_CHECKSUM}
-     * should be present. The provided checksum should match the checksum of any certificate of the
+     * should be present. The provided checksum should match the checksum of any signature of the
      * file at the download location. If the checksum doesn't match an error will be shown to the
      * user and the user will be asked to factory reset the device.
      *
      * <p>Use in an NFC record with {@link #MIME_TYPE_PROVISIONING_NFC_V2} that starts device owner
      * provisioning via an NFC bump.
      */
-    public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM
-        = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_CERTIFICATE_CHECKSUM";
+    public static final String EXTRA_PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM
+        = "android.app.extra.PROVISIONING_DEVICE_INITIALIZER_SIGNATURE_CHECKSUM";
 
     /**
      * A {@link android.os.Parcelable} extra of type {@link android.os.PersistableBundle} that
diff --git a/core/java/android/content/ContentProvider.java b/core/java/android/content/ContentProvider.java
index 72e701d..494f821 100644
--- a/core/java/android/content/ContentProvider.java
+++ b/core/java/android/content/ContentProvider.java
@@ -19,6 +19,7 @@
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
 import static android.Manifest.permission.INTERACT_ACROSS_USERS;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.AppOpsManager;
 import android.content.pm.PathPermission;
@@ -639,7 +640,7 @@
      * {@link #onCreate} has been called -- this will return {@code null} in the
      * constructor.
      */
-    public final Context getContext() {
+    public final @Nullable Context getContext() {
         return mContext;
     }
 
@@ -667,7 +668,7 @@
      * @throws SecurityException if the calling package doesn't belong to the
      *             calling UID.
      */
-    public final String getCallingPackage() {
+    public final @Nullable String getCallingPackage() {
         final String pkg = mCallingPackage.get();
         if (pkg != null) {
             mTransport.mAppOpsManager.checkPackage(Binder.getCallingUid(), pkg);
@@ -716,7 +717,7 @@
      *
      * @param permission Name of the permission required for read-only access.
      */
-    protected final void setReadPermission(String permission) {
+    protected final void setReadPermission(@Nullable String permission) {
         mReadPermission = permission;
     }
 
@@ -727,7 +728,7 @@
      * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
      */
-    public final String getReadPermission() {
+    public final @Nullable String getReadPermission() {
         return mReadPermission;
     }
 
@@ -738,7 +739,7 @@
      *
      * @param permission Name of the permission required for read/write access.
      */
-    protected final void setWritePermission(String permission) {
+    protected final void setWritePermission(@Nullable String permission) {
         mWritePermission = permission;
     }
 
@@ -749,7 +750,7 @@
      * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
      */
-    public final String getWritePermission() {
+    public final @Nullable String getWritePermission() {
         return mWritePermission;
     }
 
@@ -760,7 +761,7 @@
      *
      * @param permissions Array of path permission descriptions.
      */
-    protected final void setPathPermissions(PathPermission[] permissions) {
+    protected final void setPathPermissions(@Nullable PathPermission[] permissions) {
         mPathPermissions = permissions;
     }
 
@@ -771,7 +772,7 @@
      * <a href="{@docRoot}guide/topics/fundamentals/processes-and-threads.html#Threads">Processes
      * and Threads</a>.
      */
-    public final PathPermission[] getPathPermissions() {
+    public final @Nullable PathPermission[] getPathPermissions() {
         return mPathPermissions;
     }
 
@@ -897,8 +898,9 @@
      *      If {@code null} then the provider is free to define the sort order.
      * @return a Cursor or {@code null}.
      */
-    public abstract Cursor query(Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder);
+    public abstract @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder);
 
     /**
      * Implement this to handle query requests from clients with support for cancellation.
@@ -963,9 +965,9 @@
      * when the query is executed.
      * @return a Cursor or {@code null}.
      */
-    public Cursor query(Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder,
-            CancellationSignal cancellationSignal) {
+    public @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
         return query(uri, projection, selection, selectionArgs, sortOrder);
     }
 
@@ -987,7 +989,7 @@
      * @param uri the URI to query.
      * @return a MIME type string, or {@code null} if there is no type.
      */
-    public abstract String getType(Uri uri);
+    public abstract @Nullable String getType(@NonNull Uri uri);
 
     /**
      * Implement this to support canonicalization of URIs that refer to your
@@ -1019,7 +1021,7 @@
      * @return Return the canonical representation of <var>url</var>, or null if
      * canonicalization of that Uri is not supported.
      */
-    public Uri canonicalize(Uri url) {
+    public @Nullable Uri canonicalize(@NonNull Uri url) {
         return null;
     }
 
@@ -1037,7 +1039,7 @@
      * the data identified by the canonical representation can not be found in
      * the current environment.
      */
-    public Uri uncanonicalize(Uri url) {
+    public @Nullable Uri uncanonicalize(@NonNull Uri url) {
         return url;
     }
 
@@ -1070,7 +1072,7 @@
      *     This must not be {@code null}.
      * @return The URI for the newly inserted item.
      */
-    public abstract Uri insert(Uri uri, ContentValues values);
+    public abstract @Nullable Uri insert(@NonNull Uri uri, @Nullable ContentValues values);
 
     /**
      * Override this to handle requests to insert a set of new rows, or the
@@ -1087,7 +1089,7 @@
      *    This must not be {@code null}.
      * @return The number of values that were inserted.
      */
-    public int bulkInsert(Uri uri, ContentValues[] values) {
+    public int bulkInsert(@NonNull Uri uri, @NonNull ContentValues[] values) {
         int numValues = values.length;
         for (int i = 0; i < numValues; i++) {
             insert(uri, values[i]);
@@ -1115,7 +1117,8 @@
      * @return The number of rows affected.
      * @throws SQLException
      */
-    public abstract int delete(Uri uri, String selection, String[] selectionArgs);
+    public abstract int delete(@NonNull Uri uri, @Nullable String selection,
+            @Nullable String[] selectionArgs);
 
     /**
      * Implement this to handle requests to update one or more rows.
@@ -1134,8 +1137,8 @@
      * @param selection An optional filter to match rows to update.
      * @return the number of rows affected.
      */
-    public abstract int update(Uri uri, ContentValues values, String selection,
-            String[] selectionArgs);
+    public abstract int update(@NonNull Uri uri, @Nullable ContentValues values,
+            @Nullable String selection, @Nullable String[] selectionArgs);
 
     /**
      * Override this to handle requests to open a file blob.
@@ -1194,7 +1197,7 @@
      * @see #getType(android.net.Uri)
      * @see ParcelFileDescriptor#parseMode(String)
      */
-    public ParcelFileDescriptor openFile(Uri uri, String mode)
+    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode)
             throws FileNotFoundException {
         throw new FileNotFoundException("No files supported by provider at "
                 + uri);
@@ -1264,8 +1267,8 @@
      * @see #getType(android.net.Uri)
      * @see ParcelFileDescriptor#parseMode(String)
      */
-    public ParcelFileDescriptor openFile(Uri uri, String mode, CancellationSignal signal)
-            throws FileNotFoundException {
+    public @Nullable ParcelFileDescriptor openFile(@NonNull Uri uri, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
         return openFile(uri, mode);
     }
 
@@ -1320,7 +1323,7 @@
      * @see #openFileHelper(Uri, String)
      * @see #getType(android.net.Uri)
      */
-    public AssetFileDescriptor openAssetFile(Uri uri, String mode)
+    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode)
             throws FileNotFoundException {
         ParcelFileDescriptor fd = openFile(uri, mode);
         return fd != null ? new AssetFileDescriptor(fd, 0, -1) : null;
@@ -1383,8 +1386,8 @@
      * @see #openFileHelper(Uri, String)
      * @see #getType(android.net.Uri)
      */
-    public AssetFileDescriptor openAssetFile(Uri uri, String mode, CancellationSignal signal)
-            throws FileNotFoundException {
+    public @Nullable AssetFileDescriptor openAssetFile(@NonNull Uri uri, @NonNull String mode,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
         return openAssetFile(uri, mode);
     }
 
@@ -1402,8 +1405,8 @@
      * @return Returns a new ParcelFileDescriptor that can be used by the
      * client to access the file.
      */
-    protected final ParcelFileDescriptor openFileHelper(Uri uri,
-            String mode) throws FileNotFoundException {
+    protected final @NonNull ParcelFileDescriptor openFileHelper(@NonNull Uri uri,
+            @NonNull String mode) throws FileNotFoundException {
         Cursor c = query(uri, new String[]{"_data"}, null, null, null);
         int count = (c != null) ? c.getCount() : 0;
         if (count != 1) {
@@ -1449,7 +1452,7 @@
      * @see #openTypedAssetFile(Uri, String, Bundle)
      * @see ClipDescription#compareMimeTypes(String, String)
      */
-    public String[] getStreamTypes(Uri uri, String mimeTypeFilter) {
+    public @Nullable String[] getStreamTypes(@NonNull Uri uri, @NonNull String mimeTypeFilter) {
         return null;
     }
 
@@ -1498,8 +1501,8 @@
      * @see #openAssetFile(Uri, String)
      * @see ClipDescription#compareMimeTypes(String, String)
      */
-    public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts)
-            throws FileNotFoundException {
+    public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+            @NonNull String mimeTypeFilter, @Nullable Bundle opts) throws FileNotFoundException {
         if ("*/*".equals(mimeTypeFilter)) {
             // If they can take anything, the untyped open call is good enough.
             return openAssetFile(uri, "r");
@@ -1565,9 +1568,9 @@
      * @see #openAssetFile(Uri, String)
      * @see ClipDescription#compareMimeTypes(String, String)
      */
-    public AssetFileDescriptor openTypedAssetFile(
-            Uri uri, String mimeTypeFilter, Bundle opts, CancellationSignal signal)
-            throws FileNotFoundException {
+    public @Nullable AssetFileDescriptor openTypedAssetFile(@NonNull Uri uri,
+            @NonNull String mimeTypeFilter, @Nullable Bundle opts,
+            @Nullable CancellationSignal signal) throws FileNotFoundException {
         return openTypedAssetFile(uri, mimeTypeFilter, opts);
     }
 
@@ -1589,8 +1592,8 @@
          * @param opts Options supplied by caller.
          * @param args Your own custom arguments.
          */
-        public void writeDataToPipe(ParcelFileDescriptor output, Uri uri, String mimeType,
-                Bundle opts, T args);
+        public void writeDataToPipe(@NonNull ParcelFileDescriptor output, @NonNull Uri uri,
+                @NonNull String mimeType, @Nullable Bundle opts, @Nullable T args);
     }
 
     /**
@@ -1610,9 +1613,9 @@
      * the pipe.  This should be returned to the caller for reading; the caller
      * is responsible for closing it when done.
      */
-    public <T> ParcelFileDescriptor openPipeHelper(final Uri uri, final String mimeType,
-            final Bundle opts, final T args, final PipeDataWriter<T> func)
-            throws FileNotFoundException {
+    public @NonNull <T> ParcelFileDescriptor openPipeHelper(final @NonNull Uri uri,
+            final @NonNull String mimeType, final @Nullable Bundle opts, final @Nullable T args,
+            final @NonNull PipeDataWriter<T> func) throws FileNotFoundException {
         try {
             final ParcelFileDescriptor[] fds = ParcelFileDescriptor.createPipe();
 
@@ -1717,8 +1720,9 @@
      * @throws OperationApplicationException thrown if any operation fails.
      * @see ContentProviderOperation#apply
      */
-    public ContentProviderResult[] applyBatch(ArrayList<ContentProviderOperation> operations)
-            throws OperationApplicationException {
+    public @NonNull ContentProviderResult[] applyBatch(
+            @NonNull ArrayList<ContentProviderOperation> operations)
+                    throws OperationApplicationException {
         final int numOperations = operations.size();
         final ContentProviderResult[] results = new ContentProviderResult[numOperations];
         for (int i = 0; i < numOperations; i++) {
@@ -1745,7 +1749,8 @@
      * @return provider-defined return value.  May be {@code null}, which is also
      *   the default for providers which don't implement any call methods.
      */
-    public Bundle call(String method, @Nullable String arg, @Nullable Bundle extras) {
+    public @Nullable Bundle call(@NonNull String method, @Nullable String arg,
+            @Nullable Bundle extras) {
         return null;
     }
 
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/ContentResolver.java b/core/java/android/content/ContentResolver.java
index 96a80e7..057001c 100644
--- a/core/java/android/content/ContentResolver.java
+++ b/core/java/android/content/ContentResolver.java
@@ -17,6 +17,7 @@
 package android.content;
 
 import android.accounts.Account;
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.app.ActivityManagerNative;
 import android.app.ActivityThread;
@@ -47,6 +48,8 @@
 
 import dalvik.system.CloseGuard;
 
+import com.android.internal.util.Preconditions;
+
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
@@ -320,7 +323,9 @@
      * using the content:// scheme.
      * @return A MIME type for the content, or null if the URL is invalid or the type is unknown
      */
-    public final String getType(Uri url) {
+    public final @Nullable String getType(@NonNull Uri url) {
+        Preconditions.checkNotNull(url, "url");
+
         // XXX would like to have an acquireExistingUnstableProvider for this.
         IContentProvider provider = acquireExistingProvider(url);
         if (provider != null) {
@@ -371,7 +376,10 @@
      * data streams that match the given mimeTypeFilter.  If there are none,
      * null is returned.
      */
-    public String[] getStreamTypes(Uri url, String mimeTypeFilter) {
+    public @Nullable String[] getStreamTypes(@NonNull Uri url, @NonNull String mimeTypeFilter) {
+        Preconditions.checkNotNull(url, "url");
+        Preconditions.checkNotNull(mimeTypeFilter, "mimeTypeFilter");
+
         IContentProvider provider = acquireProvider(url);
         if (provider == null) {
             return null;
@@ -418,8 +426,9 @@
      * @return A Cursor object, which is positioned before the first entry, or null
      * @see Cursor
      */
-    public final Cursor query(Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder) {
+    public final @Nullable Cursor query(@NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder) {
         return query(uri, projection, selection, selectionArgs, sortOrder, null);
     }
 
@@ -457,9 +466,10 @@
      * @return A Cursor object, which is positioned before the first entry, or null
      * @see Cursor
      */
-    public final Cursor query(final Uri uri, String[] projection,
-            String selection, String[] selectionArgs, String sortOrder,
-            CancellationSignal cancellationSignal) {
+    public final @Nullable Cursor query(final @NonNull Uri uri, @Nullable String[] projection,
+            @Nullable String selection, @Nullable String[] selectionArgs,
+            @Nullable String sortOrder, @Nullable CancellationSignal cancellationSignal) {
+        Preconditions.checkNotNull(uri, "uri");
         IContentProvider unstableProvider = acquireUnstableProvider(uri);
         if (unstableProvider == null) {
             return null;
@@ -555,7 +565,8 @@
      *
      * @see #uncanonicalize
      */
-    public final Uri canonicalize(Uri url) {
+    public final @Nullable Uri canonicalize(@NonNull Uri url) {
+        Preconditions.checkNotNull(url, "url");
         IContentProvider provider = acquireProvider(url);
         if (provider == null) {
             return null;
@@ -590,7 +601,8 @@
      *
      * @see #canonicalize
      */
-    public final Uri uncanonicalize(Uri url) {
+    public final @Nullable Uri uncanonicalize(@NonNull Uri url) {
+        Preconditions.checkNotNull(url, "url");
         IContentProvider provider = acquireProvider(url);
         if (provider == null) {
             return null;
@@ -626,8 +638,9 @@
      * @throws FileNotFoundException if the provided URI could not be opened.
      * @see #openAssetFileDescriptor(Uri, String)
      */
-    public final InputStream openInputStream(Uri uri)
+    public final @Nullable InputStream openInputStream(@NonNull Uri uri)
             throws FileNotFoundException {
+        Preconditions.checkNotNull(uri, "uri");
         String scheme = uri.getScheme();
         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
             // Note: left here to avoid breaking compatibility.  May be removed
@@ -658,7 +671,7 @@
      * openOutputStream(uri, "w")}.
      * @throws FileNotFoundException if the provided URI could not be opened.
      */
-    public final OutputStream openOutputStream(Uri uri)
+    public final @Nullable OutputStream openOutputStream(@NonNull Uri uri)
             throws FileNotFoundException {
         return openOutputStream(uri, "w");
     }
@@ -682,7 +695,7 @@
      * @throws FileNotFoundException if the provided URI could not be opened.
      * @see #openAssetFileDescriptor(Uri, String)
      */
-    public final OutputStream openOutputStream(Uri uri, String mode)
+    public final @Nullable OutputStream openOutputStream(@NonNull Uri uri, @NonNull String mode)
             throws FileNotFoundException {
         AssetFileDescriptor fd = openAssetFileDescriptor(uri, mode, null);
         try {
@@ -729,8 +742,8 @@
      * file exists under the URI or the mode is invalid.
      * @see #openAssetFileDescriptor(Uri, String)
      */
-    public final ParcelFileDescriptor openFileDescriptor(Uri uri, String mode)
-            throws FileNotFoundException {
+    public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
+            @NonNull String mode) throws FileNotFoundException {
         return openFileDescriptor(uri, mode, null);
     }
 
@@ -774,8 +787,9 @@
      * file exists under the URI or the mode is invalid.
      * @see #openAssetFileDescriptor(Uri, String)
      */
-    public final ParcelFileDescriptor openFileDescriptor(Uri uri,
-            String mode, CancellationSignal cancellationSignal) throws FileNotFoundException {
+    public final @Nullable ParcelFileDescriptor openFileDescriptor(@NonNull Uri uri,
+            @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
+                    throws FileNotFoundException {
         AssetFileDescriptor afd = openAssetFileDescriptor(uri, mode, cancellationSignal);
         if (afd == null) {
             return null;
@@ -844,8 +858,8 @@
      * @throws FileNotFoundException Throws FileNotFoundException of no
      * file exists under the URI or the mode is invalid.
      */
-    public final AssetFileDescriptor openAssetFileDescriptor(Uri uri, String mode)
-            throws FileNotFoundException {
+    public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
+            @NonNull String mode) throws FileNotFoundException {
         return openAssetFileDescriptor(uri, mode, null);
     }
 
@@ -900,8 +914,12 @@
      * @throws FileNotFoundException Throws FileNotFoundException of no
      * file exists under the URI or the mode is invalid.
      */
-    public final AssetFileDescriptor openAssetFileDescriptor(Uri uri,
-            String mode, CancellationSignal cancellationSignal) throws FileNotFoundException {
+    public final @Nullable AssetFileDescriptor openAssetFileDescriptor(@NonNull Uri uri,
+            @NonNull String mode, @Nullable CancellationSignal cancellationSignal)
+                    throws FileNotFoundException {
+        Preconditions.checkNotNull(uri, "uri");
+        Preconditions.checkNotNull(mode, "mode");
+
         String scheme = uri.getScheme();
         if (SCHEME_ANDROID_RESOURCE.equals(scheme)) {
             if (!"r".equals(mode)) {
@@ -1023,8 +1041,8 @@
      * @throws FileNotFoundException Throws FileNotFoundException of no
      * data of the desired type exists under the URI.
      */
-    public final AssetFileDescriptor openTypedAssetFileDescriptor(
-            Uri uri, String mimeType, Bundle opts) throws FileNotFoundException {
+    public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+            @NonNull String mimeType, @Nullable Bundle opts) throws FileNotFoundException {
         return openTypedAssetFileDescriptor(uri, mimeType, opts, null);
     }
 
@@ -1059,9 +1077,12 @@
      * @throws FileNotFoundException Throws FileNotFoundException of no
      * data of the desired type exists under the URI.
      */
-    public final AssetFileDescriptor openTypedAssetFileDescriptor(Uri uri,
-            String mimeType, Bundle opts, CancellationSignal cancellationSignal)
-            throws FileNotFoundException {
+    public final @Nullable AssetFileDescriptor openTypedAssetFileDescriptor(@NonNull Uri uri,
+            @NonNull String mimeType, @Nullable Bundle opts,
+            @Nullable CancellationSignal cancellationSignal) throws FileNotFoundException {
+        Preconditions.checkNotNull(uri, "uri");
+        Preconditions.checkNotNull(mimeType, "mimeType");
+
         IContentProvider unstableProvider = acquireUnstableProvider(uri);
         if (unstableProvider == null) {
             throw new FileNotFoundException("No content provider: " + uri);
@@ -1197,8 +1218,8 @@
      *               the field. Passing an empty ContentValues will create an empty row.
      * @return the URL of the newly created row.
      */
-    public final Uri insert(Uri url, ContentValues values)
-    {
+    public final @Nullable Uri insert(@NonNull Uri url, @Nullable ContentValues values) {
+        Preconditions.checkNotNull(url, "url");
         IContentProvider provider = acquireProvider(url);
         if (provider == null) {
             throw new IllegalArgumentException("Unknown URL " + url);
@@ -1234,9 +1255,11 @@
      * @throws RemoteException thrown if a RemoteException is encountered while attempting
      *   to communicate with a remote provider.
      */
-    public ContentProviderResult[] applyBatch(String authority,
-            ArrayList<ContentProviderOperation> operations)
-            throws RemoteException, OperationApplicationException {
+    public @NonNull ContentProviderResult[] applyBatch(@NonNull String authority,
+            @NonNull ArrayList<ContentProviderOperation> operations)
+                    throws RemoteException, OperationApplicationException {
+        Preconditions.checkNotNull(authority, "authority");
+        Preconditions.checkNotNull(operations, "operations");
         ContentProviderClient provider = acquireContentProviderClient(authority);
         if (provider == null) {
             throw new IllegalArgumentException("Unknown authority " + authority);
@@ -1258,8 +1281,9 @@
      *               the field. Passing null will create an empty row.
      * @return the number of newly created rows.
      */
-    public final int bulkInsert(Uri url, ContentValues[] values)
-    {
+    public final int bulkInsert(@NonNull Uri url, @NonNull ContentValues[] values) {
+        Preconditions.checkNotNull(url, "url");
+        Preconditions.checkNotNull(values, "values");
         IContentProvider provider = acquireProvider(url);
         if (provider == null) {
             throw new IllegalArgumentException("Unknown URL " + url);
@@ -1289,8 +1313,9 @@
                     (excluding the WHERE itself).
      * @return The number of rows deleted.
      */
-    public final int delete(Uri url, String where, String[] selectionArgs)
-    {
+    public final int delete(@NonNull Uri url, @Nullable String where,
+            @Nullable String[] selectionArgs) {
+        Preconditions.checkNotNull(url, "url");
         IContentProvider provider = acquireProvider(url);
         if (provider == null) {
             throw new IllegalArgumentException("Unknown URL " + url);
@@ -1323,8 +1348,9 @@
      * @return the number of rows updated.
      * @throws NullPointerException if uri or values are null
      */
-    public final int update(Uri uri, ContentValues values, String where,
-            String[] selectionArgs) {
+    public final int update(@NonNull Uri uri, @Nullable ContentValues values,
+            @Nullable String where, @Nullable String[] selectionArgs) {
+        Preconditions.checkNotNull(uri, "uri");
         IContentProvider provider = acquireProvider(uri);
         if (provider == null) {
             throw new IllegalArgumentException("Unknown URI " + uri);
@@ -1358,14 +1384,10 @@
      * @throws NullPointerException if uri or method is null
      * @throws IllegalArgumentException if uri is not known
      */
-    public final Bundle call(
-            Uri uri, String method, @Nullable String arg, @Nullable Bundle extras) {
-        if (uri == null) {
-            throw new NullPointerException("uri == null");
-        }
-        if (method == null) {
-            throw new NullPointerException("method == null");
-        }
+    public final @Nullable Bundle call(@NonNull Uri uri, @NonNull String method,
+            @Nullable String arg, @Nullable Bundle extras) {
+        Preconditions.checkNotNull(uri, "uri");
+        Preconditions.checkNotNull(method, "method");
         IContentProvider provider = acquireProvider(uri);
         if (provider == null) {
             throw new IllegalArgumentException("Unknown URI " + uri);
@@ -1467,12 +1489,12 @@
      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
      * that services the content at uri or null if there isn't one.
      */
-    public final ContentProviderClient acquireContentProviderClient(Uri uri) {
+    public final @Nullable ContentProviderClient acquireContentProviderClient(@NonNull Uri uri) {
+        Preconditions.checkNotNull(uri, "uri");
         IContentProvider provider = acquireProvider(uri);
         if (provider != null) {
             return new ContentProviderClient(this, provider, true);
         }
-
         return null;
     }
 
@@ -1487,7 +1509,9 @@
      * @return a {@link ContentProviderClient} that is associated with the {@link ContentProvider}
      * with the authority of name or null if there isn't one.
      */
-    public final ContentProviderClient acquireContentProviderClient(String name) {
+    public final @Nullable ContentProviderClient acquireContentProviderClient(
+            @NonNull String name) {
+        Preconditions.checkNotNull(name, "name");
         IContentProvider provider = acquireProvider(name);
         if (provider != null) {
             return new ContentProviderClient(this, provider, true);
@@ -1512,7 +1536,9 @@
      * can acquire a new one if you would like to try to restart the provider
      * and perform new operations on it.
      */
-    public final ContentProviderClient acquireUnstableContentProviderClient(Uri uri) {
+    public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
+            @NonNull Uri uri) {
+        Preconditions.checkNotNull(uri, "uri");
         IContentProvider provider = acquireUnstableProvider(uri);
         if (provider != null) {
             return new ContentProviderClient(this, provider, false);
@@ -1537,7 +1563,9 @@
      * can acquire a new one if you would like to try to restart the provider
      * and perform new operations on it.
      */
-    public final ContentProviderClient acquireUnstableContentProviderClient(String name) {
+    public final @Nullable ContentProviderClient acquireUnstableContentProviderClient(
+            @NonNull String name) {
+        Preconditions.checkNotNull(name, "name");
         IContentProvider provider = acquireUnstableProvider(name);
         if (provider != null) {
             return new ContentProviderClient(this, provider, false);
@@ -1559,8 +1587,10 @@
      * @param observer The object that receives callbacks when changes occur.
      * @see #unregisterContentObserver
      */
-    public final void registerContentObserver(Uri uri, boolean notifyForDescendents,
-            ContentObserver observer) {
+    public final void registerContentObserver(@NonNull Uri uri, boolean notifyForDescendents,
+            @NonNull ContentObserver observer) {
+        Preconditions.checkNotNull(uri, "uri");
+        Preconditions.checkNotNull(observer, "observer");
         registerContentObserver(uri, notifyForDescendents, observer, UserHandle.myUserId());
     }
 
@@ -1580,7 +1610,8 @@
      * @param observer The previously registered observer that is no longer needed.
      * @see #registerContentObserver
      */
-    public final void unregisterContentObserver(ContentObserver observer) {
+    public final void unregisterContentObserver(@NonNull ContentObserver observer) {
+        Preconditions.checkNotNull(observer, "observer");
         try {
             IContentObserver contentObserver = observer.releaseContentObserver();
             if (contentObserver != null) {
@@ -1603,7 +1634,7 @@
      * has requested to receive self-change notifications by implementing
      * {@link ContentObserver#deliverSelfNotifications()} to return true.
      */
-    public void notifyChange(Uri uri, ContentObserver observer) {
+    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer) {
         notifyChange(uri, observer, true /* sync to network */);
     }
 
@@ -1623,7 +1654,9 @@
      * @param syncToNetwork If true, attempt to sync the change to the network.
      * @see #requestSync(android.accounts.Account, String, android.os.Bundle)
      */
-    public void notifyChange(Uri uri, ContentObserver observer, boolean syncToNetwork) {
+    public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
+            boolean syncToNetwork) {
+        Preconditions.checkNotNull(uri, "uri");
         notifyChange(uri, observer, syncToNetwork, UserHandle.myUserId());
     }
 
@@ -1653,7 +1686,9 @@
      *
      * @see #getPersistedUriPermissions()
      */
-    public void takePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
+    public void takePersistableUriPermission(@NonNull Uri uri,
+            @Intent.AccessUriMode int modeFlags) {
+        Preconditions.checkNotNull(uri, "uri");
         try {
             ActivityManagerNative.getDefault().takePersistableUriPermission(
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
@@ -1669,7 +1704,9 @@
      *
      * @see #getPersistedUriPermissions()
      */
-    public void releasePersistableUriPermission(Uri uri, @Intent.AccessUriMode int modeFlags) {
+    public void releasePersistableUriPermission(@NonNull Uri uri,
+            @Intent.AccessUriMode int modeFlags) {
+        Preconditions.checkNotNull(uri, "uri");
         try {
             ActivityManagerNative.getDefault().releasePersistableUriPermission(
                     ContentProvider.getUriWithoutUserId(uri), modeFlags, resolveUserId(uri));
@@ -1686,7 +1723,7 @@
      * @see #takePersistableUriPermission(Uri, int)
      * @see #releasePersistableUriPermission(Uri, int)
      */
-    public List<UriPermission> getPersistedUriPermissions() {
+    public @NonNull List<UriPermission> getPersistedUriPermissions() {
         try {
             return ActivityManagerNative.getDefault()
                     .getPersistedUriPermissions(mPackageName, true).getList();
@@ -1701,7 +1738,7 @@
      * <em>from</em> the calling app. Only grants taken with
      * {@link #takePersistableUriPermission(Uri, int)} are returned.
      */
-    public List<UriPermission> getOutgoingPersistedUriPermissions() {
+    public @NonNull List<UriPermission> getOutgoingPersistedUriPermissions() {
         try {
             return ActivityManagerNative.getDefault()
                     .getPersistedUriPermissions(mPackageName, false).getList();
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/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index 83b0140..c92c256 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -36,6 +36,7 @@
 import android.content.res.XmlResourceParser;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.FileUtils;
 import android.os.PatternMatcher;
 import android.os.UserHandle;
 import android.text.TextUtils;
@@ -1194,7 +1195,8 @@
         }
     }
 
-    private static String validateName(String name, boolean requiresSeparator) {
+    private static String validateName(String name, boolean requireSeparator,
+            boolean requireFilename) {
         final int N = name.length();
         boolean hasSep = false;
         boolean front = true;
@@ -1216,7 +1218,10 @@
             }
             return "bad character '" + c + "'";
         }
-        return hasSep || !requiresSeparator
+        if (requireFilename && !FileUtils.isValidExtFilename(name)) {
+            return "Invalid filename";
+        }
+        return hasSep || !requireSeparator
                 ? null : "must have at least one '.' separator";
     }
 
@@ -1240,7 +1245,7 @@
 
         final String packageName = attrs.getAttributeValue(null, "package");
         if (!"android".equals(packageName)) {
-            final String error = validateName(packageName, true);
+            final String error = validateName(packageName, true, true);
             if (error != null) {
                 throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                         "Invalid manifest package: " + error);
@@ -1252,7 +1257,7 @@
             if (splitName.length() == 0) {
                 splitName = null;
             } else {
-                final String error = validateName(splitName, false);
+                final String error = validateName(splitName, false, false);
                 if (error != null) {
                     throw new PackageParserException(INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME,
                             "Invalid manifest split: " + error);
@@ -1391,7 +1396,7 @@
         String str = sa.getNonConfigurationString(
                 com.android.internal.R.styleable.AndroidManifest_sharedUserId, 0);
         if (str != null && str.length() > 0) {
-            String nameError = validateName(str, true);
+            String nameError = validateName(str, true, false);
             if (nameError != null && !"android".equals(pkgName)) {
                 outError[0] = "<manifest> specifies bad sharedUserId name \""
                     + str + "\": " + nameError;
@@ -1973,7 +1978,7 @@
                 return null;
             }
             String subName = proc.substring(1);
-            String nameError = validateName(subName, false);
+            String nameError = validateName(subName, false, false);
             if (nameError != null) {
                 outError[0] = "Invalid " + type + " name " + proc + " in package "
                         + pkg + ": " + nameError;
@@ -1981,7 +1986,7 @@
             }
             return (pkg + proc).intern();
         }
-        String nameError = validateName(proc, true);
+        String nameError = validateName(proc, true, false);
         if (nameError != null && !"system".equals(proc)) {
             outError[0] = "Invalid " + type + " name " + proc + " in package "
                     + pkg + ": " + nameError;
diff --git a/core/java/android/inputmethodservice/Keyboard.java b/core/java/android/inputmethodservice/Keyboard.java
index 45f1889..a5490ef 100644
--- a/core/java/android/inputmethodservice/Keyboard.java
+++ b/core/java/android/inputmethodservice/Keyboard.java
@@ -400,16 +400,27 @@
         public void onPressed() {
             pressed = !pressed;
         }
-        
+
         /**
-         * Changes the pressed state of the key. If it is a sticky key, it will also change the
-         * toggled state of the key if the finger was release inside.
-         * @param inside whether the finger was released inside the key
+         * Changes the pressed state of the key.
+         *
+         * <p>Toggled state of the key will be flipped when all the following conditions are
+         * fulfilled:</p>
+         *
+         * <ul>
+         *     <li>This is a sticky key, that is, {@link #sticky} is {@code true}.
+         *     <li>The parameter {@code inside} is {@code true}.
+         *     <li>{@link android.os.Build.VERSION#SDK_INT} is greater than
+         *         {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
+         * </ul>
+         *
+         * @param inside whether the finger was released inside the key. Works only on Android M and
+         * later. See the method document for details.
          * @see #onPressed()
          */
         public void onReleased(boolean inside) {
             pressed = !pressed;
-            if (sticky) {
+            if (sticky && inside) {
                 on = !on;
             }
         }
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/FileUtils.java b/core/java/android/os/FileUtils.java
index 917271d..864225a 100644
--- a/core/java/android/os/FileUtils.java
+++ b/core/java/android/os/FileUtils.java
@@ -24,6 +24,8 @@
 import android.util.Slog;
 import android.webkit.MimeTypeMap;
 
+import com.android.internal.annotations.VisibleForTesting;
+
 import java.io.BufferedInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
@@ -34,6 +36,7 @@
 import java.io.FileWriter;
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
 import java.util.Arrays;
 import java.util.Comparator;
 import java.util.Objects;
@@ -456,6 +459,7 @@
                 res.append('_');
             }
         }
+        trimFilename(res, 255);
         return res.toString();
     }
 
@@ -504,9 +508,31 @@
                 res.append('_');
             }
         }
+        // Even though vfat allows 255 UCS-2 chars, we might eventually write to
+        // ext4 through a FUSE layer, so use that limit.
+        trimFilename(res, 255);
         return res.toString();
     }
 
+    @VisibleForTesting
+    public static String trimFilename(String str, int maxBytes) {
+        final StringBuilder res = new StringBuilder(str);
+        trimFilename(res, maxBytes);
+        return res.toString();
+    }
+
+    private static void trimFilename(StringBuilder res, int maxBytes) {
+        byte[] raw = res.toString().getBytes(StandardCharsets.UTF_8);
+        if (raw.length > maxBytes) {
+            maxBytes -= 3;
+            while (raw.length > maxBytes) {
+                res.deleteCharAt(res.length() / 2);
+                raw = res.toString().getBytes(StandardCharsets.UTF_8);
+            }
+            res.insert(res.length() / 2, "...");
+        }
+    }
+
     public static String rewriteAfterRename(File beforeDir, File afterDir, String path) {
         if (path == null) return null;
         final File result = rewriteAfterRename(beforeDir, afterDir, new File(path));
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 f7d2821..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/View.java b/core/java/android/view/View.java
index be372d0..0df8ea9 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -741,6 +741,11 @@
     private static boolean sUseBrokenMakeMeasureSpec = false;
 
     /**
+     * Always return a size of 0 for MeasureSpec values with a mode of UNSPECIFIED
+     */
+    static boolean sUseZeroUnspecifiedMeasureSpec = false;
+
+    /**
      * Ignore any optimizations using the measure cache.
      */
     private static boolean sIgnoreMeasureCache = false;
@@ -3796,6 +3801,13 @@
 
             Canvas.sCompatibilityRestore = targetSdkVersion < MNC;
 
+            // In MNC and newer, our widgets can pass a "hint" value in the size
+            // for UNSPECIFIED MeasureSpecs. This lets child views of scrolling containers
+            // know what the expected parent size is going to be, so e.g. list items can size
+            // themselves at 1/3 the size of their container. It breaks older apps though,
+            // specifically apps that use some popular open source libraries.
+            sUseZeroUnspecifiedMeasureSpec = targetSdkVersion < MNC;
+
             sCompatibilityDone = true;
         }
     }
@@ -17163,21 +17175,6 @@
     }
 
     /**
-     * If the view has a ColorDrawable background, returns the color of that
-     * drawable.
-     *
-     * @return The color of the ColorDrawable background, if set, otherwise 0.
-     * @hide
-     */
-    @ColorInt
-    public int getBackgroundColor() {
-        if (mBackground instanceof ColorDrawable) {
-            return ((ColorDrawable) mBackground).getColor();
-        }
-        return 0;
-    }
-
-    /**
      * Set the background to a given resource. The resource should refer to
      * a Drawable object or 0 to remove the background.
      * @param resid The identifier of the resource.
@@ -21032,6 +21029,19 @@
         }
 
         /**
+         * Like {@link #makeMeasureSpec(int, int)}, but any spec with a mode of UNSPECIFIED
+         * will automatically get a size of 0. Older apps expect this.
+         *
+         * @hide internal use only for compatibility with system widgets and older apps
+         */
+        public static int makeSafeMeasureSpec(int size, int mode) {
+            if (sUseZeroUnspecifiedMeasureSpec && mode == UNSPECIFIED) {
+                return 0;
+            }
+            return makeMeasureSpec(size, mode);
+        }
+
+        /**
          * Extracts the mode from the supplied measure specification.
          *
          * @param measureSpec the measure specification to extract the mode from
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index dd32f85..89743e5 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -5963,12 +5963,12 @@
             } else if (childDimension == LayoutParams.MATCH_PARENT) {
                 // Child wants to be our size... find out how big it should
                 // be
-                resultSize = size;
+                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                 resultMode = MeasureSpec.UNSPECIFIED;
             } else if (childDimension == LayoutParams.WRAP_CONTENT) {
                 // Child wants to determine its own size.... find out how
                 // big it should be
-                resultSize = size;
+                resultSize = View.sUseZeroUnspecifiedMeasureSpec ? 0 : size;
                 resultMode = MeasureSpec.UNSPECIFIED;
             }
             break;
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/Editor.java b/core/java/android/widget/Editor.java
index e43237a..cf6a018 100644
--- a/core/java/android/widget/Editor.java
+++ b/core/java/android/widget/Editor.java
@@ -1162,6 +1162,10 @@
         // We do not hide the span controllers, since they can be added when a new text is
         // inserted into the text view (voice IME).
         hideCursorControllers();
+        // Reset drag accelerator.
+        if (mSelectionModifierCursorController != null) {
+            mSelectionModifierCursorController.resetTouchOffsets();
+        }
         stopTextActionMode();
     }
 
diff --git a/core/java/android/widget/FastScroller.java b/core/java/android/widget/FastScroller.java
index f06f3c21..11d7026 100644
--- a/core/java/android/widget/FastScroller.java
+++ b/core/java/android/widget/FastScroller.java
@@ -662,7 +662,7 @@
 
         final int adjMaxWidth = maxWidth - marginLeft - marginRight;
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST);
-        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+        final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
                 MeasureSpec.UNSPECIFIED);
         view.measure(widthMeasureSpec, heightMeasureSpec);
 
@@ -702,7 +702,7 @@
         final int containerWidth = container.width();
         final int adjMaxWidth = containerWidth - marginLeft - marginRight;
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(adjMaxWidth, MeasureSpec.AT_MOST);
-        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+        final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
                 MeasureSpec.UNSPECIFIED);
         preview.measure(widthMeasureSpec, heightMeasureSpec);
 
@@ -768,7 +768,7 @@
         final Rect container = mContainerRect;
         final int maxWidth = container.width();
         final int widthMeasureSpec = MeasureSpec.makeMeasureSpec(maxWidth, MeasureSpec.AT_MOST);
-        final int heightMeasureSpec = MeasureSpec.makeMeasureSpec(container.height(),
+        final int heightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(container.height(),
                 MeasureSpec.UNSPECIFIED);
         track.measure(widthMeasureSpec, heightMeasureSpec);
 
diff --git a/core/java/android/widget/GridView.java b/core/java/android/widget/GridView.java
index dcaafa5..f994d4a 100644
--- a/core/java/android/widget/GridView.java
+++ b/core/java/android/widget/GridView.java
@@ -1073,7 +1073,7 @@
             p.forceAdd = true;
 
             int childHeightSpec = getChildMeasureSpec(
-                    MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
+                    MeasureSpec.makeSafeMeasureSpec(MeasureSpec.getSize(heightMeasureSpec),
                             MeasureSpec.UNSPECIFIED), 0, p.height);
             int childWidthSpec = getChildMeasureSpec(
                     MeasureSpec.makeMeasureSpec(mColumnWidth, MeasureSpec.EXACTLY), 0, p.width);
diff --git a/core/java/android/widget/LinearLayout.java b/core/java/android/widget/LinearLayout.java
index 9d14254..056323db 100644
--- a/core/java/android/widget/LinearLayout.java
+++ b/core/java/android/widget/LinearLayout.java
@@ -1062,9 +1062,9 @@
                 // use as much space as it wants because we can shrink things
                 // later (and re-measure).
                 if (baselineAligned) {
-                    final int freeWidthSpec = MeasureSpec.makeMeasureSpec(
+                    final int freeWidthSpec = MeasureSpec.makeSafeMeasureSpec(
                             MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.UNSPECIFIED);
-                    final int freeHeightSpec = MeasureSpec.makeMeasureSpec(
+                    final int freeHeightSpec = MeasureSpec.makeSafeMeasureSpec(
                             MeasureSpec.getSize(heightMeasureSpec), MeasureSpec.UNSPECIFIED);
                     child.measure(freeWidthSpec, freeHeightSpec);
                 } else {
diff --git a/core/java/android/widget/ListView.java b/core/java/android/widget/ListView.java
index f8b965f..fd0395a 100644
--- a/core/java/android/widget/ListView.java
+++ b/core/java/android/widget/ListView.java
@@ -1206,7 +1206,7 @@
         if (lpHeight > 0) {
             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
         } else {
-            childHeightSpec = MeasureSpec.makeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
+            childHeightSpec = MeasureSpec.makeSafeMeasureSpec(heightHint, MeasureSpec.UNSPECIFIED);
         }
         child.measure(childWidthSpec, childHeightSpec);
     }
@@ -1943,7 +1943,7 @@
             if (lpHeight > 0) {
                 childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
             } else {
-                childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
+                childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(),
                         MeasureSpec.UNSPECIFIED);
             }
             child.measure(childWidthSpec, childHeightSpec);
@@ -2698,7 +2698,7 @@
         if (lpHeight > 0) {
             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);
         } else {
-            childHeightSpec = MeasureSpec.makeMeasureSpec(getMeasuredHeight(),
+            childHeightSpec = MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(),
                     MeasureSpec.UNSPECIFIED);
         }
         child.measure(childWidthSpec, childHeightSpec);
diff --git a/core/java/android/widget/ScrollView.java b/core/java/android/widget/ScrollView.java
index 11904e1..58a94b9 100644
--- a/core/java/android/widget/ScrollView.java
+++ b/core/java/android/widget/ScrollView.java
@@ -1263,7 +1263,7 @@
         childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec, mPaddingLeft
                 + mPaddingRight, lp.width);
 
-        childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+        childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                 MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);
 
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
@@ -1277,7 +1277,7 @@
         final int childWidthMeasureSpec = getChildMeasureSpec(parentWidthMeasureSpec,
                 mPaddingLeft + mPaddingRight + lp.leftMargin + lp.rightMargin
                         + widthUsed, lp.width);
-        final int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(
+        final int childHeightMeasureSpec = MeasureSpec.makeSafeMeasureSpec(
                 MeasureSpec.getSize(parentHeightMeasureSpec), MeasureSpec.UNSPECIFIED);
 
         child.measure(childWidthMeasureSpec, childHeightMeasureSpec);
diff --git a/core/java/android/widget/Spinner.java b/core/java/android/widget/Spinner.java
index 6fe34dd..fdabe91 100644
--- a/core/java/android/widget/Spinner.java
+++ b/core/java/android/widget/Spinner.java
@@ -812,9 +812,9 @@
         View itemView = null;
         int itemType = 0;
         final int widthMeasureSpec =
-            MeasureSpec.makeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED);
+            MeasureSpec.makeSafeMeasureSpec(getMeasuredWidth(), MeasureSpec.UNSPECIFIED);
         final int heightMeasureSpec =
-            MeasureSpec.makeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED);
+            MeasureSpec.makeSafeMeasureSpec(getMeasuredHeight(), MeasureSpec.UNSPECIFIED);
 
         // Make sure the number of items we'll measure is capped. If it's a huge data set
         // with wildly varying sizes, oh well.
diff --git a/core/java/android/widget/TabWidget.java b/core/java/android/widget/TabWidget.java
index aa7168c..d9cff4e 100644
--- a/core/java/android/widget/TabWidget.java
+++ b/core/java/android/widget/TabWidget.java
@@ -174,7 +174,8 @@
 
         // First, measure with no constraint
         final int width = MeasureSpec.getSize(widthMeasureSpec);
-        final int unspecifiedWidth = MeasureSpec.makeMeasureSpec(width, MeasureSpec.UNSPECIFIED);
+        final int unspecifiedWidth = MeasureSpec.makeSafeMeasureSpec(width,
+                MeasureSpec.UNSPECIFIED);
         mImposedTabsHeight = -1;
         super.measureHorizontal(unspecifiedWidth, heightMeasureSpec);
 
diff --git a/core/java/android/widget/TableRow.java b/core/java/android/widget/TableRow.java
index d4288d6..f7f9c91 100644
--- a/core/java/android/widget/TableRow.java
+++ b/core/java/android/widget/TableRow.java
@@ -303,7 +303,7 @@
                             spec = getChildMeasureSpec(widthMeasureSpec, 0, LayoutParams.WRAP_CONTENT);
                             break;
                         case LayoutParams.MATCH_PARENT:
-                            spec = MeasureSpec.makeMeasureSpec(
+                            spec = MeasureSpec.makeSafeMeasureSpec(
                                     MeasureSpec.getSize(heightMeasureSpec),
                                     MeasureSpec.UNSPECIFIED);
                             break;
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/widget/ActionBarContextView.java b/core/java/com/android/internal/widget/ActionBarContextView.java
index 106272b..c5d3290 100644
--- a/core/java/com/android/internal/widget/ActionBarContextView.java
+++ b/core/java/com/android/internal/widget/ActionBarContextView.java
@@ -367,7 +367,7 @@
 
         if (mTitleLayout != null && mCustomView == null) {
             if (mTitleOptional) {
-                final int titleWidthSpec = MeasureSpec.makeMeasureSpec(contentWidth,
+                final int titleWidthSpec = MeasureSpec.makeSafeMeasureSpec(contentWidth,
                         MeasureSpec.UNSPECIFIED);
                 mTitleLayout.measure(titleWidthSpec, childSpecHeight);
                 final int titleWidth = mTitleLayout.getMeasuredWidth();
diff --git a/core/java/com/android/internal/widget/SlidingTab.java b/core/java/com/android/internal/widget/SlidingTab.java
index 0066ed0..79adada 100644
--- a/core/java/com/android/internal/widget/SlidingTab.java
+++ b/core/java/com/android/internal/widget/SlidingTab.java
@@ -403,10 +403,10 @@
         public void measure(int widthMeasureSpec, int heightMeasureSpec) {
             int width = MeasureSpec.getSize(widthMeasureSpec);
             int height = MeasureSpec.getSize(heightMeasureSpec);
-            tab.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
-                    View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
-            text.measure(View.MeasureSpec.makeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
-                    View.MeasureSpec.makeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
+            tab.measure(View.MeasureSpec.makeSafeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
+                    View.MeasureSpec.makeSafeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
+            text.measure(View.MeasureSpec.makeSafeMeasureSpec(width, View.MeasureSpec.UNSPECIFIED),
+                    View.MeasureSpec.makeSafeMeasureSpec(height, View.MeasureSpec.UNSPECIFIED));
         }
 
         /**
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index e58ac1d..8a79f5a 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -453,6 +453,63 @@
         android:description="@string/permdesc_readCellBroadcasts"
         android:protectionLevel="dangerous" />
 
+    <!-- ====================================================================== -->
+    <!-- Permissions for accessing external storage                             -->
+    <!-- ====================================================================== -->
+    <eat-comment />
+
+    <!-- Used for runtime permissions related to the shared external storage. -->
+    <permission-group android:name="android.permission-group.STORAGE"
+        android:icon="@drawable/perm_group_storage"
+        android:label="@string/permgrouplab_storage"
+        android:description="@string/permgroupdesc_storage"
+        android:priority="900" />
+
+    <!-- Allows an application to read from external storage.
+     <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
+     granted this permission.</p>
+     <p>This permission is enforced starting in API level 19.  Before API level 19, this
+     permission is not enforced and all apps still have access to read from external storage.
+     You can test your app with the permission enforced by enabling <em>Protect USB
+     storage</em> under Developer options in the Settings app on a device running Android 4.1 or
+     higher.</p>
+     <p>Also starting in API level 19, this permission is <em>not</em> required to
+     read/write files in your application-specific directories returned by
+     {@link android.content.Context#getExternalFilesDir} and
+     {@link android.content.Context#getExternalCacheDir}.
+     <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+     href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+     minSdkVersion}</a> and <a
+     href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+     targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+     grants your app this permission. If you don't need this permission, be sure your <a
+     href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+     targetSdkVersion}</a> is 4 or higher.-->
+    <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardRead"
+        android:description="@string/permdesc_sdcardRead"
+        android:protectionLevel="normal" />
+
+    <!-- Allows an application to write to external storage.
+         <p class="note"><strong>Note:</strong> If <em>both</em> your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
+         minSdkVersion}</a> and <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
+         grants your app this permission. If you don't need this permission, be sure your <a
+         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
+         targetSdkVersion}</a> is 4 or higher.
+         <p>Starting in API level 19, this permission is <em>not</em> required to
+         read/write files in your application-specific directories returned by
+         {@link android.content.Context#getExternalFilesDir} and
+         {@link android.content.Context#getExternalCacheDir}. -->
+    <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
+        android:permissionGroup="android.permission-group.STORAGE"
+        android:label="@string/permlab_sdcardWrite"
+        android:description="@string/permdesc_sdcardWrite"
+        android:protectionLevel="dangerous" />
+
     <!-- =============================================================== -->
     <!-- Permissions for accessing social info                           -->
     <!-- =============================================================== -->
@@ -865,7 +922,7 @@
     <permission android:name="android.permission.CHANGE_WIFI_STATE"
         android:description="@string/permdesc_changeWifiState"
         android:label="@string/permlab_changeWifiState"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi @hide Allows applications to read Wi-Fi credential.
          <p>Not for use by third-party applications. -->
@@ -895,7 +952,7 @@
     <permission android:name="android.permission.CHANGE_WIMAX_STATE"
         android:description="@string/permdesc_changeWimaxState"
         android:label="@string/permlab_changeWimaxState"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="normal" />
 
     <!--@SystemApi Allows applications to the the local WiFi and Bluetooth MAC address.
         @hide
@@ -912,13 +969,13 @@
     <permission android:name="android.permission.BLUETOOTH"
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="normal" />
 
     <!-- Allows applications to discover and pair bluetooth devices -->
     <permission android:name="android.permission.BLUETOOTH_ADMIN"
         android:description="@string/permdesc_bluetoothAdmin"
         android:label="@string/permlab_bluetoothAdmin"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="normal" />
 
     <!-- @SystemApi Allows applications to pair bluetooth devices without user interaction, and to
          allow or disallow phonebook access or message access.
@@ -1000,7 +1057,7 @@
     <permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"
         android:description="@string/permdesc_changeWifiMulticastState"
         android:label="@string/permlab_changeWifiMulticastState"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="normal" />
 
     <!-- Allows access to the vibrator -->
     <permission android:name="android.permission.VIBRATE"
@@ -1197,49 +1254,6 @@
     <!-- ================================== -->
     <eat-comment />
 
-    <!-- Allows an application to read from external storage.
-         <p>Any app that declares the {@link #WRITE_EXTERNAL_STORAGE} permission is implicitly
-         granted this permission.</p>
-         <p>This permission is enforced starting in API level 19.  Before API level 19, this
-         permission is not enforced and all apps still have access to read from external storage.
-         You can test your app with the permission enforced by enabling <em>Protect USB
-         storage</em> under Developer options in the Settings app on a device running Android 4.1 or
-         higher.</p>
-         <p>Also starting in API level 19, this permission is <em>not</em> required to
-         read/write files in your application-specific directories returned by
-         {@link android.content.Context#getExternalFilesDir} and
-         {@link android.content.Context#getExternalCacheDir}.
-         <p class="note"><strong>Note:</strong> If <em>both</em> your <a
-         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-         minSdkVersion}</a> and <a
-         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-         targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
-         grants your app this permission. If you don't need this permission, be sure your <a
-         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-         targetSdkVersion}</a> is 4 or higher.-->
-    <permission android:name="android.permission.READ_EXTERNAL_STORAGE"
-        android:label="@string/permlab_sdcardRead"
-        android:description="@string/permdesc_sdcardRead"
-        android:protectionLevel="normal" />
-
-    <!-- Allows an application to write to external storage.
-         <p class="note"><strong>Note:</strong> If <em>both</em> your <a
-         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min">{@code
-         minSdkVersion}</a> and <a
-         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-         targetSdkVersion}</a> values are set to 3 or lower, the system implicitly
-         grants your app this permission. If you don't need this permission, be sure your <a
-         href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#target">{@code
-         targetSdkVersion}</a> is 4 or higher.
-         <p>Starting in API level 19, this permission is <em>not</em> required to
-         read/write files in your application-specific directories returned by
-         {@link android.content.Context#getExternalFilesDir} and
-         {@link android.content.Context#getExternalCacheDir}. -->
-    <permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
-        android:label="@string/permlab_sdcardWrite"
-        android:description="@string/permdesc_sdcardWrite"
-        android:protectionLevel="normal" />
-
     <!-- @SystemApi Allows an application to write to internal media storage
          @hide  -->
     <permission android:name="android.permission.WRITE_MEDIA_STORAGE"
@@ -1477,7 +1491,7 @@
     <permission android:name="android.permission.WRITE_SETTINGS"
         android:label="@string/permlab_writeSettings"
         android:description="@string/permdesc_writeSettings"
-        android:protectionLevel="normal" />
+        android:protectionLevel="dangerous" />
 
     <!-- @SystemApi Allows an application to modify the Google service map.
     <p>Not for use by third-party applications. -->
@@ -1593,7 +1607,7 @@
     <!-- Allows an application to clear the caches of all installed
          applications on the device.  -->
     <permission android:name="android.permission.CLEAR_APP_CACHE"
-        android:protectionLevel="dangerous" />
+        android:protectionLevel="signatureOrSystem" />
 
     <!-- @SystemApi Allows an application to use any media decoder when decoding for playback
          @hide -->
diff --git a/core/res/res/drawable/floating_popup_background.xml b/core/res/res/drawable/floating_popup_background_dark.xml
similarity index 87%
copy from core/res/res/drawable/floating_popup_background.xml
copy to core/res/res/drawable/floating_popup_background_dark.xml
index b6700b3..ded1137 100644
--- a/core/res/res/drawable/floating_popup_background.xml
+++ b/core/res/res/drawable/floating_popup_background_dark.xml
@@ -16,8 +16,8 @@
 */
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shape="rectangle">
-    <solid android:color="?attr/colorBackgroundFloating" />
+       android:shape="rectangle">
+    <solid android:color="@color/background_floating_material_dark" />
     <corners android:radius="2dp" />
 </shape>
 
diff --git a/core/res/res/drawable/floating_popup_background.xml b/core/res/res/drawable/floating_popup_background_light.xml
similarity index 91%
rename from core/res/res/drawable/floating_popup_background.xml
rename to core/res/res/drawable/floating_popup_background_light.xml
index b6700b3..9c7a886 100644
--- a/core/res/res/drawable/floating_popup_background.xml
+++ b/core/res/res/drawable/floating_popup_background_light.xml
@@ -17,7 +17,7 @@
 -->
 <shape xmlns:android="http://schemas.android.com/apk/res/android"
     android:shape="rectangle">
-    <solid android:color="?attr/colorBackgroundFloating" />
+    <solid android:color="@color/background_floating_material_light" />
     <corners android:radius="2dp" />
 </shape>
 
diff --git a/core/res/res/drawable/ic_ab_back_material_dark.xml b/core/res/res/drawable/ic_ab_back_material_dark.xml
new file mode 100644
index 0000000..7cdd139
--- /dev/null
+++ b/core/res/res/drawable/ic_ab_back_material_dark.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:autoMirrored="true"
+        android:tint="@color/secondary_text_material_dark">
+  <path
+      android:pathData="M20,11L7.8,11l5.6,-5.6L12,4l-8,8l8,8l1.4,-1.4L7.8,13L20,13L20,11z"
+      android:fillColor="@color/white"/>
+</vector>
diff --git a/core/res/res/drawable/ic_ab_back_material_light.xml b/core/res/res/drawable/ic_ab_back_material_light.xml
new file mode 100644
index 0000000..65dab81
--- /dev/null
+++ b/core/res/res/drawable/ic_ab_back_material_light.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:autoMirrored="true"
+        android:tint="@color/secondary_text_material_light">
+  <path
+      android:pathData="M20,11L7.8,11l5.6,-5.6L12,4l-8,8l8,8l1.4,-1.4L7.8,13L20,13L20,11z"
+      android:fillColor="@color/white"/>
+</vector>
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material.xml b/core/res/res/drawable/ic_menu_moreoverflow_material.xml
index 502ad69..3f53451 100644
--- a/core/res/res/drawable/ic_menu_moreoverflow_material.xml
+++ b/core/res/res/drawable/ic_menu_moreoverflow_material.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
 <!--
 Copyright (C) 2014 The Android Open Source Project
 
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material_dark.xml b/core/res/res/drawable/ic_menu_moreoverflow_material_dark.xml
new file mode 100644
index 0000000..fa350a6
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_moreoverflow_material_dark.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="@color/secondary_text_material_dark">
+    <path
+        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/core/res/res/drawable/ic_menu_moreoverflow_material_light.xml b/core/res/res/drawable/ic_menu_moreoverflow_material_light.xml
new file mode 100644
index 0000000..7af234f
--- /dev/null
+++ b/core/res/res/drawable/ic_menu_moreoverflow_material_light.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2014 The Android Open Source Project
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+    you may not use this file except in compliance with the License.
+    You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="24dp"
+        android:height="24dp"
+        android:viewportWidth="24.0"
+        android:viewportHeight="24.0"
+        android:tint="@color/secondary_text_material_light">
+    <path
+        android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
+        android:fillColor="@color/white"/>
+</vector>
diff --git a/core/res/res/drawable/item_background_borderless_material_dark.xml b/core/res/res/drawable/item_background_borderless_material_dark.xml
new file mode 100644
index 0000000..685c52a
--- /dev/null
+++ b/core/res/res/drawable/item_background_borderless_material_dark.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/ripple_material_dark" />
diff --git a/core/res/res/drawable/item_background_borderless_material_light.xml b/core/res/res/drawable/item_background_borderless_material_light.xml
new file mode 100644
index 0000000..3ef6674
--- /dev/null
+++ b/core/res/res/drawable/item_background_borderless_material_light.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ 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
+  -->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/ripple_material_light" />
diff --git a/core/res/res/drawable/item_background_material_dark.xml b/core/res/res/drawable/item_background_material_dark.xml
new file mode 100644
index 0000000..06eb531
--- /dev/null
+++ b/core/res/res/drawable/item_background_material_dark.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/ripple_material_dark">
+  <item android:id="@id/mask">
+    <color android:color="@color/white" />
+  </item>
+</ripple>
diff --git a/core/res/res/drawable/item_background_material_light.xml b/core/res/res/drawable/item_background_material_light.xml
new file mode 100644
index 0000000..2f3d157
--- /dev/null
+++ b/core/res/res/drawable/item_background_material_light.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2014 The Android Open Source Project
+
+     Licensed under the Apache License, Version 2.0 (the "License");
+     you may not use this file except in compliance with the License.
+     You may obtain a copy of the License at
+
+          http://www.apache.org/licenses/LICENSE-2.0
+
+     Unless required by applicable law or agreed to in writing, software
+     distributed under the License is distributed on an "AS IS" BASIS,
+     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+     See the License for the specific language governing permissions and
+     limitations under the License.
+-->
+
+<ripple xmlns:android="http://schemas.android.com/apk/res/android"
+        android:color="@color/ripple_material_light">
+  <item android:id="@id/mask">
+    <color android:color="@color/white" />
+  </item>
+</ripple>
diff --git a/core/res/res/drawable/perm_group_storage.xml b/core/res/res/drawable/perm_group_storage.xml
new file mode 100644
index 0000000..11078d3
--- /dev/null
+++ b/core/res/res/drawable/perm_group_storage.xml
@@ -0,0 +1,24 @@
+<!--
+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.
+-->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:width="48dp"
+        android:height="48dp"
+        android:viewportWidth="48.0"
+        android:viewportHeight="48.0">
+    <path
+            android:pathData="M20,8H8c-2.2,0 -4,1.8 -4,4l0,24c0,2.2 1.8,4 4,4h32c2.2,0 4,-1.8 4,-4V16c0,-2.2 -1.8,-4 -4,-4H24L20,8z"
+            android:fillColor="#FFFFFF"/>
+</vector>
diff --git a/core/res/res/layout/floating_popup_close_overflow_button.xml b/core/res/res/layout/floating_popup_close_overflow_button.xml
index 0dbf7f7..4dae1ae 100644
--- a/core/res/res/layout/floating_popup_close_overflow_button.xml
+++ b/core/res/res/layout/floating_popup_close_overflow_button.xml
@@ -20,6 +20,6 @@
     android:layout_height="match_parent"
     android:minWidth="@dimen/floating_toolbar_menu_button_minimum_width"
     android:minHeight="@dimen/floating_toolbar_height"
-    android:src="?android:attr/actionModeCloseDrawable"
+    android:src="?attr/floatingToolbarCloseDrawable"
     android:contentDescription="@string/floating_toolbar_close_overflow_description"
-    android:background="?attr/selectableItemBackgroundBorderless" />
+    android:background="?attr/floatingToolbarItemBackgroundBorderlessDrawable" />
diff --git a/core/res/res/layout/floating_popup_container.xml b/core/res/res/layout/floating_popup_container.xml
index f37aee1..63dae44 100644
--- a/core/res/res/layout/floating_popup_container.xml
+++ b/core/res/res/layout/floating_popup_container.xml
@@ -24,4 +24,4 @@
     android:elevation="2dp"
     android:focusable="true"
     android:focusableInTouchMode="true"
-    android:background="@drawable/floating_popup_background"/>
+    android:background="?attr/floatingToolbarPopupBackgroundDrawable"/>
diff --git a/core/res/res/layout/floating_popup_menu_button.xml b/core/res/res/layout/floating_popup_menu_button.xml
index b549198..1b58ce5 100644
--- a/core/res/res/layout/floating_popup_menu_button.xml
+++ b/core/res/res/layout/floating_popup_menu_button.xml
@@ -30,5 +30,5 @@
     android:fontFamily="sans-serif-medium"
     android:textSize="@dimen/floating_toolbar_text_size"
     android:textAllCaps="true"
-    android:textColor="?attr/colorForeground"
-    android:background="?attr/selectableItemBackground" />
+    android:textColor="?attr/floatingToolbarForegroundColor"
+    android:background="?attr/floatingToolbarItemBackgroundDrawable" />
diff --git a/core/res/res/layout/floating_popup_menu_image_button.xml b/core/res/res/layout/floating_popup_menu_image_button.xml
index 07eb7a3..1ba7848 100644
--- a/core/res/res/layout/floating_popup_menu_image_button.xml
+++ b/core/res/res/layout/floating_popup_menu_image_button.xml
@@ -32,5 +32,5 @@
         android:paddingEnd="@dimen/floating_toolbar_menu_button_side_padding"
         android:paddingBottom="@dimen/floating_toolbar_menu_image_button_vertical_padding"
         android:scaleType="centerInside"
-        android:background="?attr/selectableItemBackground" />
+        android:background="?attr/floatingToolbarItemBackgroundDrawable" />
 </LinearLayout>
diff --git a/core/res/res/layout/floating_popup_open_overflow_button.xml b/core/res/res/layout/floating_popup_open_overflow_button.xml
index 3027565..f6a3e8d 100644
--- a/core/res/res/layout/floating_popup_open_overflow_button.xml
+++ b/core/res/res/layout/floating_popup_open_overflow_button.xml
@@ -24,6 +24,6 @@
     android:paddingTop="0dp"
     android:paddingBottom="0dp"
     android:paddingEnd="4dp"
-    android:src="@drawable/ic_menu_moreoverflow_material"
+    android:src="?attr/floatingToolbarOpenDrawable"
     android:contentDescription="@string/floating_toolbar_open_overflow_description"
-    android:background="?attr/selectableItemBackgroundBorderless" />
+    android:background="?attr/floatingToolbarItemBackgroundBorderlessDrawable" />
diff --git a/core/res/res/layout/floating_popup_overflow_list_item.xml b/core/res/res/layout/floating_popup_overflow_list_item.xml
index 2ff45bb..22f4e68 100644
--- a/core/res/res/layout/floating_popup_overflow_list_item.xml
+++ b/core/res/res/layout/floating_popup_overflow_list_item.xml
@@ -31,6 +31,6 @@
     android:ellipsize="end"
     android:fontFamily="sans-serif-medium"
     android:textSize="@dimen/floating_toolbar_text_size"
-    android:textColor="?attr/colorForeground"
+    android:textColor="?attr/floatingToolbarForegroundColor"
     android:textAllCaps="true" />
 
diff --git a/core/res/res/values/arrays.xml b/core/res/res/values/arrays.xml
index d5c2d19..a3cc4ae 100644
--- a/core/res/res/values/arrays.xml
+++ b/core/res/res/values/arrays.xml
@@ -310,7 +310,11 @@
        <item>@drawable/fastscroll_label_right_material</item>
        <item>@drawable/fastscroll_thumb_material</item>
        <item>@drawable/fastscroll_track_material</item>
+       <item>@drawable/floating_popup_background_dark</item>
+       <item>@drawable/floating_popup_background_light</item>
        <item>@drawable/ic_ab_back_material</item>
+       <item>@drawable/ic_ab_back_material_dark</item>
+       <item>@drawable/ic_ab_back_material_light</item>
        <item>@drawable/ic_clear_material</item>
        <item>@drawable/ic_commit_search_api_material</item>
        <item>@drawable/ic_dialog_alert_material</item>
@@ -330,7 +334,11 @@
        <item>@drawable/ic_search_api_material</item>
        <item>@drawable/ic_voice_search_api_material</item>
        <item>@drawable/item_background_borderless_material</item>
+       <item>@drawable/item_background_borderless_material_dark</item>
+       <item>@drawable/item_background_borderless_material_light</item>
        <item>@drawable/item_background_material</item>
+       <item>@drawable/item_background_material_dark</item>
+       <item>@drawable/item_background_material_light</item>
        <item>@drawable/list_divider_material</item>
        <item>@drawable/list_section_divider_material</item>
        <item>@drawable/notification_material_action_background</item>
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 52e2cf0..c08d511 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -550,6 +550,17 @@
         <attr name="windowTransitionBackgroundFadeDuration" format="integer"/>
 
         <!-- ============ -->
+        <!-- Floating toolbar styles -->
+        <!-- ============ -->
+       <eat-comment />
+       <attr name="floatingToolbarCloseDrawable" format="reference" />
+       <attr name="floatingToolbarForegroundColor" format="reference|color" />
+       <attr name="floatingToolbarItemBackgroundBorderlessDrawable" format="reference" />
+       <attr name="floatingToolbarItemBackgroundDrawable" format="reference" />
+       <attr name="floatingToolbarOpenDrawable" format="reference" />
+       <attr name="floatingToolbarPopupBackgroundDrawable" format="reference" />
+
+        <!-- ============ -->
         <!-- Alert Dialog styles -->
         <!-- ============ -->
         <eat-comment />
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index db1ac44..e7811df 100755
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -572,6 +572,43 @@
          true here reverses that logic. -->
     <bool name="config_reverseDefaultRotation">false</bool>
 
+    <!-- Sets the minimum and maximum tilt tolerance for each possible rotation.
+         This array consists of 4 pairs of values which specify the minimum and maximum
+         tilt angle at which the device will transition into each rotation.
+
+         The tilt angle represents the direction in which the plane of the screen is facing;
+         it is also known as the angle of elevation.
+
+           -90 degree tilt means that the screen is facing straight down
+                           (the device is being held overhead upside-down)
+             0 degree tilt means that the screen is facing outwards
+                           (the device is being held vertically)
+            90 degree tilt means that the screen is facing straight up
+                           (the device is resting on a flat table)
+
+        The default tolerances are set conservatively such that the device is more
+        likely to remain in its natural orientation than rotate into a counterclockwise,
+        clockwise, or reversed posture (with an especially strong bias against the latter)
+        to prevent accidental rotation while carrying the device in hand.
+
+        These thresholds may need to be tuned when the device is intended to be
+        mounted into a dock with a particularly shallow profile wherein rotation
+        would ordinarily have been suppressed.
+
+        It is helpful to consider the desired behavior both when the device is being
+        held at a positive tilt (typical case) vs. a negative tilt (reading overhead in
+        bed) since they are quite different.  In the overhead case, we typically want
+        the device to more strongly prefer to retain its current configuration (in absence
+        of a clear indication that a rotation is desired) since the user's head and neck may
+        be held at an unusual angle.
+    -->
+    <integer-array name="config_autoRotationTiltTolerance">
+        <!-- rotation:   0 (natural)    --> <item>-25</item> <item>70</item>
+        <!-- rotation:  90 (rotate CCW) --> <item>-25</item> <item>65</item>
+        <!-- rotation: 180 (reverse)    --> <item>-25</item> <item>60</item>
+        <!-- rotation: 270 (rotate CW)  --> <item>-25</item> <item>65</item>
+    </integer-array>
+
     <!-- Lid switch behavior -->
 
     <!-- The number of degrees to rotate the display when the keyboard is open.
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index f6af19c..a6b7e35 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -566,7 +566,12 @@
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_sms">SMS</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_sms">view and manage SMS messages</string>
+    <string name="permgroupdesc_sms">send and view SMS messages</string>
+
+    <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgrouplab_storage">Storage</string>
+    <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permgroupdesc_storage">access photos, media, and files on your device</string>
 
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_dictionary">User Dictionary</string>
@@ -596,7 +601,7 @@
     <!-- Title of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permgrouplab_sensors">Sensors</string>
     <!-- Description of a category of application permissions, listed so the user can choose whether they want to allow the application to do this. -->
-    <string name="permgroupdesc_sensors">access data from sensors and wearable devices</string>
+    <string name="permgroupdesc_sensors">access information about your vital signs and physical activity</string>
 
     <!-- Title for the capability of an accessibility service to retrieve window content. -->
     <string name="capability_title_canRetrieveWindowContent">Retrieve window content</string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index b019adb..361c0bd 100755
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1451,6 +1451,7 @@
   <java-symbol type="anim" name="voice_activity_open_exit" />
   <java-symbol type="anim" name="voice_activity_open_enter" />
 
+  <java-symbol type="array" name="config_autoRotationTiltTolerance" />
   <java-symbol type="array" name="config_keyboardTapVibePattern" />
   <java-symbol type="array" name="config_longPressVibePattern" />
   <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
diff --git a/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index ecf00f0..b7acdd4 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -389,6 +389,14 @@
         <item name="segmentedButtonStyle">@style/SegmentedButton</item>
         <item name="fingerprintAuthDrawable">@drawable/ic_fingerprint</item>
 
+        <!-- Floating toolbar styles -->
+        <item name="floatingToolbarCloseDrawable">@drawable/ic_ab_back_material_dark</item>
+        <item name="floatingToolbarForegroundColor">@color/foreground_material_dark</item>
+        <item name="floatingToolbarItemBackgroundBorderlessDrawable">@drawable/item_background_borderless_material_dark</item>
+        <item name="floatingToolbarItemBackgroundDrawable">@drawable/item_background_material_dark</item>
+        <item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_dark</item>
+        <item name="floatingToolbarPopupBackgroundDrawable">@drawable/floating_popup_background_dark</item>
+
         <!-- SearchView attributes -->
         <item name="searchViewStyle">@style/Widget.Holo.SearchView</item>
         <item name="searchDialogTheme">@style/Theme.SearchBar</item>
@@ -538,6 +546,14 @@
         <item name="mediaRouteButtonStyle">@style/Widget.DeviceDefault.Light.MediaRouteButton</item>
         <item name="findOnPageNextDrawable">@drawable/ic_find_next_holo_light</item>
         <item name="findOnPagePreviousDrawable">@drawable/ic_find_previous_holo_light</item>
+
+        <!-- Floating toolbar styles -->
+        <item name="floatingToolbarCloseDrawable">@drawable/ic_ab_back_material_light</item>
+        <item name="floatingToolbarForegroundColor">@color/foreground_material_light</item>
+        <item name="floatingToolbarItemBackgroundBorderlessDrawable">@drawable/item_background_borderless_material_light</item>
+        <item name="floatingToolbarItemBackgroundDrawable">@drawable/item_background_material_light</item>
+        <item name="floatingToolbarOpenDrawable">@drawable/ic_menu_moreoverflow_material_light</item>
+        <item name="floatingToolbarPopupBackgroundDrawable">@drawable/floating_popup_background_light</item>
     </style>
 
     <!-- Variant of {@link #Theme_Light} with no title bar -->
diff --git a/core/tests/coretests/src/android/os/FileUtilsTest.java b/core/tests/coretests/src/android/os/FileUtilsTest.java
index ee9e2e4..ac5abad 100644
--- a/core/tests/coretests/src/android/os/FileUtilsTest.java
+++ b/core/tests/coretests/src/android/os/FileUtilsTest.java
@@ -232,6 +232,18 @@
         assertEquals("foo_bar__baz", FileUtils.buildValidFatFilename("foo?bar**baz"));
     }
 
+    public void testTrimFilename() throws Exception {
+        assertEquals("short.txt", FileUtils.trimFilename("short.txt", 16));
+        assertEquals("extrem...eme.txt", FileUtils.trimFilename("extremelylongfilename.txt", 16));
+
+        final String unicode = "a\u03C0\u03C0\u03C0\u03C0z";
+        assertEquals("a\u03C0\u03C0\u03C0\u03C0z", FileUtils.trimFilename(unicode, 10));
+        assertEquals("a\u03C0...\u03C0z", FileUtils.trimFilename(unicode, 9));
+        assertEquals("a...\u03C0z", FileUtils.trimFilename(unicode, 8));
+        assertEquals("a...\u03C0z", FileUtils.trimFilename(unicode, 7));
+        assertEquals("a...z", FileUtils.trimFilename(unicode, 6));
+    }
+
     public void testBuildUniqueFile_normal() throws Exception {
         assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test"));
         assertNameEquals("test.jpg", FileUtils.buildUniqueFile(mTarget, "image/jpeg", "test.jpg"));
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/docs/html/distribute/engage/deep-linking.jd b/docs/html/distribute/engage/deep-linking.jd
index 701cb99..713bfbb 100644
--- a/docs/html/distribute/engage/deep-linking.jd
+++ b/docs/html/distribute/engage/deep-linking.jd
@@ -1,7 +1,7 @@
 page.title=Increase Usage with Search
 page.metaDescription=Use search to bring your existing users back into your app.
 page.image=images/cards/google-search_2x.png
-page.tags=engagement, appindexing, search
+page.tags="engagement", "app indexing", "search", "deep linking"
 @jd:body
 
 <p>
@@ -69,7 +69,7 @@
 <div class="resource-widget resource-flow-layout col-13"
   data-query="collection:distribute/engage/appindexing"
   data-sortOrder="-timestamp"
-  data-cardSizes="6x2"
-  data-maxResults="3"></div>
+  data-cardSizes="9x3"
+  data-maxResults="4"></div>
 
 
diff --git a/docs/html/distribute/googleplay/families/about.jd b/docs/html/distribute/googleplay/families/about.jd
index a3ef157..bec9b6a 100644
--- a/docs/html/distribute/googleplay/families/about.jd
+++ b/docs/html/distribute/googleplay/families/about.jd
@@ -154,6 +154,10 @@
   for Families program requirements</a>.
 </p>
 
+<h2 id="optin">
+  Opt-in and FAQs
+</h2>
+
 <p>
   To learn how to opt-in and find more details about the program, visit the
   Google Play Developer <a href=
diff --git a/docs/html/distribute/users/appindexing.jd b/docs/html/distribute/users/appindexing.jd
index 6a3fec6..04114e3 100644
--- a/docs/html/distribute/users/appindexing.jd
+++ b/docs/html/distribute/users/appindexing.jd
@@ -1,6 +1,7 @@
 page.title=Drive installs from Google Search
 page.metaDescription=Surface the content of your apps in Google Search and link it to app installs.
 meta.tags="getusers", "search", "appindexing"
+page.tags="app indexing", "search", "get users"
 page.image=images/cards/google-search_2x.png
 @jd:body
 
diff --git a/docs/html/jd_collections.js b/docs/html/jd_collections.js
index cac93afc..2505746 100644
--- a/docs/html/jd_collections.js
+++ b/docs/html/jd_collections.js
@@ -687,7 +687,8 @@
     "resources": [
       "https://developers.google.com/app-indexing/",
       "https://developers.google.com/app-indexing/webmasters/details",
-      "distribute/engage/deep-linking.html"
+      "distribute/engage/deep-linking.html",
+      "training/app-indexing/index.html"
     ]
   },
   "distribute/users/otas": {
@@ -953,7 +954,8 @@
     "resources": [
       "distribute/engage/intents.html",
       "distribute/engage/deep-linking.html",
-      "distribute/users/appindexing.html"
+      "distribute/users/appindexing.html",
+      "training/app-indexing/index.html"
     ]
   },
   "distribute/engage/intents": {
diff --git a/docs/html/training/app-indexing/index.jd b/docs/html/training/app-indexing/index.jd
index 45afea8..15a6367 100644
--- a/docs/html/training/app-indexing/index.jd
+++ b/docs/html/training/app-indexing/index.jd
@@ -1,6 +1,7 @@
 page.title=Making Your App Content Searchable by Google
-page.tags="app indexing"
-
+page.tags="app indexing", "search"
+meta.tags="getusers", "search","appindexing"
+page.image=images/cards/google-search_2x.png
 trainingnavtop=true
 startpage=true
 
@@ -59,8 +60,8 @@
 </li>
 </ol>
 
-<p>This class shows how to enable deep linking and indexing of your application
-content so that users can open this content directly from mobile search
+<p itemprop="description">This class shows how to enable deep linking and indexing of
+your application content so that users can open this content directly from mobile search
 results.</p>
 
 <h2>Lessons</h2>
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/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/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/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/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/packages/SystemUI/res/layout/mobile_signal_group.xml b/packages/SystemUI/res/layout/mobile_signal_group.xml
index 6a4ac2c..6ae5cf3 100644
--- a/packages/SystemUI/res/layout/mobile_signal_group.xml
+++ b/packages/SystemUI/res/layout/mobile_signal_group.xml
@@ -19,22 +19,25 @@
 -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:id="@+id/mobile_combo"
     android:layout_width="wrap_content"
     android:layout_height="wrap_content"
     >
-    <com.android.systemui.statusbar.AlphaOptimizedImageView
+    <com.android.systemui.statusbar.AnimatedImageView
         android:theme="@style/DualToneLightTheme"
         android:id="@+id/mobile_signal"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
+        systemui:hasOverlappingRendering="false"
         />
-    <com.android.systemui.statusbar.AlphaOptimizedImageView
+    <com.android.systemui.statusbar.AnimatedImageView
         android:theme="@style/DualToneDarkTheme"
         android:id="@+id/mobile_signal_dark"
         android:layout_height="wrap_content"
         android:layout_width="wrap_content"
         android:alpha="0.0"
+        systemui:hasOverlappingRendering="false"
         />
     <ImageView
         android:id="@+id/mobile_type"
diff --git a/packages/SystemUI/res/layout/signal_cluster_view.xml b/packages/SystemUI/res/layout/signal_cluster_view.xml
index 69dcad2..f8bd6fd 100644
--- a/packages/SystemUI/res/layout/signal_cluster_view.xml
+++ b/packages/SystemUI/res/layout/signal_cluster_view.xml
@@ -20,6 +20,7 @@
 <!-- extends LinearLayout -->
 <com.android.systemui.statusbar.SignalClusterView
     xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:systemui="http://schemas.android.com/apk/res-auto"
     android:layout_height="match_parent"
     android:layout_width="wrap_content"
     android:gravity="center_vertical"
@@ -43,6 +44,7 @@
             android:id="@+id/ethernet"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
+            systemui:hasOverlappingRendering="false"
             />
         <com.android.systemui.statusbar.AlphaOptimizedImageView
             android:theme="@style/DualToneDarkTheme"
@@ -50,6 +52,7 @@
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:alpha="0.0"
+            systemui:hasOverlappingRendering="false"
             />
     </FrameLayout>
     <FrameLayout
@@ -62,6 +65,7 @@
             android:id="@+id/wifi_signal"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
+            systemui:hasOverlappingRendering="false"
             />
         <com.android.systemui.statusbar.AlphaOptimizedImageView
             android:theme="@style/DualToneDarkTheme"
@@ -69,6 +73,7 @@
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:alpha="0.0"
+            systemui:hasOverlappingRendering="false"
             />
     </FrameLayout>
     <View
@@ -84,14 +89,17 @@
         >
     </LinearLayout>
     <FrameLayout
+        android:id="@+id/no_sims_combo"
         android:layout_height="wrap_content"
-        android:layout_width="wrap_content">
+        android:layout_width="wrap_content"
+        android:contentDescription="@string/accessibility_no_sims">
         <com.android.systemui.statusbar.AlphaOptimizedImageView
             android:theme="@style/DualToneLightTheme"
             android:id="@+id/no_sims"
             android:layout_height="wrap_content"
             android:layout_width="wrap_content"
             android:src="@drawable/stat_sys_no_sims"
+            systemui:hasOverlappingRendering="false"
             />
         <com.android.systemui.statusbar.AlphaOptimizedImageView
             android:theme="@style/DualToneDarkTheme"
@@ -100,6 +108,7 @@
             android:layout_width="wrap_content"
             android:src="@drawable/stat_sys_no_sims"
             android:alpha="0.0"
+            systemui:hasOverlappingRendering="false"
             />
     </FrameLayout>
     <View
diff --git a/packages/SystemUI/res/layout/status_bar_expanded_header.xml b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
index 0e1517f..7262ed2 100644
--- a/packages/SystemUI/res/layout/status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/status_bar_expanded_header.xml
@@ -162,6 +162,7 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
+        systemui:hasOverlappingRendering="false"
         />
 
     <TextView
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 354b70b..527248c 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -86,5 +86,9 @@
     <declare-styleable name="StatusBarWindowView_Layout">
         <attr name="ignoreRightInset" format="boolean" />
     </declare-styleable>
+
+    <declare-styleable name="AlphaOptimizedImageView">
+        <attr name="hasOverlappingRendering" format="boolean" />
+    </declare-styleable>
 </resources>
 
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index a0b70f0..47c642d 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -374,6 +374,9 @@
     <!-- Content description of the airplane mode icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_airplane_mode">Airplane mode.</string>
 
+    <!-- Content description of the no sim icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
+    <string name="accessibility_no_sims">No SIM card.</string>
+
     <!-- Content description of the carrier network changing icon for accessibility (not shown on the screen). [CHAR LIMIT=NONE] -->
     <string name="accessibility_carrier_network_change_mode">Carrier network changing.</string>
 
@@ -1099,4 +1102,7 @@
     <!-- Accessibility label for hotspot icon [CHAR LIMIT=NONE] -->
     <string name="accessibility_status_bar_hotspot">Hotspot</string>
 
+    <!-- Accessibility label for managed profile icon (not shown on screen) [CHAR LIMIT=NONE] -->
+    <string name="accessibility_managed_profile">Work profile</string>
+
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java
index 858c118..700ea34 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AlphaOptimizedImageView.java
@@ -17,34 +17,49 @@
 package com.android.systemui.statusbar;
 
 import android.content.Context;
+import android.content.res.TypedArray;
 import android.util.AttributeSet;
 import android.widget.ImageView;
 
+import com.android.systemui.R;
+
 /**
- * An ImageView which does not have overlapping rendering commands and therefore does not need a
- * layer when alpha is changed.
+ * An ImageView which supports an attribute specifying whether it has overlapping rendering
+ * commands and therefore does not need a layer when alpha is changed.
  */
-public class AlphaOptimizedImageView extends ImageView
-{
+public class AlphaOptimizedImageView extends ImageView {
+    private final boolean mHasOverlappingRendering;
+
     public AlphaOptimizedImageView(Context context) {
-        super(context);
+        this(context, null /* attrs */);
     }
 
     public AlphaOptimizedImageView(Context context, AttributeSet attrs) {
-        super(context, attrs);
+        this(context, attrs, 0 /* defStyleAttr */);
     }
 
     public AlphaOptimizedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
-        super(context, attrs, defStyleAttr);
+        this(context, attrs, defStyleAttr, 0 /* defStyleRes */);
     }
 
     public AlphaOptimizedImageView(Context context, AttributeSet attrs, int defStyleAttr,
             int defStyleRes) {
         super(context, attrs, defStyleAttr, defStyleRes);
+
+        TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
+                R.styleable.AlphaOptimizedImageView, 0, 0);
+
+        try {
+            // Default to true, which is what View.java defaults to
+            mHasOverlappingRendering = a.getBoolean(
+                    R.styleable.AlphaOptimizedImageView_hasOverlappingRendering, true);
+        } finally {
+            a.recycle();
+        }
     }
 
     @Override
     public boolean hasOverlappingRendering() {
-        return false;
+        return mHasOverlappingRendering;
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
index 9839fe9..90f7c08 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/AnimatedImageView.java
@@ -25,10 +25,15 @@
 import android.widget.RemoteViews.RemoteView;
 
 @RemoteView
-public class AnimatedImageView extends ImageView {
+public class AnimatedImageView extends AlphaOptimizedImageView {
     AnimationDrawable mAnim;
     boolean mAttached;
 
+    // Tracks the last image that was set, so that we don't refresh the image if it is exactly
+    // the same as the previous one. If this is a resid, we track that. If it's a drawable, we
+    // track the hashcode of the drawable.
+    int mDrawableId;
+
     public AnimatedImageView(Context context) {
         super(context);
     }
@@ -43,7 +48,7 @@
             mAnim.stop();
         }
         if (drawable instanceof AnimationDrawable) {
-            mAnim = (AnimationDrawable)drawable;
+            mAnim = (AnimationDrawable) drawable;
             if (isShown()) {
                 mAnim.start();
             }
@@ -54,6 +59,13 @@
 
     @Override
     public void setImageDrawable(Drawable drawable) {
+        if (drawable != null) {
+            if (mDrawableId == drawable.hashCode()) return;
+
+            mDrawableId = drawable.hashCode();
+        } else {
+            mDrawableId = 0;
+        }
         super.setImageDrawable(drawable);
         updateAnim();
     }
@@ -61,6 +73,9 @@
     @Override
     @android.view.RemotableViewMethod
     public void setImageResource(int resid) {
+        if (mDrawableId == resid) return;
+
+        mDrawableId = resid;
         super.setImageResource(resid);
         updateAnim();
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 85b4a64..0b49564 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -24,7 +24,6 @@
 import android.app.Notification;
 import android.app.NotificationManager;
 import android.app.PendingIntent;
-import android.app.RemoteInput;
 import android.app.TaskStackBuilder;
 import android.app.admin.DevicePolicyManager;
 import android.content.BroadcastReceiver;
@@ -102,7 +101,6 @@
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.PreviewInflater;
-import com.android.systemui.statusbar.policy.RemoteInputView;
 import com.android.systemui.statusbar.stack.NotificationStackScrollLayout;
 
 import java.util.ArrayList;
@@ -122,8 +120,6 @@
     // STOPSHIP disable once we resolve b/18102199
     private static final boolean NOTIFICATION_CLICK_DEBUG = true;
 
-    public static final boolean ENABLE_REMOTE_INPUT =
-            Build.IS_DEBUGGABLE && SystemProperties.getBoolean("debug.enable_remote_input", false);
     public static final boolean ENABLE_CHILD_NOTIFICATIONS = Build.IS_DEBUGGABLE
                     && SystemProperties.getBoolean("debug.child_notifs", false);
 
@@ -463,7 +459,7 @@
                 mHandler.post(new Runnable() {
                     @Override
                     public void run() {
-                        processForRemoteInput(sbn.getNotification());
+
                         String key = sbn.getKey();
                         boolean isUpdate = mNotificationData.get(key) != null;
 
@@ -1314,9 +1310,6 @@
         NotificationContentView contentContainerPublic = row.getPublicLayout();
 
         row.setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
-        if (ENABLE_REMOTE_INPUT) {
-            row.setDescendantFocusability(ViewGroup.FOCUS_BEFORE_DESCENDANTS);
-        }
 
         mNotificationClicker.register(row, sbn);
 
@@ -1479,106 +1472,10 @@
         }
         row.setUserLocked(userLocked);
         row.setStatusBarNotification(entry.notification);
-        applyRemoteInput(entry);
+
         return true;
     }
 
-    /**
-     * Adds RemoteInput actions from the WearableExtender; to be removed once more apps support this
-     * via first-class API.
-     *
-     * TODO: Remove once enough apps specify remote inputs on their own.
-     */
-    private void processForRemoteInput(Notification n) {
-        if (!ENABLE_REMOTE_INPUT) return;
-
-        if (n.extras != null && n.extras.containsKey("android.wearable.EXTENSIONS") &&
-                (n.actions == null || n.actions.length == 0)) {
-            Notification.Action viableAction = null;
-            Notification.WearableExtender we = new Notification.WearableExtender(n);
-
-            List<Notification.Action> actions = we.getActions();
-            final int numActions = actions.size();
-
-            for (int i = 0; i < numActions; i++) {
-                Notification.Action action = actions.get(i);
-                RemoteInput[] remoteInputs = action.getRemoteInputs();
-                for (RemoteInput ri : action.getRemoteInputs()) {
-                    if (ri.getAllowFreeFormInput()) {
-                        viableAction = action;
-                        break;
-                    }
-                }
-                if (viableAction != null) {
-                    break;
-                }
-            }
-
-            if (viableAction != null) {
-                Notification stripped = n.clone();
-                Notification.Builder.stripForDelivery(stripped);
-                stripped.actions = new Notification.Action[] { viableAction };
-                stripped.extras.putBoolean("android.rebuild.contentView", true);
-                stripped.contentView = null;
-                stripped.extras.putBoolean("android.rebuild.bigView", true);
-                stripped.bigContentView = null;
-                stripped.extras.putBoolean("android.rebuild.hudView", true);
-                stripped.headsUpContentView = null;
-
-                Notification rebuilt = Notification.Builder.rebuild(mContext, stripped);
-
-                n.actions = rebuilt.actions;
-                n.bigContentView = rebuilt.bigContentView;
-                n.headsUpContentView = rebuilt.headsUpContentView;
-                n.publicVersion = rebuilt.publicVersion;
-            }
-        }
-    }
-
-    private void applyRemoteInput(final Entry entry) {
-        if (!ENABLE_REMOTE_INPUT) return;
-
-        RemoteInput remoteInput = null;
-
-        // See if the notification has exactly one action and this action allows free-form input
-        // TODO: relax restrictions once we support more than one remote input action.
-        Notification.Action[] actions = entry.notification.getNotification().actions;
-        if (actions != null && actions.length == 1) {
-            if (actions[0].getRemoteInputs() != null) {
-                for (RemoteInput ri : actions[0].getRemoteInputs()) {
-                    if (ri.getAllowFreeFormInput()) {
-                        remoteInput = ri;
-                        break;
-                    }
-                }
-            }
-        }
-
-        // See if we have somewhere to put that remote input
-        if (remoteInput != null) {
-            View bigContentView = entry.getExpandedContentView();
-            if (bigContentView != null) {
-                inflateRemoteInput(bigContentView, remoteInput, actions);
-            }
-            View headsUpContentView = entry.getHeadsUpContentView();
-            if (headsUpContentView != null) {
-                inflateRemoteInput(headsUpContentView, remoteInput, actions);
-            }
-        }
-
-    }
-
-    private void inflateRemoteInput(View view, RemoteInput remoteInput,
-            Notification.Action[] actions) {
-        View actionContainerCandidate = view.findViewById(com.android.internal.R.id.actions);
-        if (actionContainerCandidate instanceof ViewGroup) {
-            ViewGroup actionContainer = (ViewGroup) actionContainerCandidate;
-            actionContainer.removeAllViews();
-            actionContainer.addView(
-                    RemoteInputView.inflate(mContext, actionContainer, actions[0], remoteInput));
-        }
-    }
-
     private final class NotificationClicker implements View.OnClickListener {
         public void onClick(final View v) {
             if (!(v instanceof ExpandableNotificationRow)) {
@@ -2072,8 +1969,6 @@
         entry.row.setStatusBarNotification(notification);
         entry.row.notifyContentUpdated();
         entry.row.resetHeight();
-
-        applyRemoteInput(entry);
     }
 
     protected void notifyHeadsUpScreenOff() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
index 2f63c73..ff7b37f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/SignalClusterView.java
@@ -80,6 +80,7 @@
     private float mDarkIntensity;
 
     ViewGroup mEthernetGroup, mWifiGroup;
+    View mNoSimsCombo;
     ImageView mVpn, mEthernet, mWifi, mAirplane, mNoSims, mEthernetDark, mWifiDark, mNoSimsDark;
     View mWifiAirplaneSpacer;
     View mWifiSignalSpacer;
@@ -162,6 +163,7 @@
         mAirplane       = (ImageView) findViewById(R.id.airplane);
         mNoSims         = (ImageView) findViewById(R.id.no_sims);
         mNoSimsDark     = (ImageView) findViewById(R.id.no_sims_dark);
+        mNoSimsCombo    =             findViewById(R.id.no_sims_combo);
         mWifiAirplaneSpacer =         findViewById(R.id.wifi_airplane_spacer);
         mWifiSignalSpacer =           findViewById(R.id.wifi_signal_spacer);
         mMobileSignalGroup = (LinearLayout) findViewById(R.id.mobile_signal_group);
@@ -416,8 +418,7 @@
             mWifiSignalSpacer.setVisibility(View.GONE);
         }
 
-        mNoSims.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
-        mNoSimsDark.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
+        mNoSimsCombo.setVisibility(mNoSimsVisible ? View.VISIBLE : View.GONE);
 
         boolean anythingVisible = mNoSimsVisible || mWifiVisible || mIsAirplaneMode
                 || anyMobileVisible || mVpnVisible || mEthernetVisible;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 6a6266e..59e1bba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -168,7 +168,8 @@
         mHotspot.addCallback(mHotspotCallback);
 
         // managed profile
-        mService.setIcon(SLOT_MANAGED_PROFILE, R.drawable.stat_sys_managed_profile_status, 0, null);
+        mService.setIcon(SLOT_MANAGED_PROFILE, R.drawable.stat_sys_managed_profile_status, 0,
+                mContext.getString(R.string.accessibility_managed_profile));
         mService.setIconVisibility(SLOT_MANAGED_PROFILE, false);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 58017d0..0d816dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -119,8 +119,7 @@
 
     private void applyFocusableFlag(State state) {
         boolean panelFocusable = state.statusBarFocusable && state.panelExpanded;
-        if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing
-                || BaseStatusBar.ENABLE_REMOTE_INPUT && panelFocusable) {
+        if (state.keyguardShowing && state.keyguardNeedsInput && state.bouncerShowing) {
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
             mLpChanged.flags &= ~WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM;
         } else if (state.isKeyguardShowingAndNotOccluded() || panelFocusable) {
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/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/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/policy/WindowOrientationListener.java b/services/core/java/com/android/server/policy/WindowOrientationListener.java
index c8fd82e..147efdd 100644
--- a/services/core/java/com/android/server/policy/WindowOrientationListener.java
+++ b/services/core/java/com/android/server/policy/WindowOrientationListener.java
@@ -24,10 +24,10 @@
 import android.os.Handler;
 import android.os.SystemClock;
 import android.os.SystemProperties;
-import android.util.Log;
 import android.util.Slog;
 
 import java.io.PrintWriter;
+import java.util.Arrays;
 
 /**
  * A special helper class used by the WindowManager
@@ -40,8 +40,6 @@
  *
  * You can also visualize the behavior of the WindowOrientationListener.
  * Refer to frameworks/base/tools/orientationplot/README.txt for details.
- *
- * @hide
  */
 public abstract class WindowOrientationListener {
     private static final String TAG = "WindowOrientationListener";
@@ -90,7 +88,7 @@
                 ? Sensor.TYPE_GRAVITY : Sensor.TYPE_ACCELEROMETER);
         if (mSensor != null) {
             // Create listener only if sensors do exist
-            mSensorEventListener = new SensorEventListenerImpl();
+            mSensorEventListener = new SensorEventListenerImpl(context);
         }
     }
 
@@ -101,12 +99,12 @@
     public void enable() {
         synchronized (mLock) {
             if (mSensor == null) {
-                Log.w(TAG, "Cannot detect sensors. Not enabled");
+                Slog.w(TAG, "Cannot detect sensors. Not enabled");
                 return;
             }
             if (mEnabled == false) {
                 if (LOG) {
-                    Log.d(TAG, "WindowOrientationListener enabled");
+                    Slog.d(TAG, "WindowOrientationListener enabled");
                 }
                 mSensorEventListener.resetLocked();
                 mSensorManager.registerListener(mSensorEventListener, mSensor, mRate, mHandler);
@@ -121,12 +119,12 @@
     public void disable() {
         synchronized (mLock) {
             if (mSensor == null) {
-                Log.w(TAG, "Cannot detect sensors. Invalid disable");
+                Slog.w(TAG, "Cannot detect sensors. Invalid disable");
                 return;
             }
             if (mEnabled == true) {
                 if (LOG) {
-                    Log.d(TAG, "WindowOrientationListener disabled");
+                    Slog.d(TAG, "WindowOrientationListener disabled");
                 }
                 mSensorManager.unregisterListener(mSensorEventListener);
                 mEnabled = false;
@@ -296,7 +294,7 @@
         // If the tilt angle remains greater than the specified angle for a minimum of
         // the specified time, then the device is deemed to be lying flat
         // (just chillin' on a table).
-        private static final float FLAT_ANGLE = 75;
+        private static final float FLAT_ANGLE = 80;
         private static final long FLAT_TIME_NANOS = 1000 * NANOS_PER_MS;
 
         // If the tilt angle has increased by at least delta degrees within the specified amount
@@ -361,8 +359,24 @@
             SensorManager.STANDARD_GRAVITY + ACCELERATION_TOLERANCE;
 
         // Maximum absolute tilt angle at which to consider orientation data.  Beyond this (i.e.
-        // when screen is facing the sky or ground), we completely ignore orientation data.
-        private static final int MAX_TILT = 75;
+        // when screen is facing the sky or ground), we completely ignore orientation data
+        // because it's too unstable.
+        private static final int MAX_TILT = 80;
+
+        // The tilt angle below which we conclude that the user is holding the device
+        // overhead reading in bed and lock into that state.
+        private static final int TILT_OVERHEAD_ENTER = -40;
+
+        // The tilt angle above which we conclude that the user would like a rotation
+        // change to occur and unlock from the overhead state.
+        private static final int TILT_OVERHEAD_EXIT = -15;
+
+        // The gap angle in degrees between adjacent orientation angles for hysteresis.
+        // This creates a "dead zone" between the current orientation and a proposed
+        // adjacent orientation.  No orientation proposal is made when the orientation
+        // angle is within the gap between the current orientation and the adjacent
+        // orientation.
+        private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45;
 
         // The tilt angle range in degrees for each orientation.
         // Beyond these tilt angles, we don't even consider transitioning into the
@@ -375,28 +389,13 @@
         // facing up (resting on a table).
         // The ideal tilt angle is 0 (when the device is vertical) so the limits establish
         // how close to vertical the device must be in order to change orientation.
-        private final int[][] TILT_TOLERANCE = new int[][] {
-            /* ROTATION_0   */ { -25, 70 },
+        private final int[][] mTiltToleranceConfig = new int[][] {
+            /* ROTATION_0   */ { -25, 70 }, // note: these are overridden by config.xml
             /* ROTATION_90  */ { -25, 65 },
             /* ROTATION_180 */ { -25, 60 },
             /* ROTATION_270 */ { -25, 65 }
         };
 
-        // The tilt angle below which we conclude that the user is holding the device
-        // overhead reading in bed and lock into that state.
-        private final int TILT_OVERHEAD_ENTER = -40;
-
-        // The tilt angle above which we conclude that the user would like a rotation
-        // change to occur and unlock from the overhead state.
-        private final int TILT_OVERHEAD_EXIT = -15;
-
-        // The gap angle in degrees between adjacent orientation angles for hysteresis.
-        // This creates a "dead zone" between the current orientation and a proposed
-        // adjacent orientation.  No orientation proposal is made when the orientation
-        // angle is within the gap between the current orientation and the adjacent
-        // orientation.
-        private static final int ADJACENT_ORIENTATION_ANGLE_GAP = 45;
-
         // Timestamp and value of the last accelerometer sample.
         private long mLastFilteredTimestampNanos;
         private float mLastFilteredX, mLastFilteredY, mLastFilteredZ;
@@ -430,11 +429,32 @@
         private boolean mOverhead;
 
         // History of observed tilt angles.
-        private static final int TILT_HISTORY_SIZE = 40;
+        private static final int TILT_HISTORY_SIZE = 200;
         private float[] mTiltHistory = new float[TILT_HISTORY_SIZE];
         private long[] mTiltHistoryTimestampNanos = new long[TILT_HISTORY_SIZE];
         private int mTiltHistoryIndex;
 
+        public SensorEventListenerImpl(Context context) {
+            // Load tilt tolerance configuration.
+            int[] tiltTolerance = context.getResources().getIntArray(
+                    com.android.internal.R.array.config_autoRotationTiltTolerance);
+            if (tiltTolerance.length == 8) {
+                for (int i = 0; i < 4; i++) {
+                    int min = tiltTolerance[i * 2];
+                    int max = tiltTolerance[i * 2 + 1];
+                    if (min >= -90 && min <= max && max <= 90) {
+                        mTiltToleranceConfig[i][0] = min;
+                        mTiltToleranceConfig[i][1] = max;
+                    } else {
+                        Slog.wtf(TAG, "config_autoRotationTiltTolerance contains invalid range: "
+                                + "min=" + min + ", max=" + max);
+                    }
+                }
+            } else {
+                Slog.wtf(TAG, "config_autoRotationTiltTolerance should have exactly 8 elements");
+            }
+        }
+
         public int getProposedRotationLocked() {
             return mProposedRotation;
         }
@@ -451,6 +471,18 @@
             pw.println(prefix + "mAccelerating=" + mAccelerating);
             pw.println(prefix + "mOverhead=" + mOverhead);
             pw.println(prefix + "mTouched=" + mTouched);
+            pw.print(prefix + "mTiltToleranceConfig=[");
+            for (int i = 0; i < 4; i++) {
+                if (i != 0) {
+                    pw.print(", ");
+                }
+                pw.print("[");
+                pw.print(mTiltToleranceConfig[i][0]);
+                pw.print(", ");
+                pw.print(mTiltToleranceConfig[i][1]);
+                pw.print("]");
+            }
+            pw.println("]");
         }
 
         @Override
@@ -658,8 +690,8 @@
          * Returns true if the tilt angle is acceptable for a given predicted rotation.
          */
         private boolean isTiltAngleAcceptableLocked(int rotation, int tiltAngle) {
-            return tiltAngle >= TILT_TOLERANCE[rotation][0]
-                    && tiltAngle <= TILT_TOLERANCE[rotation][1];
+            return tiltAngle >= mTiltToleranceConfig[rotation][0]
+                    && tiltAngle <= mTiltToleranceConfig[rotation][1];
         }
 
         /**
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 1802301..1b63ca0 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -577,8 +577,10 @@
         public SettingsObserver() {
             super(new Handler());
             ContentResolver resolver = mContext.getContentResolver();
-            resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this);
-            resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this);
+            resolver.registerContentObserver(mShowImeWithHardKeyboardUri, false, this,
+                    UserHandle.USER_ALL);
+            resolver.registerContentObserver(mDisplayInversionEnabledUri, false, this,
+                    UserHandle.USER_ALL);
         }
 
         @Override
@@ -5917,11 +5919,15 @@
         if (mContext.getResources().getConfiguration().isScreenRound()
                 && mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_windowShowCircularMask)) {
+            final int currentUserId;
+            synchronized(mWindowMap) {
+                currentUserId = mCurrentUserId;
+            }
             // Device configuration calls for a circular display mask, but we only enable the mask
             // if the accessibility color inversion feature is disabled, as the inverted mask
             // causes artifacts.
             int inversionState = Settings.Secure.getIntForUser(mContext.getContentResolver(),
-                    Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, mCurrentUserId);
+                    Settings.Secure.ACCESSIBILITY_DISPLAY_INVERSION_ENABLED, 0, currentUserId);
             int showMask = (inversionState == 1) ? 0 : 1;
             Message m = mH.obtainMessage(H.SHOW_CIRCULAR_DISPLAY_MASK);
             m.arg1 = showMask;
@@ -7422,10 +7428,10 @@
     }
 
     public void updateShowImeWithHardKeyboard() {
-        final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
-                mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
-                mCurrentUserId) == 1;
         synchronized (mWindowMap) {
+            final boolean showImeWithHardKeyboard = Settings.Secure.getIntForUser(
+                    mContext.getContentResolver(), Settings.Secure.SHOW_IME_WITH_HARD_KEYBOARD, 0,
+                    mCurrentUserId) == 1;
             if (mShowImeWithHardKeyboard != showImeWithHardKeyboard) {
                 mShowImeWithHardKeyboard = showImeWithHardKeyboard;
                 mH.sendEmptyMessage(H.SEND_NEW_CONFIGURATION);
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 2753700..ea66a04 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -21,6 +21,9 @@
 import static android.app.admin.DevicePolicyManager.WIPE_EXTERNAL_STORAGE;
 import static android.app.admin.DevicePolicyManager.WIPE_RESET_PROTECTION_DATA;
 import static android.content.pm.PackageManager.GET_UNINSTALLED_PACKAGES;
+import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
+import static org.xmlpull.v1.XmlPullParser.END_TAG;
+import static org.xmlpull.v1.XmlPullParser.TEXT;
 
 import android.Manifest.permission;
 import android.accessibilityservice.AccessibilityServiceInfo;
@@ -90,19 +93,19 @@
 import android.security.IKeyChainService;
 import android.security.KeyChain;
 import android.security.KeyChain.KeyChainConnection;
-import android.text.TextUtils;
 import android.service.persistentdata.PersistentDataBlockManager;
+import android.text.TextUtils;
 import android.util.Log;
 import android.util.PrintWriterPrinter;
 import android.util.Printer;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
+import android.view.IWindowManager;
 import android.view.accessibility.AccessibilityManager;
 import android.view.accessibility.IAccessibilityManager;
 import android.view.inputmethod.InputMethodInfo;
 import android.view.inputmethod.InputMethodManager;
-import android.view.IWindowManager;
 
 import com.android.internal.R;
 import com.android.internal.os.storage.ExternalStorageFormatter;
@@ -117,11 +120,6 @@
 import com.android.server.devicepolicy.DevicePolicyManagerService.ActiveAdmin.TrustAgentInfo;
 
 import org.xmlpull.v1.XmlPullParser;
-
-import static org.xmlpull.v1.XmlPullParser.END_DOCUMENT;
-import static org.xmlpull.v1.XmlPullParser.END_TAG;
-import static org.xmlpull.v1.XmlPullParser.TEXT;
-
 import org.xmlpull.v1.XmlPullParserException;
 import org.xmlpull.v1.XmlSerializer;
 
@@ -178,6 +176,7 @@
             = "com.android.server.ACTION_EXPIRED_PASSWORD_NOTIFICATION";
 
     private static final int MONITORING_CERT_NOTIFICATION_ID = R.string.ssl_ca_cert_warning;
+    private static final int PROFILE_WIPED_NOTIFICATION_ID = 1001;
 
     private static final boolean DBG = false;
 
@@ -354,6 +353,7 @@
                 if (DBG) Slog.v(LOG_TAG, "Sending password expiration notifications for action "
                         + action + " for user " + userHandle);
                 mHandler.post(new Runnable() {
+                    @Override
                     public void run() {
                         handlePasswordExpirationNotification(userHandle);
                     }
@@ -1929,6 +1929,7 @@
      * @param adminReceiver The admin to add
      * @param refreshing true = update an active admin, no error
      */
+    @Override
     public void setActiveAdmin(ComponentName adminReceiver, boolean refreshing, int userHandle) {
         if (!mHasFeature) {
             return;
@@ -1980,6 +1981,7 @@
         }
     }
 
+    @Override
     public boolean isAdminActive(ComponentName adminReceiver, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -2002,6 +2004,7 @@
         }
     }
 
+    @Override
     public boolean hasGrantedPolicy(ComponentName adminReceiver, int policyId, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -2016,6 +2019,7 @@
         }
     }
 
+    @Override
     @SuppressWarnings("unchecked")
     public List<ComponentName> getActiveAdmins(int userHandle) {
         if (!mHasFeature) {
@@ -2037,6 +2041,7 @@
         }
     }
 
+    @Override
     public boolean packageHasActiveAdmins(String packageName, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -2054,6 +2059,7 @@
         }
     }
 
+    @Override
     public void removeActiveAdmin(ComponentName adminReceiver, int userHandle) {
         if (!mHasFeature) {
             return;
@@ -2081,6 +2087,7 @@
         }
     }
 
+    @Override
     public void setPasswordQuality(ComponentName who, int quality) {
         if (!mHasFeature) {
             return;
@@ -2099,6 +2106,7 @@
         }
     }
 
+    @Override
     public int getPasswordQuality(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
@@ -2128,6 +2136,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumLength(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2144,6 +2153,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumLength(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2173,6 +2183,7 @@
         }
     }
 
+    @Override
     public void setPasswordHistoryLength(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2189,6 +2200,7 @@
         }
     }
 
+    @Override
     public int getPasswordHistoryLength(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2218,6 +2230,7 @@
         }
     }
 
+    @Override
     public void setPasswordExpirationTimeout(ComponentName who, long timeout) {
         if (!mHasFeature) {
             return;
@@ -2247,6 +2260,7 @@
      * Return a single admin's expiration cycle time, or the min of all cycle times.
      * Returns 0 if not configured.
      */
+    @Override
     public long getPasswordExpirationTimeout(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0L;
@@ -2373,6 +2387,7 @@
         return timeout;
     }
 
+    @Override
     public long getPasswordExpiration(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0L;
@@ -2383,6 +2398,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumUpperCase(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2399,6 +2415,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumUpperCase(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2428,6 +2445,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumLowerCase(ComponentName who, int length) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         final int userHandle = UserHandle.getCallingUserId();
@@ -2441,6 +2459,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumLowerCase(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2470,6 +2489,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumLetters(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2486,6 +2506,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumLetters(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2518,6 +2539,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumNumeric(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2534,6 +2556,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumNumeric(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2566,6 +2589,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumSymbols(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2582,6 +2606,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumSymbols(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2614,6 +2639,7 @@
         }
     }
 
+    @Override
     public void setPasswordMinimumNonLetter(ComponentName who, int length) {
         if (!mHasFeature) {
             return;
@@ -2630,6 +2656,7 @@
         }
     }
 
+    @Override
     public int getPasswordMinimumNonLetter(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -2662,6 +2689,7 @@
         }
     }
 
+    @Override
     public boolean isActivePasswordSufficient(int userHandle) {
         if (!mHasFeature) {
             return true;
@@ -2696,6 +2724,7 @@
         }
     }
 
+    @Override
     public int getCurrentFailedPasswordAttempts(int userHandle) {
         synchronized (this) {
             // This API can only be called by an active device admin,
@@ -2712,6 +2741,7 @@
         }
     }
 
+    @Override
     public void setMaximumFailedPasswordsForWipe(ComponentName who, int num) {
         if (!mHasFeature) {
             return;
@@ -2786,6 +2816,7 @@
         return strictestAdmin;
     }
 
+    @Override
     public boolean resetPassword(String passwordOrNull, int flags) {
         if (!mHasFeature) {
             return false;
@@ -2938,6 +2969,7 @@
         }
     }
 
+    @Override
     public boolean getDoNotAskCredentialsOnBoot() {
         mContext.enforceCallingOrSelfPermission(
                 android.Manifest.permission.QUERY_DO_NOT_ASK_CREDENTIALS_ON_BOOT, null);
@@ -2947,6 +2979,7 @@
         }
     }
 
+    @Override
     public void setMaximumTimeToLock(ComponentName who, long timeMs) {
         if (!mHasFeature) {
             return;
@@ -2988,6 +3021,7 @@
         }
     }
 
+    @Override
     public long getMaximumTimeToLock(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -3020,6 +3054,7 @@
         }
     }
 
+    @Override
     public void lockNow() {
         if (!mHasFeature) {
             return;
@@ -3336,14 +3371,19 @@
             wipeDataLocked(wipeExtRequested, reason);
         } else {
             mHandler.post(new Runnable() {
+                @Override
                 public void run() {
                     try {
                         IActivityManager am = ActivityManagerNative.getDefault();
                         if (am.getCurrentUser().id == userHandle) {
                             am.switchUser(UserHandle.USER_OWNER);
                         }
+
+                        boolean isManagedProfile = isManagedProfile(userHandle);
                         if (!mUserManager.removeUser(userHandle)) {
                             Slog.w(LOG_TAG, "Couldn't remove user " + userHandle);
+                        } else if (isManagedProfile) {
+                            sendWipeProfileNotification();
                         }
                     } catch (RemoteException re) {
                         // Shouldn't happen
@@ -3353,6 +3393,19 @@
         }
     }
 
+    private void sendWipeProfileNotification() {
+        String contentText = mContext.getString(R.string.work_profile_deleted_description_dpm_wipe);
+        Notification notification = new Notification.Builder(mContext)
+                .setSmallIcon(android.R.drawable.stat_sys_warning)
+                .setContentTitle(mContext.getString(R.string.work_profile_deleted))
+                .setContentText(contentText)
+                .setColor(mContext.getColor(R.color.system_notification_accent_color))
+                .setStyle(new Notification.BigTextStyle().bigText(contentText))
+                .build();
+        getNotificationManager().notify(PROFILE_WIPED_NOTIFICATION_ID, notification);
+    }
+
+    @Override
     public void getRemoveWarning(ComponentName comp, final RemoteCallback result, int userHandle) {
         if (!mHasFeature) {
             return;
@@ -3386,6 +3439,7 @@
         }
     }
 
+    @Override
     public void setActivePasswordState(int quality, int length, int letters, int uppercase,
             int lowercase, int numbers, int symbols, int nonletter, int userHandle) {
         if (!mHasFeature) {
@@ -3455,6 +3509,7 @@
             }
     }
 
+    @Override
     public void reportFailedPasswordAttempt(int userHandle) {
         enforceCrossUserPermission(userHandle);
         enforceNotManagedProfile(userHandle, "report failed password attempt");
@@ -3496,6 +3551,7 @@
         }
     }
 
+    @Override
     public void reportSuccessfulPasswordAttempt(int userHandle) {
         enforceCrossUserPermission(userHandle);
         mContext.enforceCallingOrSelfPermission(
@@ -3521,6 +3577,7 @@
         }
     }
 
+    @Override
     public ComponentName setGlobalProxy(ComponentName who, String proxySpec,
             String exclusionList) {
         if (!mHasFeature) {
@@ -3575,6 +3632,7 @@
         }
     }
 
+    @Override
     public ComponentName getGlobalProxyAdmin(int userHandle) {
         if (!mHasFeature) {
             return null;
@@ -3598,6 +3656,7 @@
         return null;
     }
 
+    @Override
     public void setRecommendedGlobalProxy(ComponentName who, ProxyInfo proxyInfo) {
         synchronized (this) {
             getActiveAdminForCallerLocked(who, DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
@@ -3659,6 +3718,7 @@
      * Set the storage encryption request for a single admin.  Returns the new total request
      * status (for all admins).
      */
+    @Override
     public int setStorageEncryption(ComponentName who, boolean encrypt) {
         if (!mHasFeature) {
             return DevicePolicyManager.ENCRYPTION_STATUS_UNSUPPORTED;
@@ -3711,6 +3771,7 @@
      * Get the current storage encryption request status for a given admin, or aggregate of all
      * active admins.
      */
+    @Override
     public boolean getStorageEncryption(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -3740,6 +3801,7 @@
     /**
      * Get the current encryption status of the device.
      */
+    @Override
     public int getStorageEncryptionStatus(int userHandle) {
         if (!mHasFeature) {
             // Ok to return current status.
@@ -3794,6 +3856,7 @@
     /**
      * Set whether the screen capture is disabled for the user managed by the specified admin.
      */
+    @Override
     public void setScreenCaptureDisabled(ComponentName who, boolean disabled) {
         if (!mHasFeature) {
             return;
@@ -3815,6 +3878,7 @@
      * Returns whether or not screen capture is disabled for a given admin, or disabled for any
      * active admin (if given admin is null).
      */
+    @Override
     public boolean getScreenCaptureDisabled(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -3851,6 +3915,7 @@
     /**
      * Set whether auto time is required by the specified admin (must be device owner).
      */
+    @Override
     public void setAutoTimeRequired(ComponentName who, boolean required) {
         if (!mHasFeature) {
             return;
@@ -3881,6 +3946,7 @@
     /**
      * Returns whether or not auto time is required by the device owner.
      */
+    @Override
     public boolean getAutoTimeRequired() {
         if (!mHasFeature) {
             return false;
@@ -3901,6 +3967,7 @@
     /**
      * Disables all device cameras according to the specified admin.
      */
+    @Override
     public void setCameraDisabled(ComponentName who, boolean disabled) {
         if (!mHasFeature) {
             return;
@@ -3922,6 +3989,7 @@
      * Gets whether or not all device cameras are disabled for a given admin, or disabled for any
      * active admins.
      */
+    @Override
     public boolean getCameraDisabled(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return false;
@@ -3948,6 +4016,7 @@
     /**
      * Selectively disable keyguard features.
      */
+    @Override
     public void setKeyguardDisabledFeatures(ComponentName who, int which) {
         if (!mHasFeature) {
             return;
@@ -3972,6 +4041,7 @@
      * Gets the disabled state for features in keyguard for the given admin,
      * or the aggregate of all active admins if who is null.
      */
+    @Override
     public int getKeyguardDisabledFeatures(ComponentName who, int userHandle) {
         if (!mHasFeature) {
             return 0;
@@ -4735,6 +4805,7 @@
         }
     }
 
+    @Override
     public void setTrustAgentConfiguration(ComponentName admin, ComponentName agent,
             PersistableBundle args) {
         if (!mHasFeature) {
@@ -4753,6 +4824,7 @@
         }
     }
 
+    @Override
     public List<PersistableBundle> getTrustAgentConfiguration(ComponentName admin,
             ComponentName agent, int userHandle) {
         if (!mHasFeature) {
@@ -4834,6 +4906,7 @@
         }
     }
 
+    @Override
     public void addCrossProfileIntentFilter(ComponentName who, IntentFilter filter, int flags) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         int callingUserId = UserHandle.getCallingUserId();
@@ -4859,6 +4932,7 @@
         }
     }
 
+    @Override
     public void clearCrossProfileIntentFilters(ComponentName who) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         int callingUserId = UserHandle.getCallingUserId();
@@ -5779,6 +5853,7 @@
      * This function can only be called by the device owner.
      * @param packages The list of packages allowed to enter lock task mode.
      */
+    @Override
     public void setLockTaskPackages(ComponentName who, String[] packages)
             throws SecurityException {
         Preconditions.checkNotNull(who, "ComponentName is null");
@@ -5802,6 +5877,7 @@
     /**
      * This function returns the list of components allowed to start the task lock mode.
      */
+    @Override
     public String[] getLockTaskPackages(ComponentName who) {
         Preconditions.checkNotNull(who, "ComponentName is null");
         synchronized (this) {
@@ -5822,6 +5898,7 @@
      * lock task mode.
      * @param pkg The package to check
      */
+    @Override
     public boolean isLockTaskPermitted(String pkg) {
         // Get current user's devicepolicy
         int uid = Binder.getCallingUid();
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/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
index 4cdf254..b0fca95 100644
--- a/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
+++ b/services/voiceinteraction/java/com/android/server/voiceinteraction/VoiceInteractionManagerService.java
@@ -839,7 +839,8 @@
                 super(handler);
                 ContentResolver resolver = mContext.getContentResolver();
                 resolver.registerContentObserver(Settings.Secure.getUriFor(
-                        Settings.Secure.VOICE_INTERACTION_SERVICE), false, this);
+                        Settings.Secure.VOICE_INTERACTION_SERVICE), false, this,
+                        UserHandle.USER_ALL);
             }
 
             @Override public void onChange(boolean selfChange) {
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/telephony/java/com/android/internal/telephony/IMms.aidl b/telephony/java/com/android/internal/telephony/IMms.aidl
index 49ac400..fa5073e 100644
--- a/telephony/java/com/android/internal/telephony/IMms.aidl
+++ b/telephony/java/com/android/internal/telephony/IMms.aidl
@@ -34,8 +34,7 @@
      *  PDU format
      * @param locationUrl the optional location url for where this message should be sent to
      * @param configOverrides the carrier-specific messaging configuration values to override for
-     *  sending the message. See {@link android.telephony.MessagingConfigurationManager} for the
-     *  value names and types.
+     *  sending the message. See {@link android.telephony.SmsManager} for the value names and types.
      * @param sentIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is successfully sent, or failed
      */
@@ -51,8 +50,8 @@
      *  from the MMS WAP push notification
      * @param contentUri a contentUri to which the downloaded MMS message will be written
      * @param configOverrides the carrier-specific messaging configuration values to override for
-     *  downloading the message. See {@link android.telephony.MessagingConfigurationManager} for the
-     *  value names and types.
+     *  downloading the message. See {@link android.telephony.SmsManager} for the value names and
+     *  types.
      * @param downloadedIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is downloaded, or the download is failed
      */
@@ -165,8 +164,7 @@
      * @param callingPkg the package name of the calling app
      * @param messageUri the URI of the stored message
      * @param configOverrides the carrier-specific messaging configuration values to override for
-     *  sending the message. See {@link android.telephony.MessagingConfigurationManager} for the
-     *  value names and types.
+     *  sending the message. See {@link android.telephony.SmsManager} for the value names and types.
      * @param sentIntent if not NULL this <code>PendingIntent</code> is
      *  broadcast when the message is successfully sent, or failed
      */
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);
             }
         },
diff --git a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
index 32ee9e8..6767a07 100644
--- a/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
+++ b/tools/layoutlib/bridge/src/android/view/BridgeInflater.java
@@ -22,6 +22,7 @@
 import com.android.ide.common.rendering.api.ResourceReference;
 import com.android.ide.common.rendering.api.ResourceValue;
 import com.android.layoutlib.bridge.Bridge;
+import com.android.layoutlib.bridge.BridgeConstants;
 import com.android.layoutlib.bridge.android.BridgeContext;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.impl.ParserFactory;
@@ -234,6 +235,13 @@
             if (viewKey != null) {
                 bc.addViewKey(view, viewKey);
             }
+            String scrollPos = attrs.getAttributeValue(BridgeConstants.NS_RESOURCES, "scrollY");
+            if (scrollPos != null) {
+                if (scrollPos.endsWith("px")) {
+                    int value = Integer.parseInt(scrollPos.substring(0, scrollPos.length() - 2));
+                    bc.setScrollYPos(view, value);
+                }
+            }
         }
     }
 
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
index a2518fa..6be5a95 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/BridgeContext.java
@@ -37,6 +37,7 @@
 import org.xmlpull.v1.XmlPullParserException;
 
 import android.annotation.Nullable;
+import android.annotation.NonNull;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -125,6 +126,7 @@
     private final LayoutlibCallback mLayoutlibCallback;
     private final WindowManager mWindowManager;
     private final DisplayManager mDisplayManager;
+    private final HashMap<View, Integer> mScrollYPos = new HashMap<View, Integer>();
 
     private Resources.Theme mTheme;
 
@@ -1738,4 +1740,13 @@
         // pass
         return new File[0];
     }
+
+    public void setScrollYPos(@NonNull View view, int scrollPos) {
+        mScrollYPos.put(view, scrollPos);
+    }
+
+    public int getScrollYPos(@NonNull View view) {
+        Integer pos = mScrollYPos.get(view);
+        return pos != null ? pos : 0;
+    }
 }
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java
new file mode 100644
index 0000000..0426907
--- /dev/null
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/android/support/DesignLibUtil.java
@@ -0,0 +1,65 @@
+/*
+ * 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.android.layoutlib.bridge.android.support;
+
+import com.android.ide.common.rendering.api.LayoutLog;
+import com.android.layoutlib.bridge.Bridge;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.view.View;
+
+import java.lang.reflect.Method;
+
+import static com.android.layoutlib.bridge.util.ReflectionUtils.ReflectionException;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.getMethod;
+import static com.android.layoutlib.bridge.util.ReflectionUtils.invoke;
+
+/**
+ * Utility class for working with the design support lib.
+ */
+public class DesignLibUtil {
+
+    private static final String PKG_PREFIX = "android.support.design.widget.";
+    public static final String CN_COORDINATOR_LAYOUT = PKG_PREFIX + "CoordinatorLayout";
+    public static final String CN_APPBAR_LAYOUT = PKG_PREFIX + "AppBarLayout";
+    public static final String CN_COLLAPSING_TOOLBAR_LAYOUT =
+            PKG_PREFIX + "CollapsingToolbarLayout";
+    public static final String CN_TOOLBAR = "android.support.v7.widget.Toolbar";
+    public static final int SCROLL_AXIS_VERTICAL = 1 << 1;
+
+    /**
+     * Tries to set the title of a view. This is used to set the title in a
+     * CollapsingToolbarLayout.
+     * <p/>
+     * Any exceptions thrown during the process are logged in {@link Bridge#getLog()}
+     */
+    public static void setTitle(@NonNull View view, @Nullable String title) {
+        if (title == null) {
+            return;
+        }
+        try {
+            Method setTitle = getMethod(view.getClass(), "setTitle", CharSequence.class);
+            if (setTitle != null) {
+                invoke(setTitle, view, title);
+            }
+        } catch (ReflectionException e) {
+            Bridge.getLog().warning(LayoutLog.TAG_INFO,
+                    "Error occurred while trying to set title.", e);
+        }
+    }
+}
diff --git a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
index ff77b58..d571d35 100644
--- a/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
+++ b/tools/layoutlib/bridge/src/com/android/layoutlib/bridge/impl/RenderSessionImpl.java
@@ -44,6 +44,7 @@
 import com.android.layoutlib.bridge.android.BridgeLayoutParamsMapAttributes;
 import com.android.layoutlib.bridge.android.BridgeXmlBlockParser;
 import com.android.layoutlib.bridge.android.RenderParamsFlags;
+import com.android.layoutlib.bridge.android.support.DesignLibUtil;
 import com.android.layoutlib.bridge.android.support.RecyclerViewUtil;
 import com.android.layoutlib.bridge.bars.AppCompatActionBar;
 import com.android.layoutlib.bridge.bars.BridgeActionBar;
@@ -148,7 +149,6 @@
     private int mTitleBarSize;
     private int mActionBarSize;
 
-
     // information being returned through the API
     private BufferedImage mImage;
     private List<ViewInfo> mViewInfoList;
@@ -424,6 +424,8 @@
             // post-inflate process. For now this supports TabHost/TabWidget
             postInflateProcess(view, params.getLayoutlibCallback(), isPreference ? view : null);
 
+            setActiveToolbar(view, context, params);
+
             // get the background drawable
             if (mWindowBackground != null) {
                 Drawable d = ResourceHelper.getDrawable(mWindowBackground, context);
@@ -544,6 +546,8 @@
             // now do the layout.
             mViewRoot.layout(0, 0, mMeasuredScreenWidth, mMeasuredScreenHeight);
 
+            handleScrolling(mViewRoot);
+
             if (params.isLayoutOnly()) {
                 // delete the canvas and image to reset them on the next full rendering
                 mImage = null;
@@ -1350,6 +1354,99 @@
     }
 
     /**
+     * If the root layout is a CoordinatorLayout with an AppBar:
+     * Set the title of the AppBar to the title of the activity context.
+     */
+    private void setActiveToolbar(View view, BridgeContext context, SessionParams params) {
+        View coordinatorLayout = findChildView(view, DesignLibUtil.CN_COORDINATOR_LAYOUT);
+        if (coordinatorLayout == null) {
+            return;
+        }
+        View appBar = findChildView(coordinatorLayout, DesignLibUtil.CN_APPBAR_LAYOUT);
+        if (appBar == null) {
+            return;
+        }
+        ViewGroup collapsingToolbar =
+                (ViewGroup) findChildView(appBar, DesignLibUtil.CN_COLLAPSING_TOOLBAR_LAYOUT);
+        if (collapsingToolbar == null) {
+            return;
+        }
+        if (!hasToolbar(collapsingToolbar)) {
+            return;
+        }
+        RenderResources res = context.getRenderResources();
+        String title = params.getAppLabel();
+        ResourceValue titleValue = res.findResValue(title, false);
+        if (titleValue != null && titleValue.getValue() != null) {
+            title = titleValue.getValue();
+        }
+        DesignLibUtil.setTitle(collapsingToolbar, title);
+    }
+
+    private View findChildView(View view, String className) {
+        if (!(view instanceof ViewGroup)) {
+            return null;
+        }
+        ViewGroup group = (ViewGroup) view;
+        for (int i = 0; i < group.getChildCount(); i++) {
+            if (isInstanceOf(group.getChildAt(i), className)) {
+                return group.getChildAt(i);
+            }
+        }
+        return null;
+    }
+
+    private boolean hasToolbar(View collapsingToolbar) {
+        if (!(collapsingToolbar instanceof ViewGroup)) {
+            return false;
+        }
+        ViewGroup group = (ViewGroup) collapsingToolbar;
+        for (int i = 0; i < group.getChildCount(); i++) {
+            if (isInstanceOf(group.getChildAt(i), DesignLibUtil.CN_TOOLBAR)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Set the vertical scroll position on all the components with the "scrollY" attribute. If the
+     * component supports nested scrolling attempt that first, then use the unconsumed scroll part
+     * to scroll the content in the component.
+     */
+    private void handleScrolling(View view) {
+        BridgeContext context = getContext();
+        int scrollPos = context.getScrollYPos(view);
+        if (scrollPos != 0) {
+            if (view.isNestedScrollingEnabled()) {
+                int[] consumed = new int[2];
+                if (view.startNestedScroll(DesignLibUtil.SCROLL_AXIS_VERTICAL)) {
+                    view.dispatchNestedPreScroll(0, scrollPos, consumed, null);
+                    view.dispatchNestedScroll(consumed[0], consumed[1], 0, scrollPos, null);
+                    view.stopNestedScroll();
+                    scrollPos -= consumed[1];
+                }
+            }
+            if (scrollPos != 0) {
+                view.scrollBy(0, scrollPos);
+            } else {
+                view.scrollBy(0, scrollPos);
+            }
+        } else {
+            view.scrollBy(0, scrollPos);
+        }
+
+        if (!(view instanceof ViewGroup)) {
+            return;
+        }
+        ViewGroup group = (ViewGroup) view;
+        for (int i = 0; i < group.getChildCount(); i++) {
+            View child = group.getChildAt(i);
+            handleScrolling(child);
+        }
+    }
+
+    /**
      * Check if the object is an instance of a class named {@code className}. This doesn't work
      * for interfaces.
      */
diff --git a/tools/orientationplot/README.txt b/tools/orientationplot/README.txt
index d53f65e..958207d 100644
--- a/tools/orientationplot/README.txt
+++ b/tools/orientationplot/README.txt
@@ -9,6 +9,8 @@
 2. numpy
 3. matplotlib
 
+eg. sudo apt-get install python-numpy python-matplotlib
+
 
 USAGE
 -----
diff --git a/tools/orientationplot/orientationplot.py b/tools/orientationplot/orientationplot.py
index 6fc3922..77ed074 100755
--- a/tools/orientationplot/orientationplot.py
+++ b/tools/orientationplot/orientationplot.py
@@ -440,7 +440,7 @@
 # Notice
 print "Window Orientation Listener plotting tool"
 print "-----------------------------------------\n"
-print "Please turn on the Window Orientation Listener logging in Development Settings."
+print "Please turn on the Window Orientation Listener logging.  See README.txt."
 
 # Start adb.
 print "Starting adb logcat.\n"