Merge "Make sure task exists in WM before trying to set the resizing state" into nyc-dev
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 0fca78d..6fc1820 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1866,6 +1866,10 @@
         } else {
             parcel.writeInt(0);
         }
+        if (mLargeIcon == null && largeIcon != null) {
+            // you snuck an icon in here without using the builder; let's try to keep it
+            mLargeIcon = Icon.createWithBitmap(largeIcon);
+        }
         if (mLargeIcon != null) {
             parcel.writeInt(1);
             mLargeIcon.writeToParcel(parcel, 0);
@@ -1986,6 +1990,10 @@
                     new Throwable());
         }
 
+        if (context.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N) {
+            extras.putBoolean(EXTRA_SHOW_WHEN, true);
+        }
+
         // ensure that any information already set directly is preserved
         final Notification.Builder builder = new Notification.Builder(context, this);
 
@@ -2269,6 +2277,14 @@
                     Collections.addAll(mPersonList, mN.extras.getStringArray(EXTRA_PEOPLE));
                 }
 
+                if (mN.getSmallIcon() == null && mN.icon != 0) {
+                    setSmallIcon(mN.icon);
+                }
+
+                if (mN.getLargeIcon() == null && mN.largeIcon != null) {
+                    setLargeIcon(mN.largeIcon);
+                }
+
                 String templateClass = mN.extras.getString(EXTRA_TEMPLATE);
                 if (!TextUtils.isEmpty(templateClass)) {
                     final Class<? extends Style> styleClass
@@ -3171,8 +3187,8 @@
         }
 
         private void resetContentMargins(RemoteViews contentView) {
-            contentView.setViewLayoutMarginEnd(R.id.line1, 0);
-            contentView.setViewLayoutMarginEnd(R.id.text, 0);
+            contentView.setViewLayoutMarginEndDimen(R.id.line1, 0);
+            contentView.setViewLayoutMarginEndDimen(R.id.text, 0);
         }
 
         private RemoteViews applyStandardTemplate(int resId) {
@@ -3218,7 +3234,7 @@
                 contentView.setViewVisibility(textId, View.VISIBLE);
             }
 
-            setContentMinHeight(contentView, showProgress || mN.mLargeIcon != null);
+            setContentMinHeight(contentView, showProgress || mN.hasLargeIcon());
 
             return contentView;
         }
@@ -3262,15 +3278,17 @@
         }
 
         private void bindLargeIcon(RemoteViews contentView) {
+            if (mN.mLargeIcon == null && mN.largeIcon != null) {
+                mN.mLargeIcon = Icon.createWithBitmap(mN.largeIcon);
+            }
             if (mN.mLargeIcon != null) {
                 contentView.setViewVisibility(R.id.right_icon, View.VISIBLE);
                 contentView.setImageViewIcon(R.id.right_icon, mN.mLargeIcon);
                 processLargeLegacyIcon(mN.mLargeIcon, contentView);
-                int endMargin = mContext.getResources().getDimensionPixelSize(
-                        R.dimen.notification_content_picture_margin);
-                contentView.setViewLayoutMarginEnd(R.id.line1, endMargin);
-                contentView.setViewLayoutMarginEnd(R.id.text, endMargin);
-                contentView.setViewLayoutMarginEnd(R.id.progress, endMargin);
+                int endMargin = R.dimen.notification_content_picture_margin;
+                contentView.setViewLayoutMarginEndDimen(R.id.line1, endMargin);
+                contentView.setViewLayoutMarginEndDimen(R.id.text, endMargin);
+                contentView.setViewLayoutMarginEndDimen(R.id.progress, endMargin);
             }
         }
 
@@ -3369,6 +3387,9 @@
         }
 
         private void bindSmallIcon(RemoteViews contentView) {
+            if (mN.mSmallIcon == null && mN.icon != 0) {
+                mN.mSmallIcon = Icon.createWithResource(mContext, mN.icon);
+            }
             contentView.setImageViewIcon(R.id.icon, mN.mSmallIcon);
             processSmallIconColor(mN.mSmallIcon, contentView);
         }
@@ -3394,6 +3415,8 @@
             big.setTextViewText(R.id.notification_material_reply_text_2, null);
             big.setViewVisibility(R.id.notification_material_reply_text_3, View.GONE);
             big.setTextViewText(R.id.notification_material_reply_text_3, null);
+
+            big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target, 0);
         }
 
         private RemoteViews applyStandardTemplateWithActions(int layoutId) {
@@ -3416,6 +3439,8 @@
             if (N > 0) {
                 big.setViewVisibility(R.id.actions_container, View.VISIBLE);
                 big.setViewVisibility(R.id.actions, View.VISIBLE);
+                big.setViewLayoutMarginBottomDimen(R.id.notification_action_list_margin_target,
+                        R.dimen.notification_action_list_height);
                 if (N>MAX_ACTION_BUTTONS) N=MAX_ACTION_BUTTONS;
                 for (int i=0; i<N; i++) {
                     Action action = mActions.get(i);
@@ -3564,6 +3589,8 @@
             mStyle = null;
             Icon largeIcon = mN.mLargeIcon;
             mN.mLargeIcon = null;
+            Bitmap largeIconLegacy = mN.largeIcon;
+            mN.largeIcon = null;
             Bundle publicExtras = new Bundle();
             publicExtras.putBoolean(EXTRA_SHOW_WHEN,
                     savedBundle.getBoolean(EXTRA_SHOW_WHEN));
@@ -3577,6 +3604,7 @@
             final RemoteViews publicView = applyStandardTemplate(getBaseLayoutResource());
             mN.extras = savedBundle;
             mN.mLargeIcon = largeIcon;
+            mN.largeIcon = largeIconLegacy;
             mStyle = style;
             return publicView;
         }
@@ -3873,6 +3901,10 @@
         }
     }
 
+    private boolean hasLargeIcon() {
+        return mLargeIcon != null || largeIcon != null;
+    }
+
     /**
      * @return true if the notification will show the time; false otherwise
      * @hide
@@ -4179,7 +4211,7 @@
                 contentView.setTextViewText(R.id.text, mBuilder.processLegacyText(mSummaryText));
                 contentView.setViewVisibility(R.id.text, View.VISIBLE);
             }
-            mBuilder.setContentMinHeight(contentView, mBuilder.mN.mLargeIcon != null);
+            mBuilder.setContentMinHeight(contentView, mBuilder.mN.hasLargeIcon());
 
             if (mBigLargeIconSet) {
                 mBuilder.mN.mLargeIcon = oldLargeIcon;
@@ -4334,7 +4366,7 @@
             contentView.setViewVisibility(R.id.big_text,
                     TextUtils.isEmpty(bigTextText) ? View.GONE : View.VISIBLE);
             contentView.setInt(R.id.big_text, "setMaxLines", calculateMaxLines(builder));
-            contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.mLargeIcon != null);
+            contentView.setBoolean(R.id.big_text, "setHasImage", builder.mN.hasLargeIcon());
         }
 
         private static int calculateMaxLines(Builder builder) {
@@ -4604,11 +4636,10 @@
             }
 
             int i=0;
-            int titlePadding = mBuilder.mContext.getResources().getDimensionPixelSize(
-                    R.dimen.notification_messaging_spacing);
-            contentView.setViewLayoutMarginBottom(R.id.line1, hasTitle ? titlePadding : 0);
+            contentView.setViewLayoutMarginBottomDimen(R.id.line1,
+                    hasTitle ? R.dimen.notification_messaging_spacing : 0);
             contentView.setInt(R.id.notification_messaging, "setNumIndentLines",
-                    mBuilder.mN.mLargeIcon == null ? 0 : (hasTitle ? 1 : 2));
+                    !mBuilder.mN.hasLargeIcon() ? 0 : (hasTitle ? 1 : 2));
 
             int contractedChildId = View.NO_ID;
             Message contractedMessage = findLatestIncomingMessage();
@@ -4981,12 +5012,11 @@
                 final int max = mBuilder.mN.extras.getInt(EXTRA_PROGRESS_MAX, 0);
                 final boolean ind = mBuilder.mN.extras.getBoolean(EXTRA_PROGRESS_INDETERMINATE);
                 boolean hasProgress = max != 0 || ind;
-                if (mBuilder.mN.mLargeIcon != null && !hasProgress) {
-                    endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
-                            R.dimen.notification_content_picture_margin);
+                if (mBuilder.mN.hasLargeIcon() && !hasProgress) {
+                    endMargin = R.dimen.notification_content_picture_margin;
                 }
             }
-            contentView.setViewLayoutMarginEnd(id, endMargin);
+            contentView.setViewLayoutMarginEndDimen(id, endMargin);
         }
     }
 
@@ -5171,13 +5201,11 @@
             }
             handleImage(view);
             // handle the content margin
-            int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
-                    R.dimen.notification_content_margin_end);;
-            if (mBuilder.mN.mLargeIcon != null) {
-                endMargin += mBuilder.mContext.getResources().getDimensionPixelSize(
-                        R.dimen.notification_content_picture_margin);
+            int endMargin = R.dimen.notification_content_margin_end;
+            if (mBuilder.mN.hasLargeIcon()) {
+                endMargin = R.dimen.notification_content_plus_picture_margin_end;
             }
-            view.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
+            view.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
             return view;
         }
 
@@ -5187,7 +5215,7 @@
             int actionsInCompact = mActionsToShowInCompact == null
                     ? 0
                     : Math.min(mActionsToShowInCompact.length, MAX_MEDIA_BUTTONS_IN_COMPACT);
-            if (mBuilder.mN.mLargeIcon == null && actionCount <= actionsInCompact) {
+            if (!mBuilder.mN.hasLargeIcon() && actionCount <= actionsInCompact) {
                 return null;
             }
             RemoteViews big = mBuilder.applyStandardTemplate(
@@ -5207,9 +5235,9 @@
         }
 
         private void handleImage(RemoteViews contentView) {
-            if (mBuilder.mN.mLargeIcon != null) {
-                contentView.setViewLayoutMarginEnd(R.id.line1, 0);
-                contentView.setViewLayoutMarginEnd(R.id.text, 0);
+            if (mBuilder.mN.hasLargeIcon()) {
+                contentView.setViewLayoutMarginEndDimen(R.id.line1, 0);
+                contentView.setViewLayoutMarginEndDimen(R.id.text, 0);
             }
         }
 
@@ -5324,13 +5352,11 @@
                 remoteViews.addView(R.id.notification_main_column, customContent);
             }
             // also update the end margin if there is an image
-            int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
-                    R.dimen.notification_content_margin_end);
-            if (mBuilder.mN.mLargeIcon != null) {
-                endMargin += mBuilder.mContext.getResources().getDimensionPixelSize(
-                        R.dimen.notification_content_picture_margin);
+            int endMargin = R.dimen.notification_content_margin_end;
+            if (mBuilder.mN.hasLargeIcon()) {
+                endMargin = R.dimen.notification_content_plus_picture_margin_end;
             }
-            remoteViews.setViewLayoutMarginEnd(R.id.notification_main_column, endMargin);
+            remoteViews.setViewLayoutMarginEndDimen(R.id.notification_main_column, endMargin);
         }
     }
 
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index e98bb7e..9a0cd56 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -47,6 +47,8 @@
      * Gets the packages whose widget providers are white-listed to be
      * available in the parent user.
      *
+     * <p>This takes the DPMS lock.  DO NOT call from PM/UM/AM with their lock held.
+     *
      * @param profileId The profile id.
      * @return The list of packages if such or empty list if there are
      *    no white-listed packages or the profile id is not a managed
@@ -58,6 +60,8 @@
      * Adds a listener for changes in the white-listed packages to show
      * cross-profile app widgets.
      *
+     * <p>This takes the DPMS lock.  DO NOT call from PM/UM/AM with their lock held.
+     *
      * @param listener The listener to add.
      */
     public abstract void addOnCrossProfileWidgetProvidersChangeListener(
@@ -66,6 +70,9 @@
     /**
      * Checks if an app with given uid is an active device admin of its user and has the policy
      * specified.
+     *
+     * <p>This takes the DPMS lock.  DO NOT call from PM/UM/AM with their lock held.
+     *
      * @param uid App uid.
      * @param reqPolicy Required policy, for policies see {@link DevicePolicyManager}.
      * @return true if the uid is an active admin with the given policy.
@@ -77,6 +84,8 @@
      * suspended by the admin. This assumes that {@param packageName} is suspended by the
      * device/profile owner. The caller should check if the package is suspended or not.
      *
+     * <p>This method does not take the DPMS lock.  Safe to be called from anywhere.
+     *
      * @param packageName The package that is suspended
      * @param userId The user having the suspended package.
      * @return The intent to trigger the admin support dialog.
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 6dc5ff7..1f745185 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -17,6 +17,7 @@
 package android.widget;
 
 import android.annotation.ColorInt;
+import android.annotation.DimenRes;
 import android.app.ActivityManager.StackId;
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
@@ -1850,13 +1851,13 @@
     /**
      * Helper action to set layout params on a View.
      */
-    private class LayoutParamAction extends Action {
+    private static class LayoutParamAction extends Action {
 
         /** Set marginEnd */
-        public static final int LAYOUT_MARGIN_END = 1;
+        public static final int LAYOUT_MARGIN_END_DIMEN = 1;
         /** Set width */
         public static final int LAYOUT_WIDTH = 2;
-        public static final int LAYOUT_MARGIN_BOTTOM = 3;
+        public static final int LAYOUT_MARGIN_BOTTOM_DIMEN = 3;
 
         /**
          * @param viewId ID of the view alter
@@ -1893,15 +1894,17 @@
                 return;
             }
             switch (property) {
-                case LAYOUT_MARGIN_END:
+                case LAYOUT_MARGIN_END_DIMEN:
                     if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
-                        ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(value);
+                        int resolved = resolveDimenPixelOffset(target, value);
+                        ((ViewGroup.MarginLayoutParams) layoutParams).setMarginEnd(resolved);
                         target.setLayoutParams(layoutParams);
                     }
                     break;
-                case LAYOUT_MARGIN_BOTTOM:
+                case LAYOUT_MARGIN_BOTTOM_DIMEN:
                     if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
-                        ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = value;
+                        int resolved = resolveDimenPixelOffset(target, value);
+                        ((ViewGroup.MarginLayoutParams) layoutParams).bottomMargin = resolved;
                         target.setLayoutParams(layoutParams);
                     }
                     break;
@@ -1914,6 +1917,13 @@
             }
         }
 
+        private static int resolveDimenPixelOffset(View target, int value) {
+            if (value == 0) {
+                return 0;
+            }
+            return target.getContext().getResources().getDimensionPixelOffset(value);
+        }
+
         public String getActionName() {
             return "LayoutParamAction" + property + ".";
         }
@@ -2870,27 +2880,36 @@
      * Hidden for now since we don't want to support this for all different layout margins yet.
      *
      * @param viewId The id of the view to change
-     * @param endMargin the left padding in pixels
+     * @param endMarginDimen a dimen resource to read the margin from or 0 to clear the margin.
      */
-    public void setViewLayoutMarginEnd(int viewId, int endMargin) {
-        addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END, endMargin));
+    public void setViewLayoutMarginEndDimen(int viewId, @DimenRes int endMarginDimen) {
+        addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_END_DIMEN,
+                endMarginDimen));
     }
 
     /**
      * Equivalent to setting {@link android.view.ViewGroup.MarginLayoutParams#bottomMargin}.
      *
+     * @param bottomMarginDimen a dimen resource to read the margin from or 0 to clear the margin.
      * @hide
      */
-    public void setViewLayoutMarginBottom(int viewId, int bottomMargin) {
-        addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM,
-                bottomMargin));
+    public void setViewLayoutMarginBottomDimen(int viewId, @DimenRes int bottomMarginDimen) {
+        addAction(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_MARGIN_BOTTOM_DIMEN,
+                bottomMarginDimen));
     }
 
     /**
      * Equivalent to setting {@link android.view.ViewGroup.LayoutParams#width}.
+     *
+     * @param layoutWidth one of 0, MATCH_PARENT or WRAP_CONTENT. Other sizes are not allowed
+     *                    because they behave poorly when the density changes.
      * @hide
      */
     public void setViewLayoutWidth(int viewId, int layoutWidth) {
+        if (layoutWidth != 0 && layoutWidth != ViewGroup.LayoutParams.MATCH_PARENT
+                && layoutWidth != ViewGroup.LayoutParams.WRAP_CONTENT) {
+            throw new IllegalArgumentException("Only supports 0, WRAP_CONTENT and MATCH_PARENT");
+        }
         mActions.add(new LayoutParamAction(viewId, LayoutParamAction.LAYOUT_WIDTH, layoutWidth));
     }
 
diff --git a/core/java/com/android/internal/inputmethod/InputMethodUtils.java b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
index a028449..716997f 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodUtils.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodUtils.java
@@ -41,6 +41,7 @@
 import android.view.textservice.SpellCheckerInfo;
 import android.view.textservice.TextServicesManager;
 
+import com.android.internal.annotations.GuardedBy;
 import com.android.internal.annotations.VisibleForTesting;
 
 import java.util.ArrayList;
@@ -83,6 +84,17 @@
         Locale.UK, // "en_GB"
     };
 
+    // A temporary workaround for the performance concerns in
+    // #getImplicitlyApplicableSubtypesLocked(Resources, InputMethodInfo).
+    // TODO: Optimize all the critical paths including this one.
+    private static final Object sCacheLock = new Object();
+    @GuardedBy("sCacheLock")
+    private static LocaleList sCachedSystemLocales;
+    @GuardedBy("sCacheLock")
+    private static InputMethodInfo sCachedInputMethodInfo;
+    @GuardedBy("sCacheLock")
+    private static ArrayList<InputMethodSubtype> sCachedResult;
+
     private InputMethodUtils() {
         // This utility class is not publicly instantiable.
     }
@@ -498,6 +510,32 @@
     @VisibleForTesting
     public static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLocked(
             Resources res, InputMethodInfo imi) {
+        final LocaleList systemLocales = res.getConfiguration().getLocales();
+
+        synchronized (sCacheLock) {
+            // We intentionally do not use InputMethodInfo#equals(InputMethodInfo) here because
+            // it does not check if subtypes are also identical.
+            if (systemLocales.equals(sCachedSystemLocales) && sCachedInputMethodInfo == imi) {
+                return new ArrayList<>(sCachedResult);
+            }
+        }
+
+        // Note: Only resource info in "res" is used in getImplicitlyApplicableSubtypesLockedImpl().
+        // TODO: Refactor getImplicitlyApplicableSubtypesLockedImpl() so that it can receive
+        // LocaleList rather than Resource.
+        final ArrayList<InputMethodSubtype> result =
+                getImplicitlyApplicableSubtypesLockedImpl(res, imi);
+        synchronized (sCacheLock) {
+            // Both LocaleList and InputMethodInfo are immutable. No need to copy them here.
+            sCachedSystemLocales = systemLocales;
+            sCachedInputMethodInfo = imi;
+            sCachedResult = new ArrayList<>(result);
+        }
+        return result;
+    }
+
+    private static ArrayList<InputMethodSubtype> getImplicitlyApplicableSubtypesLockedImpl(
+            Resources res, InputMethodInfo imi) {
         final List<InputMethodSubtype> subtypes = InputMethodUtils.getSubtypes(imi);
         final LocaleList systemLocales = res.getConfiguration().getLocales();
         final String systemLocale = systemLocales.get(0).toString();
diff --git a/core/res/res/layout/notification_material_action_list.xml b/core/res/res/layout/notification_material_action_list.xml
index 4670dca..caeb43a 100644
--- a/core/res/res/layout/notification_material_action_list.xml
+++ b/core/res/res/layout/notification_material_action_list.xml
@@ -17,7 +17,8 @@
 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
         android:id="@+id/actions_container"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content">
+        android:layout_height="wrap_content"
+        android:layout_gravity="bottom">
     <com.android.internal.widget.NotificationActionListLayout
             android:id="@+id/actions"
             android:layout_width="match_parent"
diff --git a/core/res/res/layout/notification_template_material_big_base.xml b/core/res/res/layout/notification_template_material_big_base.xml
index c54fa18..8b0b476 100644
--- a/core/res/res/layout/notification_template_material_big_base.xml
+++ b/core/res/res/layout/notification_template_material_big_base.xml
@@ -14,7 +14,7 @@
   ~ See the License for the specific language governing permissions and
   ~ limitations under the License
   -->
-<LinearLayout
+<FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/status_bar_latest_event_content"
     android:layout_width="match_parent"
@@ -22,43 +22,49 @@
     android:orientation="vertical"
     android:tag="big"
     >
-    <FrameLayout
-        android:id="@+id/status_bar_latest_event_content"
-        android:layout_width="match_parent"
-        android:layout_height="wrap_content"
-        android:layout_gravity="top"
-        android:tag="base"
-        >
-        <include layout="@layout/notification_template_header" />
-        <LinearLayout
-            android:id="@+id/notification_main_column"
+    <LinearLayout
+            android:id="@+id/notification_action_list_margin_target"
             android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_gravity="top"
-            android:layout_marginStart="@dimen/notification_content_margin_start"
-            android:layout_marginEnd="@dimen/notification_content_margin_end"
-            android:layout_marginTop="@dimen/notification_content_margin_top"
-            android:layout_marginBottom="@dimen/notification_content_margin_bottom"
+            android:layout_height="wrap_content"
+            android:layout_marginBottom="@dimen/notification_action_list_height"
             android:orientation="vertical"
             >
-            <include layout="@layout/notification_template_part_line1" />
-            <include layout="@layout/notification_template_text" />
-        </LinearLayout>
         <FrameLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:layout_gravity="bottom"
-            android:layout_marginStart="@dimen/notification_content_margin_start"
-            android:layout_marginBottom="15dp"
-            android:layout_marginEnd="@dimen/notification_content_margin_end">
-            <include layout="@layout/notification_template_progress" />
+            android:layout_gravity="top"
+            >
+            <include layout="@layout/notification_template_header" />
+            <LinearLayout
+                android:id="@+id/notification_main_column"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_gravity="top"
+                android:layout_marginStart="@dimen/notification_content_margin_start"
+                android:layout_marginEnd="@dimen/notification_content_margin_end"
+                android:layout_marginTop="@dimen/notification_content_margin_top"
+                android:layout_marginBottom="@dimen/notification_content_margin_bottom"
+                android:orientation="vertical"
+                >
+                <include layout="@layout/notification_template_part_line1" />
+                <include layout="@layout/notification_template_text" />
+            </LinearLayout>
+            <FrameLayout
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:layout_gravity="bottom"
+                android:layout_marginStart="@dimen/notification_content_margin_start"
+                android:layout_marginBottom="15dp"
+                android:layout_marginEnd="@dimen/notification_content_margin_end">
+                <include layout="@layout/notification_template_progress" />
+            </FrameLayout>
+            <include layout="@layout/notification_template_right_icon" />
         </FrameLayout>
-        <include layout="@layout/notification_template_right_icon" />
-    </FrameLayout>
-    <ViewStub android:layout="@layout/notification_material_reply_text"
-            android:id="@+id/notification_material_reply_container"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-    />
+        <ViewStub android:layout="@layout/notification_material_reply_text"
+                android:id="@+id/notification_material_reply_container"
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+        />
+    </LinearLayout>
     <include layout="@layout/notification_material_action_list" />
-</LinearLayout>
+</FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_picture.xml b/core/res/res/layout/notification_template_material_big_picture.xml
index d87b9d9..83c0fec 100644
--- a/core/res/res/layout/notification_template_material_big_picture.xml
+++ b/core/res/res/layout/notification_template_material_big_picture.xml
@@ -30,6 +30,7 @@
             android:layout_marginTop="@dimen/notification_content_margin_top"
             android:clipToPadding="false"
             android:orientation="vertical"
+            android:id="@+id/notification_action_list_margin_target"
             >
         <LinearLayout
             android:id="@+id/notification_main_column"
@@ -60,6 +61,6 @@
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
                 />
-        <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
+    <include layout="@layout/notification_material_action_list" />
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_big_text.xml b/core/res/res/layout/notification_template_material_big_text.xml
index 71600ef..f4f783e 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -24,10 +24,12 @@
     <include layout="@layout/notification_template_header" />
 
     <LinearLayout
+            android:id="@+id/notification_action_list_margin_target"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="top"
             android:layout_marginTop="@dimen/notification_content_margin_top"
+            android:layout_marginBottom="@dimen/notification_action_list_height"
             android:clipToPadding="false"
             android:orientation="vertical">
 
@@ -61,7 +63,7 @@
                 android:id="@+id/notification_material_reply_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
-        <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
+    <include layout="@layout/notification_material_action_list" />
     <include layout="@layout/notification_template_right_icon" />
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_inbox.xml b/core/res/res/layout/notification_template_material_inbox.xml
index 0e93d0b..7820e39 100644
--- a/core/res/res/layout/notification_template_material_inbox.xml
+++ b/core/res/res/layout/notification_template_material_inbox.xml
@@ -23,6 +23,7 @@
     >
     <include layout="@layout/notification_template_header" />
     <LinearLayout
+            android:id="@+id/notification_action_list_margin_target"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="top"
@@ -117,7 +118,7 @@
                 android:id="@+id/notification_material_reply_container"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content" />
-        <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
+    <include layout="@layout/notification_material_action_list" />
     <include layout="@layout/notification_template_right_icon" />
 </FrameLayout>
diff --git a/core/res/res/layout/notification_template_material_messaging.xml b/core/res/res/layout/notification_template_material_messaging.xml
index d95ff05..07b1100 100644
--- a/core/res/res/layout/notification_template_material_messaging.xml
+++ b/core/res/res/layout/notification_template_material_messaging.xml
@@ -22,6 +22,7 @@
     >
     <include layout="@layout/notification_template_header" />
     <LinearLayout
+            android:id="@+id/notification_action_list_margin_target"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layout_gravity="top"
@@ -74,7 +75,7 @@
                     />
             </com.android.internal.widget.MessagingLinearLayout>
         </LinearLayout>
-        <include layout="@layout/notification_material_action_list" />
     </LinearLayout>
+    <include layout="@layout/notification_material_action_list" />
     <include layout="@layout/notification_template_right_icon" />
 </FrameLayout>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 37fb816..91d7227 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -148,12 +148,20 @@
     <!-- The margin on the start of the content view -->
     <dimen name="notification_content_margin_start">16dp</dimen>
 
-    <!-- The margin on the end of the content view -->
+    <!-- The margin on the end of the content view
+        Keep in sync with notification_content_plus_picture_margin! -->
     <dimen name="notification_content_margin_end">16dp</dimen>
 
-    <!-- The margin on the end of the content view with a picture.-->
+    <!-- The margin on the end of the content view with a picture.
+        Keep in sync with notification_content_plus_picture_margin! -->
     <dimen name="notification_content_picture_margin">56dp</dimen>
 
+    <!-- The margin on the end of the content view with a picture, plus the standard
+        content end margin.
+        Keep equal to (notification_content_picture_margin + notification_content_margin_end)!
+    -->
+    <dimen name="notification_content_plus_picture_margin_end">72dp</dimen>
+
     <!-- The height of the notification action list -->
     <dimen name="notification_action_list_height">56dp</dimen>
 
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index abef7f8..7e9b57c 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -2602,6 +2602,9 @@
 
   <java-symbol type="bool" name="config_supportPreRebootSecurityLogs" />
 
+  <java-symbol type="dimen" name="notification_content_plus_picture_margin_end" />
+  <java-symbol type="id" name="notification_action_list_margin_target" />
+
   <!-- Pinner Service -->
   <java-symbol type="array" name="config_defaultPinnerServiceFiles" />
 
diff --git a/docs/html-intl/intl/es/training/material/compatibility.jd b/docs/html-intl/intl/es/training/material/compatibility.jd
index ad2e953..d2cb9aa 100644
--- a/docs/html-intl/intl/es/training/material/compatibility.jd
+++ b/docs/html-intl/intl/es/training/material/compatibility.jd
@@ -123,7 +123,7 @@
 <h3>Dependencias</h3>
 
 <p>Para usar estas características en versiones de Android anteriores a la 5.0 (API nivel 21), incluye
-en tu proyecto la Biblioteca de soporte v7 de Android como una <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependencia de Gradle</a>:</p>
+en tu proyecto la Biblioteca de soporte v7 de Android como una <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependencia de Gradle</a>:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html-intl/intl/in/training/material/compatibility.jd b/docs/html-intl/intl/in/training/material/compatibility.jd
index d57c7be..ef444c3 100644
--- a/docs/html-intl/intl/in/training/material/compatibility.jd
+++ b/docs/html-intl/intl/in/training/material/compatibility.jd
@@ -123,7 +123,7 @@
 <h3>Dependensi</h3>
 
 <p>Untuk menggunakan fitur-fitur ini di versi Android sebelum 5.0 (API level 21), sertakan
-Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p>
+Android v7 Support Library dalam proyek Anda sebagai <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependensi Gradle</a>:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html-intl/intl/ja/training/material/compatibility.jd b/docs/html-intl/intl/ja/training/material/compatibility.jd
index 0f8922f..2581170 100644
--- a/docs/html-intl/intl/ja/training/material/compatibility.jd
+++ b/docs/html-intl/intl/ja/training/material/compatibility.jd
@@ -122,7 +122,7 @@
 
 <h3>依存関係</h3>
 
-<p>5.0(API レベル 21)より前のバージョンの Android でこれらの機能を使用するには、Android v7 サポート ライブラリを <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle 依存関係</a>としてプロジェクトに含めます。
+<p>5.0(API レベル 21)より前のバージョンの Android でこれらの機能を使用するには、Android v7 サポート ライブラリを <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle 依存関係</a>としてプロジェクトに含めます。
 </p>
 
 <pre>
diff --git a/docs/html-intl/intl/ko/training/material/compatibility.jd b/docs/html-intl/intl/ko/training/material/compatibility.jd
index 266cd7c..5bb8434 100644
--- a/docs/html-intl/intl/ko/training/material/compatibility.jd
+++ b/docs/html-intl/intl/ko/training/material/compatibility.jd
@@ -122,7 +122,7 @@
 
 <h3>종속 사항</h3>
 
-<p>Android 5.0(API 레벨 21) 이전 버전에서 이러한 기능을 사용하려면 프로젝트에 Android v7 지원 라이브러리를 <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle 종속 사항</a>으로 포함합니다.
+<p>Android 5.0(API 레벨 21) 이전 버전에서 이러한 기능을 사용하려면 프로젝트에 Android v7 지원 라이브러리를 <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle 종속 사항</a>으로 포함합니다.
 </p>
 
 <pre>
diff --git a/docs/html-intl/intl/pt-br/training/material/compatibility.jd b/docs/html-intl/intl/pt-br/training/material/compatibility.jd
index 2540df1..d242c0c 100644
--- a/docs/html-intl/intl/pt-br/training/material/compatibility.jd
+++ b/docs/html-intl/intl/pt-br/training/material/compatibility.jd
@@ -123,7 +123,7 @@
 <h3>Dependências</h3>
 
 <p>Para usar esses recursos em versões anteriores ao Android 5.0 (API de nível 21), inclua a
-Biblioteca de Suporte v7 do Android no projeto como uma <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">dependência de Gradle</a>:</p>
+Biblioteca de Suporte v7 do Android no projeto como uma <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">dependência de Gradle</a>:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html-intl/intl/ru/training/material/compatibility.jd b/docs/html-intl/intl/ru/training/material/compatibility.jd
index b7ca338..1f1d630 100644
--- a/docs/html-intl/intl/ru/training/material/compatibility.jd
+++ b/docs/html-intl/intl/ru/training/material/compatibility.jd
@@ -123,7 +123,7 @@
 <h3>Зависимости</h3>
 
 <p>Чтобы воспользоваться этими возможностями в версиях Android, предшествующих 5.0 (уровень API 21), включите в свой проект вспомогательную библиотеку
-Android v7 как <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">зависимость Gradle</a>:</p>
+Android v7 как <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">зависимость Gradle</a>:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html-intl/intl/vi/training/material/compatibility.jd b/docs/html-intl/intl/vi/training/material/compatibility.jd
index 65e8131..e19a745 100644
--- a/docs/html-intl/intl/vi/training/material/compatibility.jd
+++ b/docs/html-intl/intl/vi/training/material/compatibility.jd
@@ -123,7 +123,7 @@
 <h3>Phụ thuộc</h3>
 
 <p>Để sử dụng những tính năng này trong các phiên bản Android trước 5.0 (API mức 21), hãy thêm
-Thư viện Hỗ trợ v7 của Android vào dự án của bạn như một <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Phần phụ thuộc Gradle</a>:</p>
+Thư viện Hỗ trợ v7 của Android vào dự án của bạn như một <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Phần phụ thuộc Gradle</a>:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html-intl/intl/zh-cn/training/material/compatibility.jd b/docs/html-intl/intl/zh-cn/training/material/compatibility.jd
index aa23d4b..9ba8569 100644
--- a/docs/html-intl/intl/zh-cn/training/material/compatibility.jd
+++ b/docs/html-intl/intl/zh-cn/training/material/compatibility.jd
@@ -123,7 +123,7 @@
 <h3>依赖项</h3>
 
 <p>如果要在 Android 5.0(API 级别 21)之前的 Android 版本中使用这些功能,请将
-Android v7 支持内容库作为 <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle 依赖项</a>包括在您的项目中:</p>
+Android v7 支持内容库作为 <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle 依赖项</a>包括在您的项目中:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html-intl/intl/zh-tw/training/material/compatibility.jd b/docs/html-intl/intl/zh-tw/training/material/compatibility.jd
index 767788b..7d3cdde 100644
--- a/docs/html-intl/intl/zh-tw/training/material/compatibility.jd
+++ b/docs/html-intl/intl/zh-tw/training/material/compatibility.jd
@@ -122,7 +122,7 @@
 
 <h3>相依性</h3>
 
-<p>如果要在 Android 5.0 (API 級別 21) 以前的版本中使用這些功能,請在您的專案中包含 Android v7 支援程式庫做為 <a href="{@docRoot}/sdk/installing/studio-build.html#dependencies">Gradle 相依性</a>:
+<p>如果要在 Android 5.0 (API 級別 21) 以前的版本中使用這些功能,請在您的專案中包含 Android v7 支援程式庫做為 <a href="{@docRoot}sdk/installing/studio-build.html#dependencies">Gradle 相依性</a>:
 </p>
 
 <pre>
diff --git a/docs/html/guide/practices/verifying-apps-art.jd b/docs/html/guide/practices/verifying-apps-art.jd
index 8a88222..217c65c 100644
--- a/docs/html/guide/practices/verifying-apps-art.jd
+++ b/docs/html/guide/practices/verifying-apps-art.jd
@@ -63,7 +63,7 @@
 java.lang.System#gc() System.gc()} to prompt garbage collection (GC). This should be
 far less necessary with ART, particularly if you're invoking garbage collection
 to prevent <a
-href="{@docRoot}/tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type
+href="{@docRoot}tools/debugging/debugging-memory.html#LogMessages"><code>GC_FOR_ALLOC</code></a>-type
 occurrences or to reduce fragmentation. You can verify which runtime is in use
 by calling {@link java.lang.System#getProperty(java.lang.String)
 System.getProperty("java.vm.version")}. If ART is in use, the property's value
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index 606b38f..f2bc111 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -37,6 +37,7 @@
         <li><a href="#apk_signature_v2">APK Signature Scheme v2</a></li>
         <li><a href="#scoped_directory_access">Scoped Directory Access</a></li>
         <li><a href="#keyboard_shortcuts_helper">Keyboard Shortcuts Helper</a></li>
+        <li><a href="#custom_pointer_api">Custom Pointer API</a></li>
         <li><a href="#sustained_performance_api">Sustained Performance API</a></li>
         <li><a href="#vr">VR Support</a></li>
         <li><a href="#print_svc">Print Service Enhancements</a></li>
@@ -843,18 +844,46 @@
 <h2 id="keyboard_shortcuts_helper">Keyboard Shortcuts Helper</h2>
 
 <p>
-In Android N, the user can press "Alt + /" to trigger a <em>Keyboard Shortcuts</em>
-screen that displays all shortcuts available both from the system and from
-the app in focus. These are retrieved automatically from the app’s menu if
-available, but developers can provide their own fine-tuned shortcuts lists
-for the screen. You can do this by overriding the new
-<code>Activity.onProvideKeyboardShortcuts()</code> method, described in the downloadable
-<a href="{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.
+  In Android N, the user can press <strong>Meta + /</strong> to trigger a
+  <em>Keyboard Shortcuts</em> screen that displays all shortcuts available both
+  from the system and from the app in focus. The system retrieves these
+  shortcuts automatically from the app’s menu if the shortcuts exist. You can
+  also provide your own fine-tuned shortcuts lists for the screen. You can do
+  this by overriding the new <code>Activity.onProvideKeyboardShortcuts()</code>
+  method, described in the downloadable <a href=
+  "{@docRoot}preview/setup-sdk.html#docs-dl">API Reference</a>.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> The <strong>Meta</strong> key is not present on all
+  keyboards: on a Macintosh keyboard, it is the <strong>Command</strong> key,
+  on the Windows keyboard, it is the <strong>Windows</strong> key, and on the
+  Pixel C and the Chrome OS keyboards, it is the <strong>Search</strong> key.
 </p>
 
 <p>
-To trigger the Keyboard Shortcuts Helper from anywhere in your app,
-call {@code Activity.requestKeyboardShortcutsHelper()} for the relevant activity.
+  To trigger Keyboard Shortcuts Helper from anywhere in your app, call
+  {@code Activity.requestKeyboardShortcutsHelper()} for the relevant activity.
+</p>
+
+<h2 id="custom_pointer_api">
+  Custom Pointer API
+</h2>
+
+<p>
+  Android N introduces the Custom Pointer API, which lets you customize the
+  appearance, visibility, and behavior of the pointer. This capability is
+  especially useful when a user is using a mouse or touchpad to interact with
+  UI objects. The default pointer uses a standard icon. This API also includes
+  advanced functionality such as changing the pointer icon's appearance based
+  on specific mouse or touchpad movements.
+</p>
+
+<p>
+  To set a pointer icon, override the <code>onResolvePointerIcon()</code>
+  method of the <code>View</code> class. This method uses a
+  <code>PointerIcon</code> object to draw the icon that corresponds to a
+  specific motion event.
 </p>
 
 <h2 id="sustained_performance_api">Sustained Performance API</h2>
diff --git a/docs/html/preview/behavior-changes.jd b/docs/html/preview/behavior-changes.jd
index 66dce7a..ece6b43 100644
--- a/docs/html/preview/behavior-changes.jd
+++ b/docs/html/preview/behavior-changes.jd
@@ -612,5 +612,15 @@
 {@link android.content.pm.PackageInstaller#uninstall PackageInstaller.uninstall()}.
 </li>
 
+  <li>The JCA provider called <em>Crypto</em> is deprecated, because its only
+  algorithm, SHA1PRNG, is cryptographically weak. Apps can no longer use
+  SHA1PRNG to (insecurely) derive keys, because this provider is no longer
+  available. For more information, see the blog
+  post <a href=
+  "http://android-developers.blogspot.com/2016/06/security-crypto-provider-deprecated-in.html"
+  class="external-link">Security "Crypto" provider deprecated in Android
+  N</a>.
+  </li>
+
 </ul>
 
diff --git a/docs/html/preview/download-ota.jd b/docs/html/preview/download-ota.jd
index 2058501..18f3e8d 100644
--- a/docs/html/preview/download-ota.jd
+++ b/docs/html/preview/download-ota.jd
@@ -203,72 +203,72 @@
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >bullhead-ota-npd35k-b8cfbd80.zip</a><br>
-      MD5: 15fe2eba9b01737374196bdf0a792fe9<br>
-      SHA-1: 5014b2bba77f9e1a680ac3f90729621c85a14283
+      >bullhead-ota-npd56n-dd5c12ee.zip</a><br>
+      MD5: af9a82e9a78925ca9c1c7f5f6fb851ec<br>
+      SHA-1: e4aabd5634b7ebdeffa877cd9e49244c0be326e4
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >shamu-ota-npd35k-078e6fa5.zip</a><br>
-      MD5: e8b12f7721c53af9a450f7058928a5fc<br>
-      SHA-1: b7a9b756f84a1d2e482ff9c16749d65f6e51425a
+      >shamu-ota-npd56n-2818fd62.zip</a><br>
+      MD5: d8df396b187a8667889260e5464bd676<br>
+      SHA-1: c03c8ef8be587a574565855d4faa526254794e03
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >angler-ota-npd35k-88457699.zip</a><br>
-      MD5: 3fac09fef759dde26e57cb80b20b6477<br>
-      SHA-1: 27d6caa786577d8a38b2da5bf94b33b4524a1a1c
+      >angler-ota-npd56n-d2f2611c.zip</a><br>
+      MD5: c3c206892d414d4fc7da892ff840eada<br>
+      SHA-1: 2bdc79409ace5e163ef014ae51977d0a71b83df5
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantis-ota-npd35k-51dbae76.zip</a><br>
-      MD5: 58312c4a5971818ef5c77a3f446003da<br>
-      SHA-1: aad9005be33d3e2bab480509a6ab74c3c3b9d921
+      >volantis-ota-npd56n-42228a60.zip</a><br>
+      MD5: c80cf483d8b3c014fc7b27f80957a158<br>
+      SHA-1: f437829320f47ea3aa5f8b70ce2f0bb3d30b3f4f
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantisg-ota-npd35k-834f047f.zip</a><br>
-      MD5: 92b7d1fa252f7394e70f957c72d4aac8<br>
-      SHA-1: b6c057c84d90893630e303cbb60530e20ddb8361
+      >volantisg-ota-npd56n-9b4dbaac.zip</a><br>
+      MD5: 9e55ac1650e4f07a662bafa7f082e91c<br>
+      SHA-1: b9982be56c2817d122664869a1fbe9b13e9c72f7
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >fugu-ota-npd35k-6ac91298.zip</a><br>
-      MD5: 1461622ad53ea842b2722fa7b49b8172<br>
-      SHA-1: 409c061668ab270774877d7f3eae44fa48d2b931
+      >fugu-ota-npd56n-b305968a.zip</a><br>
+      MD5: dfc980acad6772d8473ccaa9cbbb681a<br>
+      SHA-1: d7bf8192649dea970afda165d181b4eea07abd7d
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >ryu-ota-npd35k-a0b2347f.zip</a><br>
-      MD5: c60117f3640cc6db12386fd632289c7d<br>
-      SHA-1: 87349c767c69efb4172c90ce1d88cf578c3d28b3
+      >ryu-ota-npd56n-5bf2fd66.zip</a><br>
+      MD5: 1699e4bacfbef16a75ae6cf3f2e3d886<br>
+      SHA-1: e20f3a8e43fcdd6acef21da80894afc8f9474e33
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >seed_l8150-ota-npd35k-09897a1d.zip</a><br>
-      MD5: a55cf94f7cce0393ec6c0b35041766b7<br>
-      SHA-1: 6f33742290eb46f2561891f38ca2e754b4e50c6a
+      >seed_l8150-ota-npd56n-a322696c.zip</a><br>
+      MD5: afc0e363ad2fd7418423e189a339a8e9<br>
+      SHA-1: fc4d818878df51894eac29932dd0e9f6511329c6
     </td>
   </tr>
 
diff --git a/docs/html/preview/download.jd b/docs/html/preview/download.jd
index b5405c7..ad82211 100644
--- a/docs/html/preview/download.jd
+++ b/docs/html/preview/download.jd
@@ -302,72 +302,72 @@
   <tr id="bullhead">
     <td>Nexus 5X <br>"bullhead"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >bullhead-npd35k-factory-5ba40535.tgz</a><br>
-      MD5: b6c5d79a21815ee21db41822dcf61e9f<br>
-      SHA-1: 5ba4053577007d15c96472206e3a79bc80ab194c
+      >bullhead-npd56n-factory-996cac57.tgz</a><br>
+      MD5: 5aadba91f60de00d58dc6198ef5cc3ba<br>
+      SHA-1: 996cac575d83bde573315290da8f52cecc4127d2
     </td>
   </tr>
 
   <tr id="shamu">
     <td>Nexus 6 <br>"shamu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >shamu-npd35k-factory-a33bf20c.tgz</a><br>
-      MD5: e1cf9c57cfb11bebe7f1f5bfbf05d7ab<br>
-      SHA-1: a33bf20c719206bcf08d1edd8da6c0ff9d50f69c
+      >shamu-npd56n-factory-7936bf75.tgz</a><br>
+      MD5: b7ed0db569f3bc2d6655fe8d8cea0e13<br>
+      SHA-1: 7936bf75e6bfb771bd14485211a319b246311b96
     </td>
   </tr>
 
   <tr id="angler">
     <td>Nexus 6P <br>"angler"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >angler-npd35k-factory-81c341d5.tgz</a><br>
-      MD5: e93de7949433339856124c3729c15ebb<br>
-      SHA-1: 81c341d57ef2cd139569b055d5d59e9e592a7abd
+      >angler-npd56n-factory-1ce5ccad.tgz</a><br>
+      MD5: f296eccaed4e2526d6435df8cf0e8df1<br>
+      SHA-1: 1ce5ccad8a3eae143e0ecd9c7afbb1be2f1d41cc
     </td>
   </tr>
 
   <tr id="volantis">
     <td>Nexus 9 <br>"volantis"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantis-npd35k-factory-2b50e19d.tgz</a><br>
-      MD5: 565be87ebb2d5937e2abe1a42645864b<br>
-      SHA-1: 2b50e19dae2667b27f911e3c61ed64860caf43e1
+      >volantis-npd56n-factory-8b9f997e.tgz</a><br>
+      MD5: 111c2fe5777dd6aae71fb8ef35dda9d3<br>
+      SHA-1: 8b9f997ea39fdaf505527536bd346948ae1bae30
     </td>
   </tr>
 
   <tr id="volantisg">
     <td>Nexus 9G <br>"volantisg"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >volantisg-npd35k-factory-2e89ebe6.tgz</a><br>
-      MD5: a8464e15c6683fe2afa378a63e205fda<br>
-      SHA-1: 2e89ebe67a46b2f3beb050746c13341cd11fa678
+      >volantisg-npd56n-factory-ef05106a.tgz</a><br>
+      MD5: 3a6f4d47b385966347bd26b7a922cd6e<br>
+      SHA-1: ef05106a9e3becea5673ea67d6c0cc21a2ec09d4
     </td>
   </tr>
 
   <tr id="fugu">
     <td>Nexus Player <br>"fugu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >fugu-npd35k-factory-1de74874.tgz</a><br>
-      MD5: c0dbb7db671f61b2785da5001cedefcb<br>
-      SHA-1: 1de74874f8d83e14d642f13b5a2130fc2aa55873
+      >fugu-npd56n-factory-a51674a1.tgz</a><br>
+      MD5: b75dc745a64848ea24124db8fa9252ed<br>
+      SHA-1: a51674a1303b17fec0405d513f9c0fe9f225780f
     </td>
   </tr>
 
   <tr id="ryu">
     <td>Pixel C <br>"ryu"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >ryu-npd35k-factory-b4eed85d.tgz</a><br>
-      MD5: bdcb6f770e753668b5fadff2a6678e0d<br>
-      SHA-1: b4eed85de0d42c200348a8629084f78e24f72ac2
+      >ryu-npd56n-factory-e36c49b1.tgz</a><br>
+      MD5: 0a2d660b09e19614a5b3573487b88066<br>
+      SHA-1: e36c49b184843cdfe10278aebc04ce50b6d670b6
     </td>
   </tr>
 
   <tr id="seed">
     <td>General Mobile 4G (Android One) <br>"seed"</td>
     <td><a href="#top" onclick="onDownload(this)"
-      >seed_l8150-npd35k-factory-5ab1212b.tgz</a><br>
-      MD5: 7d34a9774fdd6e025d485ce6cfc23c4c<br>
-      SHA-1: 5ab1212bc9417269d391aacf1e672fff24b4ecc5
+      >seed_l8150-npd56n-factory-dd5d4fd2.tgz</a><br>
+      MD5: 3420581b969af777753141dacc7f73b9<br>
+      SHA-1: dd5d4fd203f9c5dad658434c0ff370c411b78835
     </td>
   </tr>
 
diff --git a/docs/html/preview/features/direct-boot.jd b/docs/html/preview/features/direct-boot.jd
index 3d442d0..8351f4b 100644
--- a/docs/html/preview/features/direct-boot.jd
+++ b/docs/html/preview/features/direct-boot.jd
@@ -108,18 +108,25 @@
 
 <h2 id="notification">Getting Notified of User Unlock</h2>
 
-<p>Once the user unlocks the device after restart, your app can switch to
+<p>When the user unlocks the device after restart, your app can switch to
 accessing credential encrypted storage and use regular system services that
 depend on user credentials.</p>
 
 <p>To get notified when the user unlocks the device after a reboot,
 register a {@link android.content.BroadcastReceiver} from a running component
-to listen for the <code>ACTION_USER_UNLOCKED</code> message. Or, you can
-receive the existing {@link android.content.Intent#ACTION_BOOT_COMPLETED
-ACTION_BOOT_COMPLETED} message, which now indicates the device has booted and
-the user has unlocked the device.</p>
+to listen for unlock notification messages. When the user unlocks the device
+after boot:
+</p>
+<ul>
+<li>If your app has foreground processes that need immediate notification,
+listen for the {@code ACTION_USER_UNLOCKED} message.</li>
+<li>If your app only uses background processes that can act on a delayed
+notification, listen for the
+{@link android.content.Intent#ACTION_BOOT_COMPLETED ACTION_BOOT_COMPLETED}
+message.</li>
+</ul>
 
-<p>You can directly query if the user has unlocked the device by calling
+<p>If the user has unlocked the device, you can find out by calling
 <code>UserManager.isUserUnlocked()</code>.</p>
 
 <h2 id="migrating">Migrating Existing Data</h2>
diff --git a/docs/html/topic/libraries/support-library/revisions.jd b/docs/html/topic/libraries/support-library/revisions.jd
index 7525760..88b0ca1 100644
--- a/docs/html/topic/libraries/support-library/revisions.jd
+++ b/docs/html/topic/libraries/support-library/revisions.jd
@@ -6,6 +6,124 @@
 <p>This page provides details about the Support Library package releases.</p>
 
 <div class="toggle-content opened">
+  <p id="rev24-0-0">
+    <a href="#" onclick="return toggleContent(this)"><img src=
+    "{@docRoot}assets/images/styles/disclosure_up.png" class=
+    "toggle-content-img" alt="">Android Support Library, revision 24.0.0</a>
+    <em>(June 2016)</em>
+  </p>
+
+  <div class="toggle-content-toggleme">
+    <dl>
+      <dt>
+        Changes for <a href=
+        "{@docRoot}tools/support-library/features.html#v4">v4 Support
+        Library</a>:
+      </dt>
+
+      <dd>
+          <ul>
+            <li>Added <code>Fragment.commitNow()</code>
+            for synchronous commit
+            </li>
+
+            <li>Added <code>NotificationCompat.MessagingStyle</code>
+            for multi-party conversations
+            </li>
+
+            <li>Added <code>NotificationManagerCompat.areNotificationsEnabled()</code>
+            and <code>getImportance()</code>
+            </li>
+
+            <li>{@link android.support.v4.media.session.MediaSessionCompat}
+            now mirrors the functionality of {@link
+            android.media.session.MediaSession} and no longer calls {@link
+            android.media.session.MediaSession#setMediaButtonReceiver
+            setMediaButtonReceiver()} automatically
+            </li>
+          </ul>
+          <p class="note">
+            <strong>Note:</strong> <a href=
+            "{@docRoot}reference/android/support/v4/media/MediaBrowserServiceCompat.html"
+            ><code>MediaBrowserServiceCompat</code></a> is compatible with
+            devices running API Level 24 as of Support Library revision 24.0.0.
+            Older versions of <a href=
+            "{@docRoot}reference/android/support/v4/media/MediaBrowserServiceCompat.html"
+            ><code>MediaBrowserServiceCompat</code></a>
+            are <em>not</em> compatible with API Level 24. If your app uses
+            <a href=
+            "{@docRoot}reference/android/support/v4/media/MediaBrowserServiceCompat.html"
+            ><code>MediaBrowserServiceCompat</code></a> and
+            supports devices running API level 24, you must update to Support
+            Library version 24.0.0 or later.
+          </p>
+
+      <dt>
+        Changes for <a href=
+        "{@docRoot}tools/support-library/features.html#v7-appcompat">v7
+        appcompat library</a>:
+      </dt>
+
+      <dd>
+        <ul>
+          <li>Added support for referencing themed {@link
+            android.content.res.ColorStateList} objects from XML
+          </li>
+        </ul>
+      </dd>
+
+      <dt>
+        Changes for <a href=
+        "{@docRoot}tools/support-library/features.html#design">Design Support
+        Library</a>:
+      </dt>
+
+      <dd>
+        <ul>
+          <li>Improvements to {@link android.support.design.widget.AppBarLayout}
+            handling of elevation using {@link
+            android.animation.StateListAnimator}
+          </li>
+        </ul>
+      </dd>
+
+      <dt>
+        Changes for <a href=
+        "{@docRoot}topic/libraries/support-library/features.html#v17-leanback"
+        >v17 Leanback library</a>:
+      </dt>
+
+      <dd>
+        <ul>
+          <li>Added <code>OnboardingFragment</code> to provide first-run welcome
+            and setup flow
+          </li>
+        </ul>
+      </dd>
+
+      <dt>
+        Changes for <a href=
+        "{@docRoot}topic/libraries/support-library/features.html#custom-tabs"
+        >custom tabs</a>:
+      </dt>
+
+      <dd>
+        <ul>
+          <li>Added support for providing a {@link android.widget.RemoteViews}
+            hierarchy for the secondary toolbar</li>
+          <li>Added <code>CustomTabsClient.connectAndInitialize()</code>
+            for one-line warm up</li>
+        </ul>
+      </dd>
+
+    </dl>
+  </div>
+</div>
+
+<!-- end of collapsible section: 24.0.0 -->
+
+
+<div class="toggle-content closed">
   <p id="rev23-4-0">
     <a href="#" onclick="return toggleContent(this)"><img src=
     "{@docRoot}assets/images/styles/disclosure_up.png" class=
@@ -45,10 +163,9 @@
 
       <dd>
         <ul>
-          <li>Added <!-- TODO: Link to method -->
-             <code><a href=
-            "{@docRoot}reference/android/support/v7/app/AppCompatDelegate.html">
-            AppCompatDelegate</a>.setCompatVectorFromResourcesEnabled()</code>
+          <li>Added
+            {@link android.support.v7.app.AppCompatDelegate#setCompatVectorFromResourcesEnabled
+            AppCompatDelegate.setCompatVectorFromResourcesEnabled()}
             method to re-enable usage of vector drawables in {@link
             android.graphics.drawable.DrawableContainer} objects on devices
             running Android 4.4 (API level 19) and lower. See <a href=
@@ -118,8 +235,9 @@
 
       <dd>
         <ul>
-          <li>Fixed a bug where <!-- TODO: Javadoc link -->
-             <code>VectorDrawableCompat</code> does not render correctly in
+          <li>Fixed a bug where {@link
+            android.support.graphics.drawable.VectorDrawableCompat} does
+            not render correctly in
             {@link android.widget.TextView} on API level 23. (<a class=
             "external-link" href=
             "https://code.google.com/p/android/issues/detail?id=206227">Issue
diff --git a/docs/html/training/material/compatibility.jd b/docs/html/training/material/compatibility.jd
index 9ea88b2..8ebe6f6 100644
--- a/docs/html/training/material/compatibility.jd
+++ b/docs/html/training/material/compatibility.jd
@@ -127,7 +127,7 @@
 
 <p>To use these features in versions of Android earlier than 5.0 (API level 21), include the
 Android v7 Support Library in your project as a <a
-href="{@docRoot}/studio/build/index.html#dependencies">Gradle dependency</a>:</p>
+href="{@docRoot}studio/build/index.html#dependencies">Gradle dependency</a>:</p>
 
 <pre>
 dependencies {
diff --git a/docs/html/training/wearables/watch-faces/performance.jd b/docs/html/training/wearables/watch-faces/performance.jd
index 4a96545..a83a72b 100644
--- a/docs/html/training/wearables/watch-faces/performance.jd
+++ b/docs/html/training/wearables/watch-faces/performance.jd
@@ -6,30 +6,117 @@
 <div id="tb">
 <h2>This lesson teaches you to</h2>
 <ol>
+  <li><a href="#Basic">Basic Optimization</a></li>
+  <li><a href="#Animations">Best Practices for Animations</a></li>
   <li><a href="#ReduceSize">Reduce the Size of Your Bitmap Assets</a></li>
   <li><a href="#CombineBitmaps">Combine Bitmap Assets</a></li>
   <li><a href="#AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</a></li>
   <li><a href="#OutDrawing">Move Expensive Operations Outside the Drawing Method</a></li>
-  <li><a href="#SavePower">Follow Best Practices to Save Power</a></li>
 </ol>
 <h2>You should also read</h2>
 <ul>
   <li><a href="{@docRoot}design/wear/watchfaces.html">Watch Faces for Android Wear</a></li>
   <li><a href="http://android-developers.blogspot.com/2014/12/making-performant-watch-face.html">
 Making a performant watch face</a></li>
+  <li><a href="http://android-developers.blogspot.com/2016/04/deprecation-of-bindlistener.html">
+Deprecation of BIND_LISTENER with Android Wear APIs</a></li>
 </ul>
 </div>
 </div>
 
-<p>In addition to accommodating notification cards and system indicators, you need to ensure that
-the animations in your watch face run smoothly and that your service does not perform unnecessary
-computations. Watch faces in Android Wear run continuously on the device, so it is critical
-that your watch face uses power efficiently.</p>
+<p>This lesson has tips for conserving power and improving performance.
+A watch face runs continuously, so it must use power
+efficiently. </p>
 
-<p>This lesson provides some tips to speed up your animations and to measure and conserve
-power on the device.</p>
+<p>Services must not perform unnecessary computations.
+Watch faces with animations must run smoothly while accommodating
+notification cards and system indicators.</p>
 
+<h2 id="Basic">Basic Optimization</h2>
 
+<p>This section contains best practices for improving efficiency during
+periods when a watch face is inactive.</p>
+
+<h3>Use callbacks in WatchFaceService.Engine</h3>
+
+<p>Ensure that your watch face performs
+computations only when active; use callbacks
+in <a href="{@docRoot}reference/android/support/wearable/watchface/
+WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>.
+Preferably, use the following methods of that class to determine if
+the watch face is visible:</p>
+
+<ul>
+  <li>{@code onVisibilityChanged(boolean)}</li>
+  <li>{@code isVisible()}</li>
+</ul>
+
+<p>Alternatively, use the following methods of the same class
+(<a href="{@docRoot}reference/android/support/wearable/watchface/
+WatchFaceService.Engine.html">{@code WatchFaceService.Engine}</a>):</p>
+
+<ul>
+  <li>{@code onCreate()}</li>
+  <li>{@code onDestroy()}</li>
+</ul>
+
+<h3>Use listeners registered with the DataApi interface</h3>
+
+<p>To listen for events, use live listeners that are registered
+with <a href="https://developers.google.com/android/reference/com/google/
+android/gms/wearable/DataApi.html#addListener
+(com.google.android.gms.common.api.GoogleApiClient, com.
+google.android.gms.wearable.DataApi.DataListener)">{@code DataApi.addListener}</a>.
+For an example, see <a href="{@docRoot}training/wearables/data-layer/
+data-items.html#ListenEvents">Syncing Data Items</a>.</p>
+
+<p>Do not use <a href="https://developers.google.com/
+android/reference/com/google/android/gms/wearable/
+WearableListenerService">{@code WearableListenerService}</a> to listen for
+events, because it is
+called whether or not a watch face is active. For more information, see
+<a href="http://android-developers.blogspot.com/2016/04/
+deprecation-of-bindlistener.html">Deprecation of BIND_LISTENER
+with Android Wear APIs</a>.</p>
+
+<p>Do not register a broadcast receiver in the Android manifest file
+to get system events such as time zone changes, battery events, etc., because
+the <a href="{@docRoot}reference/android/content/BroadcastReceiver.html">{@code BroadcastReceiver}</a>
+is called whether or not a watch face is active. However, you can use the
+<a href="{@docRoot}reference/android/content/Context.html#registerReceiver(android.
+content.BroadcastReceiver, android.content.IntentFilter)">{@code registerReceiver}</a> method
+of the {@code Context} class to register a receiver.</p>
+
+<h3>Monitor power consumption</h3>
+
+<p>The <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">
+Android Wear companion app</a> enables developers and users to see how much battery
+is consumed by different processes
+on the wearable device (under <strong>Settings</strong> > <strong>Watch
+battery</strong>).</p>
+
+<p>For information about features introduced in Android 5.0 that help you improve battery life,
+see <a href="{@docRoot}about/versions/android-5.0.html#Power">Project Volta</a>.</p>
+
+<h2 id="Animations">Best Practices for Animations</h2>
+
+<p>The best practices in this section help to reduce the power consumption of animations.</p>
+
+<h3>Reduce the frame rate of animations</h3>
+
+<p>Animations are often computationally expensive and consume a significant amount of power. Most
+animations look fluid at 30 frames per second, so you should avoid running your animations
+at a higher frame rate.</p>
+
+<h3>Let the CPU sleep between animations</h3>
+
+<p>Animations and small changes to the contents of the watch face wake up the CPU. Your watch
+face should let the CPU sleep in between animations. For example, you can use short bursts of
+animation every second in interactive mode and then let the CPU sleep until the next second.
+Letting the CPU sleep often, even briefly, can significantly reduce power consumption.</p>
+
+<p>To maximize battery life, use animations sparingly. Even a blinking colon wakes up the CPU with
+every blink and hurts battery life.</p>
 
 <h2 id="ReduceSize">Reduce the Size of Your Bitmap Assets</h2>
 
@@ -68,16 +155,12 @@
 <p>Reducing the size of your bitmap assets as described in this section not only improves
 the performance of your animations, but it also saves power.</p>
 
-
-
 <h2 id="CombineBitmaps">Combine Bitmap Assets</h2>
 
 <p>If you have bitmaps that are often drawn together, consider combining them into the same
 graphic asset. You can often combine the background image in interactive mode with the tick
 marks to avoid drawing two full-screen bitmaps every time the system redraws the watch face.</p>
 
-
-
 <h2 id="AntiAlias">Disable Anti-Aliasing when Drawing Scaled Bitmaps</h2>
 
 <p>When you draw a scaled bitmap on the {@link android.graphics.Canvas} object using the {@link
@@ -139,35 +222,3 @@
 consistent across invocations. For more information, see
 <a href="{@docRoot}tools/debugging/ddms.html">Using DDMS</a>.</p>
 
-
-
-<h2 id="SavePower">Follow Best Practices to Save Power</h2>
-
-<p>In addition to the techniques described in the previous sections, follow the best
-practices in this section to reduce the power consumption of your watch face.</p>
-
-<h3>Reduce the frame rate of animations</h3>
-
-<p>Animations are often computationally expensive and consume a significant amount of power. Most
-animations look fluid at 30 frames per second, so you should avoid running your animations
-at a higher frame rate.</p>
-
-<h3>Let the CPU sleep</h3>
-
-<p>Animations and small changes to the contents of the watch face wake up the CPU. Your watch
-face should let the CPU sleep in between animations. For example, you can use short bursts of
-animation every second in interactive mode and then let the CPU sleep until the next second.
-Letting the CPU sleep often, even briefly, can significantly reduce power consumption.</p>
-
-<p>To maximize battery life, use animations sparingly. Even a blinking colon wakes up the CPU with
-every blink and hurts battery life.</p>
-
-<h3>Monitor power consumption</h3>
-
-<p>The <a href="https://play.google.com/store/apps/details?id=com.google.android.wearable.app&hl=en">
-Android Wear companion app</a> lets developers and users see how much battery different processes
-on the wearable device are consuming under <strong>Settings</strong> > <strong>Watch
-battery</strong>.</p>
-
-<p>For more information about new features in Android 5.0 that help you improve battery life,
-see <a href="{@docRoot}about/versions/android-5.0.html#Power">Project Volta</a>.</p>
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index e6399d4..c626c54 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -149,6 +149,8 @@
             if (mEglManager.isCurrent(mEglSurface)) {
                 mEglManager.makeCurrent(EGL_NO_SURFACE);
             }
+        } else if (mIsDirty && hasSurface()) {
+            mRenderThread.postFrameCallback(this);
         }
     }
 }
@@ -231,6 +233,8 @@
     freePrefetchedLayers(info.observer);
     GL_CHECKPOINT(MODERATE);
 
+    mIsDirty = true;
+
     if (CC_UNLIKELY(!mNativeSurface.get())) {
         mCurrentFrameInfo->addFlag(FrameInfoFlags::SkippedFrame);
         info.out.canDrawThisFrame = false;
@@ -503,6 +507,7 @@
     // Even if we decided to cancel the frame, from the perspective of jank
     // metrics the frame was swapped at this point
     mCurrentFrameInfo->markSwapBuffers();
+    mIsDirty = false;
 
     if (drew || mEglManager.damageRequiresSwap()) {
         if (CC_UNLIKELY(!mEglManager.swapBuffers(frame, screenDirty))) {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index e739b29..a6eb7ad 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -187,7 +187,12 @@
     EglManager& mEglManager;
     sp<Surface> mNativeSurface;
     EGLSurface mEglSurface = EGL_NO_SURFACE;
+    // stopped indicates the CanvasContext will reject actual redraw operations,
+    // and defer repaint until it is un-stopped
     bool mStopped = false;
+    // CanvasContext is dirty if it has received an update that it has not
+    // painted onto its surface.
+    bool mIsDirty = false;
     bool mBufferPreserved = false;
     SwapBehavior mSwapBehavior = kSwap_default;
     struct SwapHistory {
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java
index 3f6081b..4d40e6b 100644
--- a/media/java/android/media/MediaPlayer.java
+++ b/media/java/android/media/MediaPlayer.java
@@ -709,6 +709,8 @@
      * played.
      *
      * @param sh the SurfaceHolder to use for video display
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized or has been released.
      */
     public void setDisplay(SurfaceHolder sh) {
         mSurfaceHolder = sh;
@@ -739,6 +741,8 @@
      *
      * @param surface The {@link Surface} to be used for the video portion of
      * the media.
+     * @throws IllegalStateException if the internal player engine has not been
+     * initialized or has been released.
      */
     public void setSurface(Surface surface) {
         if (mScreenOnWhilePlaying && surface != null) {
diff --git a/packages/PrintRecommendationService/AndroidManifest.xml b/packages/PrintRecommendationService/AndroidManifest.xml
index 0eb218c..c6736d7 100644
--- a/packages/PrintRecommendationService/AndroidManifest.xml
+++ b/packages/PrintRecommendationService/AndroidManifest.xml
@@ -17,7 +17,12 @@
  */
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
-    package="com.android.printservice.recommendation">
+    package="com.android.printservice.recommendation"
+    android:versionCode="1"
+    android:versionName="1.0.0">
+
+    <uses-sdk android:minSdkVersion="24"
+        android:targetSdkVersion="24" />
 
     <uses-permission android:name="android.permission.INTERNET" />
 
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
index e071f6a..284827b 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPointPreference.java
@@ -28,13 +28,10 @@
 import android.text.TextUtils;
 import android.util.AttributeSet;
 import android.util.SparseArray;
-import android.view.View;
 import android.widget.TextView;
 
 import com.android.settingslib.R;
 
-import java.util.Objects;
-
 public class AccessPointPreference extends Preference {
 
     private static final int[] STATE_SECURED = {
@@ -111,7 +108,6 @@
             mTitleView.setCompoundDrawablePadding(mBadgePadding);
         }
         view.itemView.setContentDescription(mContentDescription);
-        view.itemView.setAccessibilityLiveRegion(View.ACCESSIBILITY_LIVE_REGION_POLITE);
     }
 
     protected void updateIcon(int level, Context context) {
@@ -152,7 +148,6 @@
      * Updates the title and summary; may indirectly call notifyChanged().
      */
     public void refresh() {
-        boolean updated = false;
         if (mForSavedNetworks) {
             setTitle(mAccessPoint.getConfigName());
         } else {
@@ -164,28 +159,21 @@
         if (level != mLevel) {
             mLevel = level;
             updateIcon(mLevel, context);
-            updated = true;
+            notifyChanged();
         }
         updateBadge(context);
 
         setSummary(mForSavedNetworks ? mAccessPoint.getSavedNetworkSummary()
                 : mAccessPoint.getSettingsSummary());
 
-        CharSequence contentDescription = getTitle();
+        mContentDescription = getTitle();
         if (getSummary() != null) {
-            contentDescription = TextUtils.concat(contentDescription, ",", getSummary());
+            mContentDescription = TextUtils.concat(mContentDescription, ",", getSummary());
         }
         if (level >= 0 && level < WIFI_CONNECTION_STRENGTH.length) {
-            contentDescription = TextUtils.concat(contentDescription, ",",
+            mContentDescription = TextUtils.concat(mContentDescription, ",",
                     getContext().getString(WIFI_CONNECTION_STRENGTH[level]));
         }
-        if (!Objects.equals(contentDescription, mContentDescription)) {
-            mContentDescription = contentDescription;
-            updated = true;
-        }
-        if (updated) {
-            notifyChanged();
-        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
index 9fb8bd5..2c5c437 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/misc/Utilities.java
@@ -34,6 +34,7 @@
 import android.util.Property;
 import android.util.TypedValue;
 import android.view.View;
+import android.view.ViewGroup;
 import android.view.ViewParent;
 import android.view.ViewStub;
 
@@ -285,6 +286,26 @@
     }
 
     /**
+     * Returns whether this view, or one of its descendants have accessibility focus.
+     */
+    public static boolean isDescendentAccessibilityFocused(View v) {
+        if (v.isAccessibilityFocused()) {
+            return true;
+        }
+
+        if (v instanceof ViewGroup) {
+            ViewGroup vg = (ViewGroup) v;
+            int childCount = vg.getChildCount();
+            for (int i = 0; i < childCount; i++) {
+                if (isDescendentAccessibilityFocused(vg.getChildAt(i))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
      * Returns the application configuration, which is independent of the activity's current
      * configuration in multiwindow.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
index 231360e..586a8bc 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackView.java
@@ -44,6 +44,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.AccessibilityNodeInfo;
 import android.widget.FrameLayout;
+import android.widget.ScrollView;
 
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.MetricsProto.MetricsEvent;
@@ -170,7 +171,7 @@
     @ViewDebug.ExportedProperty(category="recents")
     private boolean mEnterAnimationComplete = false;
     @ViewDebug.ExportedProperty(category="recents")
-    private boolean mTouchExplorationEnabled;
+    boolean mTouchExplorationEnabled;
     @ViewDebug.ExportedProperty(category="recents")
     boolean mScreenPinningEnabled;
 
@@ -579,7 +580,7 @@
             if (task.isFreeformTask() || (transform != null && transform.visible)) {
                 mTmpTaskViewMap.put(task.key, tv);
             } else {
-                if (mTouchExplorationEnabled) {
+                if (mTouchExplorationEnabled && Utilities.isDescendentAccessibilityFocused(tv)) {
                     lastFocusedTaskIndex = taskIndex;
                     resetFocusedTask(task);
                 }
@@ -630,12 +631,14 @@
 
         // Update the focus if the previous focused task was returned to the view pool
         if (lastFocusedTaskIndex != -1) {
-            if (lastFocusedTaskIndex < visibleTaskRange[1]) {
-                setFocusedTask(visibleTaskRange[1], false /* scrollToTask */,
-                        true /* requestViewFocus */);
-            } else {
-                setFocusedTask(visibleTaskRange[0], false /* scrollToTask */,
-                        true /* requestViewFocus */);
+            int newFocusedTaskIndex = (lastFocusedTaskIndex < visibleTaskRange[1])
+                    ? visibleTaskRange[1]
+                    : visibleTaskRange[0];
+            setFocusedTask(newFocusedTaskIndex, false /* scrollToTask */,
+                    true /* requestViewFocus */);
+            TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
+            if (focusedTaskView != null) {
+                focusedTaskView.requestAccessibilityFocus();
             }
         }
     }
@@ -938,24 +941,7 @@
      *                            focus.
      */
     public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated) {
-        setRelativeFocusedTask(forward, stackTasksOnly, animated, false);
-    }
-
-    /**
-     * Sets the focused task relative to the currently focused task.
-     *
-     * @param forward whether to go to the next task in the stack (along the curve) or the previous
-     * @param stackTasksOnly if set, will ensure that the traversal only goes along stack tasks, and
-     *                       if the currently focused task is not a stack task, will set the focus
-     *                       to the first visible stack task
-     * @param animated determines whether to actually draw the highlight along with the change in
-     *                            focus.
-     * @param cancelWindowAnimations if set, will attempt to cancel window animations if a scroll
-     *                               happens.
-     */
-    public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
-                                       boolean cancelWindowAnimations) {
-        setRelativeFocusedTask(forward, stackTasksOnly, animated, cancelWindowAnimations, 0);
+        setRelativeFocusedTask(forward, stackTasksOnly, animated, false, 0);
     }
 
     /**
@@ -972,13 +958,13 @@
      * @param timerIndicatorDuration the duration to initialize the auto-advance timer indicator
      */
     public void setRelativeFocusedTask(boolean forward, boolean stackTasksOnly, boolean animated,
-                                       boolean cancelWindowAnimations,
-                                       int timerIndicatorDuration) {
-        int newIndex = mStack.indexOfStackTask(mFocusedTask);
-        if (mFocusedTask != null) {
+                                       boolean cancelWindowAnimations, int timerIndicatorDuration) {
+        Task focusedTask = getFocusedTask();
+        int newIndex = mStack.indexOfStackTask(focusedTask);
+        if (focusedTask != null) {
             if (stackTasksOnly) {
                 List<Task> tasks =  mStack.getStackTasks();
-                if (mFocusedTask.isFreeformTask()) {
+                if (focusedTask.isFreeformTask()) {
                     // Try and focus the front most stack task
                     TaskView tv = getFrontMostTaskView(stackTasksOnly);
                     if (tv != null) {
@@ -1054,6 +1040,25 @@
         return mFocusedTask;
     }
 
+    /**
+     * Returns the accessibility focused task.
+     */
+    Task getAccessibilityFocusedTask() {
+        List<TaskView> taskViews = getTaskViews();
+        int taskViewCount = taskViews.size();
+        for (int i = 0; i < taskViewCount; i++) {
+            TaskView tv = taskViews.get(i);
+            if (Utilities.isDescendentAccessibilityFocused(tv)) {
+                return tv.getTask();
+            }
+        }
+        TaskView frontTv = getFrontMostTaskView(true /* stackTasksOnly */);
+        if (frontTv != null) {
+            return frontTv.getTask();
+        }
+        return null;
+    }
+
     @Override
     public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
         super.onInitializeAccessibilityEvent(event);
@@ -1078,21 +1083,23 @@
         super.onInitializeAccessibilityNodeInfo(info);
         List<TaskView> taskViews = getTaskViews();
         int taskViewCount = taskViews.size();
-        if (taskViewCount > 1 && mFocusedTask != null) {
+        if (taskViewCount > 1) {
+            // Find the accessibility focused task
+            Task focusedTask = getAccessibilityFocusedTask();
             info.setScrollable(true);
-            int focusedTaskIndex = mStack.indexOfStackTask(mFocusedTask);
+            int focusedTaskIndex = mStack.indexOfStackTask(focusedTask);
             if (focusedTaskIndex > 0) {
-                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
-            }
-            if (focusedTaskIndex < mStack.getTaskCount() - 1) {
                 info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
             }
+            if (0 <= focusedTaskIndex && focusedTaskIndex < mStack.getTaskCount() - 1) {
+                info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
+            }
         }
     }
 
     @Override
     public CharSequence getAccessibilityClassName() {
-        return TaskStackView.class.getName();
+        return ScrollView.class.getName();
     }
 
     @Override
@@ -1100,14 +1107,20 @@
         if (super.performAccessibilityAction(action, arguments)) {
             return true;
         }
-        switch (action) {
-            case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
-                setRelativeFocusedTask(true, false /* stackTasksOnly */, false /* animated */);
-                return true;
-            }
-            case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
-                setRelativeFocusedTask(false, false /* stackTasksOnly */, false /* animated */);
-                return true;
+        Task focusedTask = getAccessibilityFocusedTask();
+        int taskIndex = mStack.indexOfStackTask(focusedTask);
+        if (0 <= taskIndex && taskIndex < mStack.getTaskCount()) {
+            switch (action) {
+                case AccessibilityNodeInfo.ACTION_SCROLL_FORWARD: {
+                    setFocusedTask(taskIndex + 1, true /* scrollToTask */, true /* requestViewFocus */,
+                            0);
+                    return true;
+                }
+                case AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD: {
+                    setFocusedTask(taskIndex - 1, true /* scrollToTask */, true /* requestViewFocus */,
+                            0);
+                    return true;
+                }
             }
         }
         return false;
@@ -1489,6 +1502,7 @@
         unbindTaskView(tv, task);
 
         // Reset the view properties and view state
+        tv.clearAccessibilityFocus();
         tv.resetViewProperties();
         tv.setFocusedState(false, false /* requestViewFocus */);
         tv.setClipViewInStack(false);
@@ -1949,6 +1963,10 @@
                         RecentsActivityLaunchState launchState = config.getLaunchState();
                         setFocusedTask(mStack.indexOfStackTask(mFocusedTask),
                                 false /* scrollToTask */, launchState.launchedWithAltTab);
+                        TaskView focusedTaskView = getChildViewForTask(mFocusedTask);
+                        if (mTouchExplorationEnabled && focusedTaskView != null) {
+                            focusedTaskView.requestAccessibilityFocus();
+                        }
                     }
 
                     EventBus.getDefault().send(new EnterRecentsTaskStackAnimationCompletedEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
index b554a46..67a2595 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskStackViewTouchHandler.java
@@ -343,7 +343,9 @@
                     }
 
                     // Reset the focused task after the user has scrolled
-                    mSv.resetFocusedTask(mSv.getFocusedTask());
+                    if (!mSv.mTouchExplorationEnabled) {
+                        mSv.resetFocusedTask(mSv.getFocusedTask());
+                    }
                 } else if (mActiveTaskView == null) {
                     // This tap didn't start on a task.
                     maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY());
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
index 612c41d..4ecdd77 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/TaskView.java
@@ -133,8 +133,6 @@
     @ViewDebug.ExportedProperty(deepExport=true, prefix="task_")
     private Task mTask;
     @ViewDebug.ExportedProperty(category="recents")
-    private boolean mTaskDataLoaded;
-    @ViewDebug.ExportedProperty(category="recents")
     private boolean mClipViewInStack = true;
     @ViewDebug.ExportedProperty(category="recents")
     private boolean mTouchExplorationEnabled;
@@ -451,16 +449,12 @@
      * Explicitly sets the focused state of this task.
      */
     public void setFocusedState(boolean isFocused, boolean requestViewFocus) {
-        SystemServicesProxy ssp = Recents.getSystemServices();
         if (isFocused) {
             if (requestViewFocus && !isFocused()) {
                 requestFocus();
             }
-            if (requestViewFocus && !isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) {
-                requestAccessibilityFocus();
-            }
         } else {
-            if (isAccessibilityFocused() && ssp.isTouchExplorationEnabled()) {
+            if (isAccessibilityFocused() && mTouchExplorationEnabled) {
                 clearAccessibilityFocus();
             }
         }
@@ -622,7 +616,6 @@
         // Update each of the views to the new task data
         mThumbnailView.onTaskDataLoaded(thumbnailInfo);
         mHeaderView.onTaskDataLoaded();
-        mTaskDataLoaded = true;
     }
 
     @Override
@@ -631,7 +624,6 @@
         mTask.removeCallback(this);
         mThumbnailView.unbindFromTask();
         mHeaderView.unbindFromTask(mTouchExplorationEnabled);
-        mTaskDataLoaded = false;
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index aedc7df..28a6851 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -193,6 +193,13 @@
         mGroupExpansionChanging = changing;
     }
 
+    @Override
+    public void setActualHeightAnimating(boolean animating) {
+        if (mPrivateLayout != null) {
+            mPrivateLayout.setContentHeightAnimating(animating);
+        }
+    }
+
     public NotificationContentView getPrivateLayout() {
         return mPrivateLayout;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
index 2c302ed..b4f90c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableView.java
@@ -432,6 +432,8 @@
         return false;
     }
 
+    public void setActualHeightAnimating(boolean animating) {}
+
     /**
      * A listener notifying when {@link #getActualHeight} changes.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
index 21fed3c..a11263a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationContentView.java
@@ -106,13 +106,19 @@
     private boolean mExpandable;
     private boolean mClipToActualHeight = true;
     private ExpandableNotificationRow mContainingNotification;
+    /** The visible type at the start of a touch driven transformation */
     private int mTransformationStartVisibleType;
+    /** The visible type at the start of an animation driven transformation */
+    private int mAnimationStartVisibleType = UNDEFINED;
     private boolean mUserExpanding;
     private int mSingleLineWidthIndention;
     private boolean mForceSelectNextLayout = true;
     private PendingIntent mPreviousExpandedRemoteInputIntent;
     private PendingIntent mPreviousHeadsUpRemoteInputIntent;
 
+    private int mContentHeightAtAnimationStart = UNDEFINED;
+
+
     public NotificationContentView(Context context, AttributeSet attrs) {
         super(context, attrs);
         mHybridGroupManager = new HybridGroupManager(getContext(), this);
@@ -258,7 +264,14 @@
 
     @Override
     protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        int previousHeight = 0;
+        if (mExpandedChild != null) {
+            previousHeight = mExpandedChild.getHeight();
+        }
         super.onLayout(changed, left, top, right, bottom);
+        if (previousHeight != 0 && mExpandedChild.getHeight() != previousHeight) {
+            mContentHeightAtAnimationStart = previousHeight;
+        }
         updateClipping();
         invalidateOutline();
         selectLayout(false /* animate */, mForceSelectNextLayout /* force */);
@@ -408,24 +421,54 @@
      *         height, the notification is clipped instead of being further shrunk.
      */
     private int getMinContentHeightHint() {
-        if (mIsChildInGroup && (mVisibleType == VISIBLE_TYPE_SINGLELINE
-                || mTransformationStartVisibleType == VISIBLE_TYPE_SINGLELINE)) {
+        if (mIsChildInGroup && isVisibleOrTransitioning(VISIBLE_TYPE_SINGLELINE)) {
             return mContext.getResources().getDimensionPixelSize(
                         com.android.internal.R.dimen.notification_action_list_height);
         }
+
+        // Transition between heads-up & expanded, or pinned.
+        if (mHeadsUpChild != null && mExpandedChild != null) {
+            boolean transitioningBetweenHunAndExpanded =
+                    isTransitioningFromTo(VISIBLE_TYPE_HEADSUP, VISIBLE_TYPE_EXPANDED) ||
+                    isTransitioningFromTo(VISIBLE_TYPE_EXPANDED, VISIBLE_TYPE_HEADSUP);
+            boolean pinned = !isVisibleOrTransitioning(VISIBLE_TYPE_CONTRACTED) && mIsHeadsUp;
+            if (transitioningBetweenHunAndExpanded || pinned) {
+                return Math.min(mHeadsUpChild.getHeight(), mExpandedChild.getHeight());
+            }
+        }
+
+        // Size change of the expanded version
+        if ((mVisibleType == VISIBLE_TYPE_EXPANDED) && mContentHeightAtAnimationStart >= 0
+                && mExpandedChild != null) {
+            return Math.min(mContentHeightAtAnimationStart, mExpandedChild.getHeight());
+        }
+
         int hint;
-        if (mHeadsUpChild != null) {
+        if (mHeadsUpChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_HEADSUP)) {
             hint = mHeadsUpChild.getHeight();
+        } else if (mExpandedChild != null) {
+            hint = mExpandedChild.getHeight();
         } else {
             hint = mContractedChild.getHeight() + mContext.getResources().getDimensionPixelSize(
                     com.android.internal.R.dimen.notification_action_list_height);
         }
-        if (mExpandedChild != null) {
+
+        if (mExpandedChild != null && isVisibleOrTransitioning(VISIBLE_TYPE_EXPANDED)) {
             hint = Math.min(hint, mExpandedChild.getHeight());
         }
         return hint;
     }
 
+    private boolean isTransitioningFromTo(int from, int to) {
+        return (mTransformationStartVisibleType == from || mAnimationStartVisibleType == from)
+                && mVisibleType == to;
+    }
+
+    private boolean isVisibleOrTransitioning(int type) {
+        return mVisibleType == type || mTransformationStartVisibleType == type
+                || mAnimationStartVisibleType == type;
+    }
+
     private void updateContentTransformation() {
         int visibleType = calculateVisibleType();
         if (visibleType != mVisibleType) {
@@ -656,6 +699,7 @@
             shownView.setVisible(true);
             return;
         }
+        mAnimationStartVisibleType = mVisibleType;
         shownView.transformFrom(hiddenView);
         getViewForVisibleType(visibleType).setVisibility(View.VISIBLE);
         hiddenView.transformTo(shownView, new Runnable() {
@@ -664,6 +708,7 @@
                 if (hiddenView != getTransformableViewForVisibleType(mVisibleType)) {
                     hiddenView.setVisible(false);
                 }
+                mAnimationStartVisibleType = UNDEFINED;
             }
         });
     }
@@ -1082,4 +1127,10 @@
             mHeadsUpRemoteInput.setRemoved();
         }
     }
+
+    public void setContentHeightAnimating(boolean animating) {
+        if (!animating) {
+            mContentHeightAtAnimationStart = UNDEFINED;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
index c0373be..8c72544 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActionListTransformState.java
@@ -44,6 +44,16 @@
     }
 
     @Override
+    public void transformViewFullyFrom(TransformState otherState, float transformationAmount) {
+        // Don't do Y transform - let the wrapper handle this based on the content height
+    }
+
+    @Override
+    public void transformViewFullyTo(TransformState otherState, float transformationAmount) {
+        // Don't do Y transform - let the wrapper handle this based on the content height
+    }
+
+    @Override
     protected void resetTransformedView() {
         // We need to keep the Y transformation, because this is used to keep the action list
         // aligned at the bottom, unrelated to transforms.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
index 0f94227..7ac0d80 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/StackStateAnimator.java
@@ -485,6 +485,7 @@
                 child.setTag(TAG_ANIMATOR_HEIGHT, null);
                 child.setTag(TAG_START_HEIGHT, null);
                 child.setTag(TAG_END_HEIGHT, null);
+                child.setActualHeightAnimating(false);
                 if (!mWasCancelled && child instanceof ExpandableNotificationRow) {
                     ((ExpandableNotificationRow) child).setGroupExpansionChanging(
                             false /* isExpansionChanging */);
@@ -505,6 +506,7 @@
         child.setTag(TAG_ANIMATOR_HEIGHT, animator);
         child.setTag(TAG_START_HEIGHT, child.getActualHeight());
         child.setTag(TAG_END_HEIGHT, newEndValue);
+        child.setActualHeightAnimating(true);
     }
 
     private void startInsetAnimation(final ExpandableView child,
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
index c6992aa..1973e05 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialog.java
@@ -977,6 +977,7 @@
             final int density = newConfig.densityDpi;
             if (density != mDensity) {
                 mDialog.dismiss();
+                mZenFooter.cleanup();
                 initDialog();
             }
             updateWindowWidthH();
diff --git a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
index 65975d9..f01e95f 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/ZenFooter.java
@@ -79,18 +79,11 @@
         mZen = controller.getZen();
         mConfig = controller.getConfig();
         mController = controller;
+        mController.addCallback(mZenCallback);
         update();
     }
 
-    @Override
-    protected void onAttachedToWindow() {
-        super.onAttachedToWindow();
-        mController.addCallback(mZenCallback);
-    }
-
-    @Override
-    protected void onDetachedFromWindow() {
-        super.onDetachedFromWindow();
+    public void cleanup() {
         mController.removeCallback(mZenCallback);
     }
 
diff --git a/services/core/java/com/android/server/AlarmManagerService.java b/services/core/java/com/android/server/AlarmManagerService.java
index 8ad6e6a..400c4a7 100644
--- a/services/core/java/com/android/server/AlarmManagerService.java
+++ b/services/core/java/com/android/server/AlarmManagerService.java
@@ -3073,9 +3073,14 @@
                 fs.numWakeup++;
                 if (alarm.workSource != null && alarm.workSource.size() > 0) {
                     for (int wi=0; wi<alarm.workSource.size(); wi++) {
+                        final String wsName = alarm.workSource.getName(wi);
+                        if (wsName == null) {
+                            Slog.w(TAG, "Null worksource name for alarm " + alarm);
+                        }
                         ActivityManagerNative.noteWakeupAlarm(
                                 alarm.operation, alarm.workSource.get(wi),
-                                alarm.workSource.getName(wi), alarm.statsTag);
+                                (wsName != null) ? wsName : alarm.packageName,
+                                alarm.statsTag);
                     }
                 } else {
                     ActivityManagerNative.noteWakeupAlarm(
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index df85cfa..d83a750 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2581,14 +2581,11 @@
     }
 
     private void insertTaskAtTop(TaskRecord task, ActivityRecord newActivity) {
-        boolean isLastTaskOverHome = false;
         // If the moving task is over home stack, transfer its return type to next task
         if (task.isOverHomeStack()) {
             final TaskRecord nextTask = getNextTask(task);
             if (nextTask != null) {
                 nextTask.setTaskToReturnTo(task.getTaskToReturnTo());
-            } else {
-                isLastTaskOverHome = true;
             }
         }
 
@@ -2598,10 +2595,7 @@
             ActivityStack lastStack = mStackSupervisor.getLastStack();
             final boolean fromHome = lastStack.isHomeStack();
             if (!isHomeStack() && (fromHome || topTask() != task)) {
-                // If it's a last task over home - we default to keep its return to type not to
-                // make underlying task focused when this one will be finished.
-                int returnToType = isLastTaskOverHome
-                        ? task.getTaskToReturnTo() : APPLICATION_ACTIVITY_TYPE;
+                int returnToType = APPLICATION_ACTIVITY_TYPE;
                 if (fromHome && StackId.allowTopTaskToReturnHome(mStackId)) {
                     returnToType = lastStack.topTask() == null
                             ? HOME_ACTIVITY_TYPE : lastStack.topTask().taskType;
diff --git a/services/core/java/com/android/server/am/ActivityStartInterceptor.java b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
index 566d8d9..a2c2040 100644
--- a/services/core/java/com/android/server/am/ActivityStartInterceptor.java
+++ b/services/core/java/com/android/server/am/ActivityStartInterceptor.java
@@ -147,6 +147,9 @@
         }
         DevicePolicyManagerInternal devicePolicyManager = LocalServices.getService(
                 DevicePolicyManagerInternal.class);
+        if (devicePolicyManager == null) {
+            return false;
+        }
         mIntent = devicePolicyManager.createPackageSuspendedDialogIntent(
                 mAInfo.packageName, mUserId);
         mCallingPid = mRealCallingPid;
diff --git a/services/core/java/com/android/server/content/ContentService.java b/services/core/java/com/android/server/content/ContentService.java
index 1b2ccd7..9220aa3 100644
--- a/services/core/java/com/android/server/content/ContentService.java
+++ b/services/core/java/com/android/server/content/ContentService.java
@@ -22,6 +22,7 @@
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.AppOpsManager;
+import android.app.job.JobInfo;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentProvider;
@@ -512,6 +513,16 @@
         syncAsUser(request, UserHandle.getCallingUserId());
     }
 
+    private long clampPeriod(long period) {
+        long minPeriod = JobInfo.getMinPeriodMillis() / 1000;
+        if (period < minPeriod) {
+            Slog.w(TAG, "Requested poll frequency of " + period
+                    + " seconds being rounded up to " + minPeriod + "s.");
+            period = minPeriod;
+        }
+        return period;
+    }
+
     /**
      * If the user id supplied is different to the calling user, the caller must hold the
      * INTERACT_ACROSS_USERS_FULL permission.
@@ -539,11 +550,8 @@
                 SyncStorageEngine.EndPoint info;
                 info = new SyncStorageEngine.EndPoint(
                         request.getAccount(), request.getProvider(), userId);
-                if (runAtTime < 3600) {
-                    Slog.w(TAG, "Requested poll frequency of " + runAtTime
-                            + " seconds being rounded up to 1 hour.");
-                    runAtTime = 3600;
-                }
+
+                runAtTime = clampPeriod(runAtTime);
                 // Schedule periodic sync.
                 getSyncManager().updateOrAddPeriodicSync(info, runAtTime,
                         flextime, extras);
@@ -761,11 +769,8 @@
                 "no permission to write the sync settings");
 
         int userId = UserHandle.getCallingUserId();
-        if (pollFrequency < 3600) {
-            Slog.w(TAG, "Requested poll frequency of " + pollFrequency
-                    + " seconds being rounded up to 1 hour.");
-            pollFrequency = 3600;
-        }
+
+        pollFrequency = clampPeriod(pollFrequency);
         long defaultFlex = SyncStorageEngine.calculateDefaultFlexTime(pollFrequency);
 
         long identityToken = clearCallingIdentity();
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 4692a57..b528016 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -8139,21 +8139,23 @@
             Intent intent = new Intent(Settings.ACTION_SHOW_ADMIN_SUPPORT_DETAILS);
             intent.putExtra(Intent.EXTRA_USER_ID, userId);
             intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            synchronized (DevicePolicyManagerService.this) {
-                ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
-                if (profileOwner != null) {
-                    intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner);
-                    return intent;
-                }
 
-                if (mOwners.getDeviceOwnerUserId() == userId) {
-                    ComponentName deviceOwner = mOwners.getDeviceOwnerComponent();
-                    if (deviceOwner != null) {
-                        intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner);
-                        return intent;
-                    }
-                }
+            // This method is called from AM with its lock held, so don't take the DPMS lock.
+            // b/29242568
+
+            ComponentName profileOwner = mOwners.getProfileOwnerComponent(userId);
+            if (profileOwner != null) {
+                intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, profileOwner);
+                return intent;
             }
+
+            final Pair<Integer, ComponentName> deviceOwner =
+                    mOwners.getDeviceOwnerUserIdAndComponent();
+            if (deviceOwner != null && deviceOwner.first == userId) {
+                intent.putExtra(DevicePolicyManager.EXTRA_DEVICE_ADMIN, deviceOwner.second);
+                return intent;
+            }
+
             // We're not specifying the device admin because there isn't one.
             return intent;
         }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
index cb39ebd..1ae1a77 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/Owners.java
@@ -16,9 +16,9 @@
 
 package com.android.server.devicepolicy;
 
+import android.annotation.Nullable;
 import android.app.admin.SystemUpdatePolicy;
 import android.content.ComponentName;
-import android.content.Context;
 import android.content.pm.PackageManagerInternal;
 import android.content.pm.UserInfo;
 import android.os.Environment;
@@ -28,6 +28,7 @@
 import android.util.ArrayMap;
 import android.util.AtomicFile;
 import android.util.Log;
+import android.util.Pair;
 import android.util.Slog;
 import android.util.SparseArray;
 import android.util.Xml;
@@ -54,8 +55,8 @@
  * Stores and restores state for the Device and Profile owners. By definition there can be
  * only one device owner, but there may be a profile owner for each user.
  *
- * <p>This class is not thread safe.  (i.e. access to this class must always be synchronized
- * in the caller side.)
+ * <p>This class is thread safe, so individual methods can safely be called without locking.
+ * However, caller must still synchronize on their side to ensure integrity between multiple calls.
  */
 class Owners {
     private static final String TAG = "DevicePolicyManagerService";
@@ -101,6 +102,8 @@
     // Local system update policy controllable by device owner.
     private SystemUpdatePolicy mSystemUpdatePolicy;
 
+    private final Object mLock = new Object();
+
     public Owners(UserManager userManager,
             UserManagerInternal userManagerInternal,
             PackageManagerInternal packageManagerInternal) {
@@ -113,47 +116,49 @@
      * Load configuration from the disk.
      */
     void load() {
-        // First, try to read from the legacy file.
-        final File legacy = getLegacyConfigFileWithTestOverride();
+        synchronized (mLock) {
+            // First, try to read from the legacy file.
+            final File legacy = getLegacyConfigFileWithTestOverride();
 
-        final List<UserInfo> users = mUserManager.getUsers();
+            final List<UserInfo> users = mUserManager.getUsers();
 
-        if (readLegacyOwnerFile(legacy)) {
-            if (DEBUG) {
-                Log.d(TAG, "Legacy config file found.");
-            }
+            if (readLegacyOwnerFileLocked(legacy)) {
+                if (DEBUG) {
+                    Log.d(TAG, "Legacy config file found.");
+                }
 
-            // Legacy file exists, write to new files and remove the legacy one.
-            writeDeviceOwner();
-            for (int userId : getProfileOwnerKeys()) {
-                writeProfileOwner(userId);
-            }
-            if (DEBUG) {
-                Log.d(TAG, "Deleting legacy config file");
-            }
-            if (!legacy.delete()) {
-                Slog.e(TAG, "Failed to remove the legacy setting file");
-            }
-        } else {
-            // No legacy file, read from the new format files.
-            new DeviceOwnerReadWriter().readFromFileLocked();
+                // Legacy file exists, write to new files and remove the legacy one.
+                writeDeviceOwner();
+                for (int userId : getProfileOwnerKeys()) {
+                    writeProfileOwner(userId);
+                }
+                if (DEBUG) {
+                    Log.d(TAG, "Deleting legacy config file");
+                }
+                if (!legacy.delete()) {
+                    Slog.e(TAG, "Failed to remove the legacy setting file");
+                }
+            } else {
+                // No legacy file, read from the new format files.
+                new DeviceOwnerReadWriter().readFromFileLocked();
 
+                for (UserInfo ui : users) {
+                    new ProfileOwnerReadWriter(ui.id).readFromFileLocked();
+                }
+            }
+            mUserManagerInternal.setDeviceManaged(hasDeviceOwner());
             for (UserInfo ui : users) {
-                new ProfileOwnerReadWriter(ui.id).readFromFileLocked();
+                mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id));
             }
+            if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) {
+                Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
+                        getDeviceOwnerUserId()));
+            }
+            pushToPackageManagerLocked();
         }
-        mUserManagerInternal.setDeviceManaged(hasDeviceOwner());
-        for (UserInfo ui : users) {
-            mUserManagerInternal.setUserManaged(ui.id, hasProfileOwner(ui.id));
-        }
-        if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) {
-            Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
-                    getDeviceOwnerUserId()));
-        }
-        pushToPackageManager();
     }
 
-    private void pushToPackageManager() {
+    private void pushToPackageManagerLocked() {
         final SparseArray<String> po = new SparseArray<>();
         for (int i = mProfileOwners.size() - 1; i >= 0; i--) {
             po.put(mProfileOwners.keyAt(i), mProfileOwners.valueAt(i).packageName);
@@ -164,27 +169,50 @@
     }
 
     String getDeviceOwnerPackageName() {
-        return mDeviceOwner != null ? mDeviceOwner.packageName : null;
+        synchronized (mLock) {
+            return mDeviceOwner != null ? mDeviceOwner.packageName : null;
+        }
     }
 
     int getDeviceOwnerUserId() {
-        return mDeviceOwnerUserId;
+        synchronized (mLock) {
+            return mDeviceOwnerUserId;
+        }
+    }
+
+    @Nullable
+    Pair<Integer, ComponentName> getDeviceOwnerUserIdAndComponent() {
+        synchronized (mLock) {
+            if (mDeviceOwner == null) {
+                return null;
+            } else {
+                return Pair.create(mDeviceOwnerUserId, mDeviceOwner.admin);
+            }
+        }
     }
 
     String getDeviceOwnerName() {
-        return mDeviceOwner != null ? mDeviceOwner.name : null;
+        synchronized (mLock) {
+            return mDeviceOwner != null ? mDeviceOwner.name : null;
+        }
     }
 
     ComponentName getDeviceOwnerComponent() {
-        return mDeviceOwner != null ? mDeviceOwner.admin : null;
+        synchronized (mLock) {
+            return mDeviceOwner != null ? mDeviceOwner.admin : null;
+        }
     }
 
     String getDeviceOwnerRemoteBugreportUri() {
-        return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null;
+        synchronized (mLock) {
+            return mDeviceOwner != null ? mDeviceOwner.remoteBugreportUri : null;
+        }
     }
 
     String getDeviceOwnerRemoteBugreportHash() {
-        return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null;
+        synchronized (mLock) {
+            return mDeviceOwner != null ? mDeviceOwner.remoteBugreportHash : null;
+        }
     }
 
     void setDeviceOwner(ComponentName admin, String ownerName, int userId) {
@@ -192,132 +220,172 @@
             Slog.e(TAG, "Invalid user id for device owner user: " + userId);
             return;
         }
-        // For a newly set DO, there's no need for migration.
-        setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId,
-                /* userRestrictionsMigrated =*/ true);
+        synchronized (mLock) {
+            // For a newly set DO, there's no need for migration.
+            setDeviceOwnerWithRestrictionsMigrated(admin, ownerName, userId,
+                    /* userRestrictionsMigrated =*/ true);
+        }
     }
 
     // Note this should be only called during migration.  Normally when DO is set,
     // userRestrictionsMigrated should always be true.
     void setDeviceOwnerWithRestrictionsMigrated(ComponentName admin, String ownerName, int userId,
             boolean userRestrictionsMigrated) {
-        mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated,
-                /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null);
-        mDeviceOwnerUserId = userId;
+        synchronized (mLock) {
+            mDeviceOwner = new OwnerInfo(ownerName, admin, userRestrictionsMigrated,
+                    /* remoteBugreportUri =*/ null, /* remoteBugreportHash =*/ null);
+            mDeviceOwnerUserId = userId;
 
-        mUserManagerInternal.setDeviceManaged(true);
-        pushToPackageManager();
+            mUserManagerInternal.setDeviceManaged(true);
+            pushToPackageManagerLocked();
+        }
     }
 
     void clearDeviceOwner() {
-        mDeviceOwner = null;
-        mDeviceOwnerUserId = UserHandle.USER_NULL;
+        synchronized (mLock) {
+            mDeviceOwner = null;
+            mDeviceOwnerUserId = UserHandle.USER_NULL;
 
-        mUserManagerInternal.setDeviceManaged(false);
-        pushToPackageManager();
+            mUserManagerInternal.setDeviceManaged(false);
+            pushToPackageManagerLocked();
+        }
     }
 
     void setProfileOwner(ComponentName admin, String ownerName, int userId) {
-        // For a newly set PO, there's no need for migration.
-        mProfileOwners.put(userId, new OwnerInfo(ownerName, admin,
-                /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null,
-                /* remoteBugreportHash =*/ null));
-        mUserManagerInternal.setUserManaged(userId, true);
-        pushToPackageManager();
+        synchronized (mLock) {
+            // For a newly set PO, there's no need for migration.
+            mProfileOwners.put(userId, new OwnerInfo(ownerName, admin,
+                    /* userRestrictionsMigrated =*/ true, /* remoteBugreportUri =*/ null,
+                    /* remoteBugreportHash =*/ null));
+            mUserManagerInternal.setUserManaged(userId, true);
+            pushToPackageManagerLocked();
+        }
     }
 
     void removeProfileOwner(int userId) {
-        mProfileOwners.remove(userId);
-        mUserManagerInternal.setUserManaged(userId, false);
-        pushToPackageManager();
+        synchronized (mLock) {
+            mProfileOwners.remove(userId);
+            mUserManagerInternal.setUserManaged(userId, false);
+            pushToPackageManagerLocked();
+        }
     }
 
     ComponentName getProfileOwnerComponent(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null ? profileOwner.admin : null;
+        synchronized (mLock) {
+            OwnerInfo profileOwner = mProfileOwners.get(userId);
+            return profileOwner != null ? profileOwner.admin : null;
+        }
     }
 
     String getProfileOwnerName(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null ? profileOwner.name : null;
+        synchronized (mLock) {
+            OwnerInfo profileOwner = mProfileOwners.get(userId);
+            return profileOwner != null ? profileOwner.name : null;
+        }
     }
 
     String getProfileOwnerPackage(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null ? profileOwner.packageName : null;
+        synchronized (mLock) {
+            OwnerInfo profileOwner = mProfileOwners.get(userId);
+            return profileOwner != null ? profileOwner.packageName : null;
+        }
     }
 
     Set<Integer> getProfileOwnerKeys() {
-        return mProfileOwners.keySet();
+        synchronized (mLock) {
+            return mProfileOwners.keySet();
+        }
     }
 
     SystemUpdatePolicy getSystemUpdatePolicy() {
-        return mSystemUpdatePolicy;
+        synchronized (mLock) {
+            return mSystemUpdatePolicy;
+        }
     }
 
     void setSystemUpdatePolicy(SystemUpdatePolicy systemUpdatePolicy) {
-        mSystemUpdatePolicy = systemUpdatePolicy;
+        synchronized (mLock) {
+            mSystemUpdatePolicy = systemUpdatePolicy;
+        }
     }
 
     void clearSystemUpdatePolicy() {
-        mSystemUpdatePolicy = null;
+        synchronized (mLock) {
+            mSystemUpdatePolicy = null;
+        }
     }
 
     boolean hasDeviceOwner() {
-        return mDeviceOwner != null;
+        synchronized (mLock) {
+            return mDeviceOwner != null;
+        }
     }
 
     boolean isDeviceOwnerUserId(int userId) {
-        return mDeviceOwner != null && mDeviceOwnerUserId == userId;
+        synchronized (mLock) {
+            return mDeviceOwner != null && mDeviceOwnerUserId == userId;
+        }
     }
 
     boolean hasProfileOwner(int userId) {
-        return getProfileOwnerComponent(userId) != null;
+        synchronized (mLock) {
+            return getProfileOwnerComponent(userId) != null;
+        }
     }
 
     /**
      * @return true if user restrictions need to be migrated for DO.
      */
     boolean getDeviceOwnerUserRestrictionsNeedsMigration() {
-        return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated;
+        synchronized (mLock) {
+            return mDeviceOwner != null && !mDeviceOwner.userRestrictionsMigrated;
+        }
     }
 
     /**
      * @return true if user restrictions need to be migrated for PO.
      */
     boolean getProfileOwnerUserRestrictionsNeedsMigration(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        return profileOwner != null && !profileOwner.userRestrictionsMigrated;
+        synchronized (mLock) {
+            OwnerInfo profileOwner = mProfileOwners.get(userId);
+            return profileOwner != null && !profileOwner.userRestrictionsMigrated;
+        }
     }
 
     /** Sets the user restrictions migrated flag, and also writes to the file. */
     void setDeviceOwnerUserRestrictionsMigrated() {
-        if (mDeviceOwner != null) {
-            mDeviceOwner.userRestrictionsMigrated = true;
+        synchronized (mLock) {
+            if (mDeviceOwner != null) {
+                mDeviceOwner.userRestrictionsMigrated = true;
+            }
+            writeDeviceOwner();
         }
-        writeDeviceOwner();
     }
 
     /** Sets the remote bugreport uri and hash, and also writes to the file. */
     void setDeviceOwnerRemoteBugreportUriAndHash(String remoteBugreportUri,
             String remoteBugreportHash) {
-        if (mDeviceOwner != null) {
-            mDeviceOwner.remoteBugreportUri = remoteBugreportUri;
-            mDeviceOwner.remoteBugreportHash = remoteBugreportHash;
+        synchronized (mLock) {
+            if (mDeviceOwner != null) {
+                mDeviceOwner.remoteBugreportUri = remoteBugreportUri;
+                mDeviceOwner.remoteBugreportHash = remoteBugreportHash;
+            }
+            writeDeviceOwner();
         }
-        writeDeviceOwner();
     }
 
     /** Sets the user restrictions migrated flag, and also writes to the file.  */
     void setProfileOwnerUserRestrictionsMigrated(int userId) {
-        OwnerInfo profileOwner = mProfileOwners.get(userId);
-        if (profileOwner != null) {
-            profileOwner.userRestrictionsMigrated = true;
+        synchronized (mLock) {
+            OwnerInfo profileOwner = mProfileOwners.get(userId);
+            if (profileOwner != null) {
+                profileOwner.userRestrictionsMigrated = true;
+            }
+            writeProfileOwner(userId);
         }
-        writeProfileOwner(userId);
     }
 
-    private boolean readLegacyOwnerFile(File file) {
+    private boolean readLegacyOwnerFileLocked(File file) {
         if (!file.exists()) {
             // Already migrated or the device has no owners.
             return false;
@@ -383,7 +451,7 @@
     }
 
     void writeDeviceOwner() {
-        synchronized (this) {
+        synchronized (mLock) {
             if (DEBUG) {
                 Log.d(TAG, "Writing to device owner file");
             }
@@ -392,7 +460,7 @@
     }
 
     void writeProfileOwner(int userId) {
-        synchronized (this) {
+        synchronized (mLock) {
             if (DEBUG) {
                 Log.d(TAG, "Writing to profile owner file for user " + userId);
             }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 5c2e0ba..ff7ca62 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -700,6 +700,24 @@
     public static final String KEY_DURATION_BLOCKING_DISABLED_AFTER_EMERGENCY_INT =
             "duration_blocking_disabled_after_emergency_int";
 
+    /**
+     * @hide
+     * The default value for preferred CDMA roaming mode (aka CDMA system select.)
+     *          CDMA_ROAMING_MODE_RADIO_DEFAULT = the default roaming mode from the radio
+     *          CDMA_ROAMING_MODE_HOME = Home Networks
+     *          CDMA_ROAMING_MODE_AFFILIATED = Roaming on Affiliated networks
+     *          CDMA_ROAMING_MODE_ANY = Roaming on any networks
+     */
+    public static final String KEY_CDMA_ROAMING_MODE_INT = "cdma_roaming_mode_int";
+    /** @hide */
+    public static final int CDMA_ROAMING_MODE_RADIO_DEFAULT = -1;
+    /** @hide */
+    public static final int CDMA_ROAMING_MODE_HOME = 0;
+    /** @hide */
+    public static final int CDMA_ROAMING_MODE_AFFILIATED = 1;
+    /** @hide */
+    public static final int CDMA_ROAMING_MODE_ANY = 2;
+
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
 
@@ -836,6 +854,7 @@
         sDefaults.putString(KEY_MMS_USER_AGENT_STRING, "");
         sDefaults.putBoolean(KEY_ALLOW_NON_EMERGENCY_CALLS_IN_ECM_BOOL, true);
         sDefaults.putBoolean(KEY_USE_RCS_PRESENCE_BOOL, false);
+        sDefaults.putInt(KEY_CDMA_ROAMING_MODE_INT, CDMA_ROAMING_MODE_RADIO_DEFAULT);
 
         // Used for Sim card State detection app
         sDefaults.putStringArray(KEY_SIM_PROVISIONING_STATUS_DETECTION_CARRIER_APP_STRING_ARRAY,