Merge "Improve action bar transition" into nyc-dev
diff --git a/core/java/android/animation/ValueAnimator.java b/core/java/android/animation/ValueAnimator.java
index 4edf249..0c7ee2c 100644
--- a/core/java/android/animation/ValueAnimator.java
+++ b/core/java/android/animation/ValueAnimator.java
@@ -602,7 +602,9 @@
         long currentTime = AnimationUtils.currentAnimationTimeMillis();
         mStartTime = currentTime - seekTime;
         mStartTimeCommitted = true; // do not allow start time to be compensated for jank
-        if (!mRunning) {
+        if (!isPulsingInternal()) {
+            // If the animation loop hasn't started, the startTime will be adjusted in the first
+            // frame based on seek fraction.
             mSeekFraction = fraction;
         }
         mOverallFraction = fraction;
@@ -980,6 +982,10 @@
         mStarted = true;
         mPaused = false;
         mRunning = false;
+        // Resets mLastFrameTime when start() is called, so that if the animation was running,
+        // calling start() would put the animation in the
+        // started-but-not-yet-reached-the-first-frame phase.
+        mLastFrameTime = 0;
         AnimationHandler animationHandler = AnimationHandler.getInstance();
         animationHandler.addAnimationFrameCallback(this, (long) (mStartDelay * sDurationScale));
 
@@ -1095,7 +1101,7 @@
      */
     @Override
     public void reverse() {
-        if (mRunning) {
+        if (isPulsingInternal()) {
             long currentTime = AnimationUtils.currentAnimationTimeMillis();
             long currentPlayTime = currentTime - mStartTime;
             long timeLeft = getScaledDuration() - currentPlayTime;
@@ -1103,6 +1109,7 @@
             mStartTimeCommitted = true; // do not allow start time to be compensated for jank
             mReversing = !mReversing;
         } else if (mStarted) {
+            mReversing = !mReversing;
             end();
         } else {
             start(true);
@@ -1177,6 +1184,15 @@
     }
 
     /**
+     * Internal only: This tracks whether the animation has gotten on the animation loop. Note
+     * this is different than {@link #isRunning()} in that the latter tracks the time after start()
+     * is called (or after start delay if any), which may be before the animation loop starts.
+     */
+    private boolean isPulsingInternal() {
+        return mLastFrameTime > 0;
+    }
+
+    /**
      * Returns the name of this animator for debugging purposes.
      */
     String getNameForTrace() {
diff --git a/core/java/android/app/Activity.java b/core/java/android/app/Activity.java
index a5fcec6..13cf46d 100644
--- a/core/java/android/app/Activity.java
+++ b/core/java/android/app/Activity.java
@@ -57,6 +57,7 @@
 import android.media.AudioManager;
 import android.media.session.MediaController;
 import android.net.Uri;
+import android.os.BadParcelableException;
 import android.os.Build;
 import android.os.Bundle;
 import android.os.Handler;
@@ -5006,13 +5007,18 @@
     @Nullable
     public Uri getReferrer() {
         Intent intent = getIntent();
-        Uri referrer = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
-        if (referrer != null) {
-            return referrer;
-        }
-        String referrerName = intent.getStringExtra(Intent.EXTRA_REFERRER_NAME);
-        if (referrerName != null) {
-            return Uri.parse(referrerName);
+        try {
+            Uri referrer = intent.getParcelableExtra(Intent.EXTRA_REFERRER);
+            if (referrer != null) {
+                return referrer;
+            }
+            String referrerName = intent.getStringExtra(Intent.EXTRA_REFERRER_NAME);
+            if (referrerName != null) {
+                return Uri.parse(referrerName);
+            }
+        } catch (BadParcelableException e) {
+            Log.w(TAG, "Cannot read referrer from intent;"
+                    + " intent extras contain unknown custom Parcelable objects");
         }
         if (mReferrer != null) {
             return new Uri.Builder().scheme("android-app").authority(mReferrer).build();
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 2c2f6c1..0728bdf 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -16,6 +16,8 @@
 
 package android.app;
 
+import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.assist.AssistContent;
 import android.app.assist.AssistStructure;
 import android.app.backup.BackupAgent;
@@ -4578,20 +4580,37 @@
     }
 
     /**
+     * Creates a new Configuration only if override would modify base. Otherwise returns base.
+     * @param base The base configuration.
+     * @param override The update to apply to the base configuration. Can be null.
+     * @return A Configuration representing base with override applied.
+     */
+    private static Configuration createNewConfigAndUpdateIfNotNull(@NonNull Configuration base,
+            @Nullable Configuration override) {
+        if (override == null) {
+            return base;
+        }
+        Configuration newConfig = new Configuration(base);
+        newConfig.updateFrom(override);
+        return newConfig;
+    }
+
+    /**
      * Decides whether to update an Activity's configuration and whether to tell the
      * Activity/Component about it.
      * @param cb The component callback to notify of configuration change.
      * @param activityToken The Activity binder token for which this configuration change happened.
      *                      If the change is global, this is null.
      * @param newConfig The new configuration.
-     * @param overrideConfig The override config that differentiates the Activity's configuration
+     * @param amOverrideConfig The override config that differentiates the Activity's configuration
      *                       from the base global configuration.
+     *                       This is supplied by ActivityManager.
      * @param reportToActivity Notify the Activity of the change.
      */
     private void performConfigurationChanged(ComponentCallbacks2 cb,
                                              IBinder activityToken,
                                              Configuration newConfig,
-                                             Configuration overrideConfig,
+                                             Configuration amOverrideConfig,
                                              boolean reportToActivity) {
         // Only for Activity objects, check that they actually call up to their
         // superclass implementation.  ComponentCallbacks2 is an interface, so
@@ -4605,7 +4624,6 @@
         if ((activity == null) || (activity.mCurrentConfig == null)) {
             shouldChangeConfig = true;
         } else {
-
             // If the new config is the same as the config this Activity
             // is already running with then don't bother calling
             // onConfigurationChanged
@@ -4615,34 +4633,36 @@
             }
         }
 
-        if (DEBUG_CONFIGURATION) {
-            Slog.v(TAG, "Config callback " + cb + ": shouldChangeConfig=" + shouldChangeConfig);
-        }
-
         if (shouldChangeConfig) {
+            // Propagate the configuration change to the Activity and ResourcesManager.
+
+            // ContextThemeWrappers may override the configuration for that context.
+            // We must check and apply any overrides defined.
+            Configuration contextThemeWrapperOverrideConfig = null;
+            if (cb instanceof ContextThemeWrapper) {
+                final ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
+                contextThemeWrapperOverrideConfig = contextThemeWrapper.getOverrideConfiguration();
+            }
+
+            // We only update an Activity's configuration if this is not a global
+            // configuration change. This must also be done before the callback,
+            // or else we violate the contract that the new resources are available
+            // in {@link ComponentCallbacks2#onConfigurationChanged(Configuration)}.
             if (activityToken != null) {
-                // We only update an Activity's configuration if this is not a global
-                // configuration change. This must also be done before the callback,
-                // or else we violate the contract that the new resources are available
-                // in {@link ComponentCallbacks2#onConfigurationChanged(Configuration)}.
-                mResourcesManager.updateResourcesForActivity(activityToken, overrideConfig);
+                // Apply the ContextThemeWrapper override if necessary.
+                // NOTE: Make sure the configurations are not modified, as they are treated
+                // as immutable in many places.
+                final Configuration finalOverrideConfig = createNewConfigAndUpdateIfNotNull(
+                        amOverrideConfig, contextThemeWrapperOverrideConfig);
+                mResourcesManager.updateResourcesForActivity(activityToken, finalOverrideConfig);
             }
 
             if (reportToActivity) {
-                Configuration configToReport = newConfig;
-
-                if (cb instanceof ContextThemeWrapper) {
-                    // ContextThemeWrappers may override the configuration for that context.
-                    // We must check and apply any overrides defined.
-                    ContextThemeWrapper contextThemeWrapper = (ContextThemeWrapper) cb;
-                    final Configuration localOverrideConfig =
-                            contextThemeWrapper.getOverrideConfiguration();
-                    if (localOverrideConfig != null) {
-                        configToReport = new Configuration(newConfig);
-                        configToReport.updateFrom(localOverrideConfig);
-                    }
-                }
-
+                // Apply the ContextThemeWrapper override if necessary.
+                // NOTE: Make sure the configurations are not modified, as they are treated
+                // as immutable in many places.
+                final Configuration configToReport = createNewConfigAndUpdateIfNotNull(
+                        newConfig, contextThemeWrapperOverrideConfig);
                 cb.onConfigurationChanged(configToReport);
             }
 
diff --git a/core/java/android/app/AppOpsManager.java b/core/java/android/app/AppOpsManager.java
index e526c17..1e4ffbe 100644
--- a/core/java/android/app/AppOpsManager.java
+++ b/core/java/android/app/AppOpsManager.java
@@ -1340,9 +1340,14 @@
     /** @hide */
     public void setUserRestriction(int code, boolean restricted, IBinder token,
             String[] exceptionPackages) {
+        setUserRestrictionForUser(code, restricted, token, exceptionPackages, mContext.getUserId());
+    }
+
+    /** @hide */
+    public void setUserRestrictionForUser(int code, boolean restricted, IBinder token,
+            String[] exceptionPackages, int userId) {
         try {
-            mService.setUserRestriction(code, restricted, token, mContext.getUserId(),
-                  exceptionPackages);
+            mService.setUserRestriction(code, restricted, token, userId, exceptionPackages);
         } catch (RemoteException e) {
             throw e.rethrowFromSystemServer();
         }
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index 152f45e..0b62ed2 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -1191,14 +1191,18 @@
 
         public void performReceive(Intent intent, int resultCode, String data,
                 Bundle extras, boolean ordered, boolean sticky, int sendingUser) {
-            if (ActivityThread.DEBUG_BROADCAST) {
-                int seq = intent.getIntExtra("seq", -1);
-                Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction() + " seq=" + seq
-                        + " to " + mReceiver);
-            }
-            Args args = new Args(intent, resultCode, data, extras, ordered,
+            final Args args = new Args(intent, resultCode, data, extras, ordered,
                     sticky, sendingUser);
-            if (!mActivityThread.post(args)) {
+            if (intent == null) {
+                Log.wtf(TAG, "Null intent received");
+            } else {
+                if (ActivityThread.DEBUG_BROADCAST) {
+                    int seq = intent.getIntExtra("seq", -1);
+                    Slog.i(ActivityThread.TAG, "Enqueueing broadcast " + intent.getAction()
+                            + " seq=" + seq + " to " + mReceiver);
+                }
+            }
+            if (intent == null || !mActivityThread.post(args)) {
                 if (mRegistered && ordered) {
                     IActivityManager mgr = ActivityManagerNative.getDefault();
                     if (ActivityThread.DEBUG_BROADCAST) Slog.i(ActivityThread.TAG,
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 83a2066..f896fb5 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -1986,6 +1986,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 +2273,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 +3183,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) {
@@ -3266,11 +3278,10 @@
                 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);
             }
         }
 
@@ -3394,6 +3405,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 +3429,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);
@@ -4570,12 +4585,21 @@
                     : mConversationTitle;
             boolean hasTitle = !TextUtils.isEmpty(title);
 
-            if (!hasTitle && mMessages.size() == 1) {
-                CharSequence sender = mMessages.get(0).mSender;
-                CharSequence text = mMessages.get(0).mText;
+            if (mMessages.size() == 1) {
+                // Special case for a single message: Use the big text style
+                // so the collapsed and expanded versions match nicely.
+                CharSequence bigTitle;
+                CharSequence text;
+                if (hasTitle) {
+                    bigTitle = title;
+                    text = makeMessageLine(mMessages.get(0));
+                } else {
+                    bigTitle = mMessages.get(0).mSender;
+                    text = mMessages.get(0).mText;
+                }
                 RemoteViews contentView = mBuilder.applyStandardTemplateWithActions(
                         mBuilder.getBigTextLayoutResource(),
-                        false /* progress */, sender, null /* text */);
+                        false /* progress */, bigTitle, null /* text */);
                 BigTextStyle.applyBigTextContentView(mBuilder, contentView, text);
                 return contentView;
             }
@@ -4595,12 +4619,13 @@
             }
 
             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));
 
+            int contractedChildId = View.NO_ID;
+            Message contractedMessage = findLatestIncomingMessage();
             int firstMessage = Math.max(0, mMessages.size() - rowIds.length);
             while (firstMessage + i < mMessages.size() && i < rowIds.length) {
                 Message m = mMessages.get(firstMessage + i);
@@ -4609,8 +4634,15 @@
                 contentView.setViewVisibility(rowId, View.VISIBLE);
                 contentView.setTextViewText(rowId, makeMessageLine(m));
 
+                if (contractedMessage == m) {
+                    contractedChildId = rowId;
+                }
+
                 i++;
             }
+            // Record this here to allow transformation between the contracted and expanded views.
+            contentView.setInt(R.id.notification_messaging, "setContractedChildId",
+                    contractedChildId);
             return contentView;
         }
 
@@ -4964,11 +4996,10 @@
                 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);
+                    endMargin = R.dimen.notification_content_picture_margin;
                 }
             }
-            contentView.setViewLayoutMarginEnd(id, endMargin);
+            contentView.setViewLayoutMarginEndDimen(id, endMargin);
         }
     }
 
@@ -5153,13 +5184,11 @@
             }
             handleImage(view);
             // handle the content margin
-            int endMargin = mBuilder.mContext.getResources().getDimensionPixelSize(
-                    R.dimen.notification_content_margin_end);;
+            int endMargin = R.dimen.notification_content_margin_end;
             if (mBuilder.mN.mLargeIcon != null) {
-                endMargin += mBuilder.mContext.getResources().getDimensionPixelSize(
-                        R.dimen.notification_content_picture_margin);
+                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;
         }
 
@@ -5190,8 +5219,8 @@
 
         private void handleImage(RemoteViews contentView) {
             if (mBuilder.mN.mLargeIcon != null) {
-                contentView.setViewLayoutMarginEnd(R.id.line1, 0);
-                contentView.setViewLayoutMarginEnd(R.id.text, 0);
+                contentView.setViewLayoutMarginEndDimen(R.id.line1, 0);
+                contentView.setViewLayoutMarginEndDimen(R.id.text, 0);
             }
         }
 
@@ -5306,13 +5335,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);
+            int endMargin = R.dimen.notification_content_margin_end;
             if (mBuilder.mN.mLargeIcon != null) {
-                endMargin += mBuilder.mContext.getResources().getDimensionPixelSize(
-                        R.dimen.notification_content_picture_margin);
+                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/WallpaperManager.java b/core/java/android/app/WallpaperManager.java
index 18f93cd..7f467f0 100644
--- a/core/java/android/app/WallpaperManager.java
+++ b/core/java/android/app/WallpaperManager.java
@@ -1576,8 +1576,11 @@
         final String whichProp;
         final int defaultResId;
         if (which == FLAG_LOCK) {
+            /* Factory-default lock wallpapers are not yet supported
             whichProp = PROP_LOCK_WALLPAPER;
             defaultResId = com.android.internal.R.drawable.default_lock_wallpaper;
+            */
+            return null;
         } else {
             whichProp = PROP_WALLPAPER;
             defaultResId = com.android.internal.R.drawable.default_wallpaper;
diff --git a/core/java/android/app/admin/DevicePolicyManagerInternal.java b/core/java/android/app/admin/DevicePolicyManagerInternal.java
index 54a2f7a..9a0cd56 100644
--- a/core/java/android/app/admin/DevicePolicyManagerInternal.java
+++ b/core/java/android/app/admin/DevicePolicyManagerInternal.java
@@ -17,7 +17,6 @@
 package android.app.admin;
 
 import android.content.Intent;
-import android.os.UserHandle;
 
 import java.util.List;
 
@@ -48,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
@@ -59,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(
@@ -67,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.
@@ -74,21 +80,12 @@
     public abstract boolean isActiveAdminWithPolicy(int uid, int reqPolicy);
 
     /**
-     * Checks if a given package has a device or a profile owner for the given user.
-     * <p>
-     * <em>Note: does <b>not</b> support negative userIds like {@link UserHandle#USER_ALL}</em>
-     *
-     * @param packageName The package to check
-     * @param userId the userId to check for.
-     * @return true if package has a device or profile owner, false otherwise.
-     */
-    public abstract boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId);
-
-    /**
      * Creates an intent to show the admin support dialog to let the user know that the package is
      * 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/content/pm/PackageManagerInternal.java b/core/java/android/content/pm/PackageManagerInternal.java
index 13ebb82..14f7727 100644
--- a/core/java/android/content/pm/PackageManagerInternal.java
+++ b/core/java/android/content/pm/PackageManagerInternal.java
@@ -18,6 +18,7 @@
 
 import android.content.ComponentName;
 import android.content.pm.PackageManager.NameNotFoundException;
+import android.util.SparseArray;
 
 import java.util.List;
 
@@ -147,4 +148,16 @@
      */
     public abstract ComponentName getHomeActivitiesAsUser(List<ResolveInfo> allHomeCandidates,
             int userId);
+
+    /**
+     * Called by DeviceOwnerManagerService to set the package names of device owner and profile
+     * owners.
+     */
+    public abstract void setDeviceAndProfileOwnerPackages(
+            int deviceOwnerUserId, String deviceOwner, SparseArray<String> profileOwners);
+
+    /**
+     * Whether a package's data be cleared.
+     */
+    public abstract boolean canPackageBeWiped(int userId, String packageName);
 }
diff --git a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
index 5743b4d..0cee114 100644
--- a/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
+++ b/core/java/android/hardware/camera2/impl/CameraDeviceImpl.java
@@ -1610,41 +1610,6 @@
     }
 
     public class CameraDeviceCallbacks extends ICameraDeviceCallbacks.Stub {
-        //
-        // Constants below need to be kept up-to-date with
-        // frameworks/av/include/camera/camera2/ICameraDeviceCallbacks.h
-        //
-
-        //
-        // Error codes for onCameraError
-        //
-
-        /**
-         * Camera has been disconnected
-         */
-        public static final int ERROR_CAMERA_DISCONNECTED = 0;
-        /**
-         * Camera has encountered a device-level error
-         * Matches CameraDevice.StateCallback#ERROR_CAMERA_DEVICE
-         */
-        public static final int ERROR_CAMERA_DEVICE = 1;
-        /**
-         * Camera has encountered a service-level error
-         * Matches CameraDevice.StateCallback#ERROR_CAMERA_SERVICE
-         */
-        public static final int ERROR_CAMERA_SERVICE = 2;
-        /**
-         * Camera has encountered an error processing a single request.
-         */
-        public static final int ERROR_CAMERA_REQUEST = 3;
-        /**
-         * Camera has encountered an error producing metadata for a single capture
-         */
-        public static final int ERROR_CAMERA_RESULT = 4;
-        /**
-         * Camera has encountered an error producing an image buffer for a single capture
-         */
-        public static final int ERROR_CAMERA_BUFFER = 5;
 
         @Override
         public IBinder asBinder() {
@@ -1675,11 +1640,14 @@
                     case ERROR_CAMERA_DEVICE:
                     case ERROR_CAMERA_SERVICE:
                         mInError = true;
+                        final int publicErrorCode = (errorCode == ERROR_CAMERA_DEVICE) ?
+                                StateCallback.ERROR_CAMERA_DEVICE :
+                                StateCallback.ERROR_CAMERA_SERVICE;
                         Runnable r = new Runnable() {
                             @Override
                             public void run() {
                                 if (!CameraDeviceImpl.this.isClosed()) {
-                                    mDeviceCallback.onError(CameraDeviceImpl.this, errorCode);
+                                    mDeviceCallback.onError(CameraDeviceImpl.this, publicErrorCode);
                                 }
                             }
                         };
@@ -2050,7 +2018,7 @@
             public void run() {
                 if (!isClosed()) {
                     mDeviceCallback.onError(CameraDeviceImpl.this,
-                            CameraDeviceCallbacks.ERROR_CAMERA_SERVICE);
+                            StateCallback.ERROR_CAMERA_SERVICE);
                 }
             }
         };
diff --git a/core/java/android/hardware/camera2/marshal/MarshalRegistry.java b/core/java/android/hardware/camera2/marshal/MarshalRegistry.java
index ba821e4..1565087 100644
--- a/core/java/android/hardware/camera2/marshal/MarshalRegistry.java
+++ b/core/java/android/hardware/camera2/marshal/MarshalRegistry.java
@@ -37,7 +37,9 @@
      * @param queryable a non-{@code null} marshal queryable that supports marshaling {@code T}
      */
     public static <T> void registerMarshalQueryable(MarshalQueryable<T> queryable) {
-        sRegisteredMarshalQueryables.add(queryable);
+        synchronized(sMarshalLock) {
+            sRegisteredMarshalQueryables.add(queryable);
+        }
     }
 
     /**
@@ -54,47 +56,50 @@
      */
     @SuppressWarnings("unchecked")
     public static <T> Marshaler<T> getMarshaler(TypeReference<T> typeToken, int nativeType) {
-        // TODO: can avoid making a new token each time by code-genning
-        // the list of type tokens and native types from the keys (at the call sites)
-        MarshalToken<T> marshalToken = new MarshalToken<T>(typeToken, nativeType);
+        synchronized(sMarshalLock) {
+            // TODO: can avoid making a new token each time by code-genning
+            // the list of type tokens and native types from the keys (at the call sites)
+            MarshalToken<T> marshalToken = new MarshalToken<T>(typeToken, nativeType);
 
-        /*
-         * Marshalers are instantiated lazily once they are looked up; successive lookups
-         * will not instantiate new marshalers.
-         */
-        Marshaler<T> marshaler =
-                (Marshaler<T>) sMarshalerMap.get(marshalToken);
-
-        if (sRegisteredMarshalQueryables.size() == 0) {
-            throw new AssertionError("No available query marshalers registered");
-        }
-
-        if (marshaler == null) {
-            // Query each marshaler to see if they support the native/managed type combination
-            for (MarshalQueryable<?> potentialMarshaler : sRegisteredMarshalQueryables) {
-
-                MarshalQueryable<T> castedPotential =
-                        (MarshalQueryable<T>)potentialMarshaler;
-
-                if (castedPotential.isTypeMappingSupported(typeToken, nativeType)) {
-                    marshaler = castedPotential.createMarshaler(typeToken, nativeType);
-                    break;
-                }
-            }
+            /*
+             * Marshalers are instantiated lazily once they are looked up; successive lookups
+             * will not instantiate new marshalers.
+             */
+            Marshaler<T> marshaler =
+                    (Marshaler<T>) sMarshalerMap.get(marshalToken);
 
             if (marshaler == null) {
-                throw new UnsupportedOperationException(
+
+                if (sRegisteredMarshalQueryables.size() == 0) {
+                    throw new AssertionError("No available query marshalers registered");
+                }
+
+                // Query each marshaler to see if they support the native/managed type combination
+                for (MarshalQueryable<?> potentialMarshaler : sRegisteredMarshalQueryables) {
+
+                    MarshalQueryable<T> castedPotential =
+                            (MarshalQueryable<T>)potentialMarshaler;
+
+                    if (castedPotential.isTypeMappingSupported(typeToken, nativeType)) {
+                        marshaler = castedPotential.createMarshaler(typeToken, nativeType);
+                        break;
+                    }
+                }
+
+                if (marshaler == null) {
+                    throw new UnsupportedOperationException(
                         "Could not find marshaler that matches the requested " +
-                                "combination of type reference " +
-                                typeToken + " and native type " +
-                                MarshalHelpers.toStringNativeType(nativeType));
+                        "combination of type reference " +
+                        typeToken + " and native type " +
+                        MarshalHelpers.toStringNativeType(nativeType));
+                }
+
+                // Only put when no cached version exists to avoid +0.5ms lookup per call.
+                sMarshalerMap.put(marshalToken, marshaler);
             }
 
-            // Only put when no cached version exists to avoid +0.5ms lookup per call.
-            sMarshalerMap.put(marshalToken, marshaler);
+            return marshaler;
         }
-
-        return marshaler;
     }
 
     private static class MarshalToken<T> {
@@ -125,9 +130,12 @@
         }
     }
 
-    private static List<MarshalQueryable<?>> sRegisteredMarshalQueryables =
+    // Control access to the static data structures below
+    private static final Object sMarshalLock = new Object();
+
+    private static final List<MarshalQueryable<?>> sRegisteredMarshalQueryables =
             new ArrayList<MarshalQueryable<?>>();
-    private static HashMap<MarshalToken<?>, Marshaler<?>> sMarshalerMap =
+    private static final HashMap<MarshalToken<?>, Marshaler<?>> sMarshalerMap =
             new HashMap<MarshalToken<?>, Marshaler<?>>();
 
     private MarshalRegistry() {
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index ea5ae32..f4bf3ea 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -176,7 +176,7 @@
     /**
      * Current version of checkin data format.
      */
-    static final String CHECKIN_VERSION = "17";
+    static final String CHECKIN_VERSION = "18";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -2371,6 +2371,20 @@
     };
 
     /**
+     * Return the counter keeping track of the amount of battery discharge while the screen was off,
+     * measured in micro-Ampere-hours. This will be non-zero only if the device's battery has
+     * a coulomb counter.
+     */
+    public abstract LongCounter getDischargeScreenOffCoulombCounter();
+
+    /**
+     * Return the counter keeping track of the amount of battery discharge measured in
+     * micro-Ampere-hours. This will be non-zero only if the device's battery has
+     * a coulomb counter.
+     */
+    public abstract LongCounter getDischargeCoulombCounter();
+
+    /**
      * Return the array of discharge step durations.
      */
     public abstract LevelStepTracker getDischargeLevelStepTracker();
@@ -2805,6 +2819,9 @@
                 rawRealtime, which);
         final int connChanges = getNumConnectivityChange(which);
         final long phoneOnTime = getPhoneOnTime(rawRealtime, which);
+        final long dischargeCount = getDischargeCoulombCounter().getCountLocked(which);
+        final long dischargeScreenOffCount = getDischargeScreenOffCoulombCounter()
+                .getCountLocked(which);
 
         final StringBuilder sb = new StringBuilder(128);
         
@@ -2820,6 +2837,7 @@
                 totalRealtime / 1000, totalUptime / 1000,
                 getStartClockTime(),
                 whichBatteryScreenOffRealtime / 1000, whichBatteryScreenOffUptime / 1000);
+
         
         // Calculate wakelock times across all uids.
         long fullWakeLockTimeTotal = 0;
@@ -2969,12 +2987,14 @@
             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
                     getDischargeStartLevel()-getDischargeCurrentLevel(),
                     getDischargeStartLevel()-getDischargeCurrentLevel(),
-                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff());
+                    getDischargeAmountScreenOn(), getDischargeAmountScreenOff(),
+                    dischargeCount / 1000, dischargeScreenOffCount / 1000);
         } else {
             dumpLine(pw, 0 /* uid */, category, BATTERY_DISCHARGE_DATA,
                     getLowDischargeAmountSinceCharge(), getHighDischargeAmountSinceCharge(),
                     getDischargeAmountScreenOnSinceCharge(),
-                    getDischargeAmountScreenOffSinceCharge());
+                    getDischargeAmountScreenOffSinceCharge(),
+                    dischargeCount / 1000, dischargeScreenOffCount / 1000);
         }
         
         if (reqUid < 0) {
@@ -3371,6 +3391,39 @@
                     formatTimeMs(sb, chargeTimeRemaining / 1000);
             pw.println(sb.toString());
         }
+
+        final LongCounter dischargeCounter = getDischargeCoulombCounter();
+        final long dischargeCount = dischargeCounter.getCountLocked(which);
+        if (dischargeCount >= 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                sb.append("  Discharge: ");
+                sb.append(BatteryStatsHelper.makemAh(dischargeCount / 1000.0));
+                sb.append(" mAh");
+            pw.println(sb.toString());
+        }
+
+        final LongCounter dischargeScreenOffCounter = getDischargeScreenOffCoulombCounter();
+        final long dischargeScreenOffCount = dischargeScreenOffCounter.getCountLocked(which);
+        if (dischargeScreenOffCount >= 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                sb.append("  Screen off discharge: ");
+                sb.append(BatteryStatsHelper.makemAh(dischargeScreenOffCount / 1000.0));
+                sb.append(" mAh");
+            pw.println(sb.toString());
+        }
+
+        final long dischargeScreenOnCount = dischargeCount - dischargeScreenOffCount;
+        if (dischargeScreenOnCount >= 0) {
+            sb.setLength(0);
+            sb.append(prefix);
+                sb.append("  Screen on discharge: ");
+                sb.append(BatteryStatsHelper.makemAh(dischargeScreenOnCount / 1000.0));
+                sb.append(" mAh");
+            pw.println(sb.toString());
+        }
+
         pw.print("  Start clock time: ");
         pw.println(DateFormat.format("yyyy-MM-dd-HH-mm-ss", getStartClockTime()).toString());
 
diff --git a/core/java/android/os/ParcelFileDescriptor.java b/core/java/android/os/ParcelFileDescriptor.java
index d5491d3..7702c17 100644
--- a/core/java/android/os/ParcelFileDescriptor.java
+++ b/core/java/android/os/ParcelFileDescriptor.java
@@ -864,6 +864,34 @@
                 super.close();
             }
         }
+
+        @Override
+        public int read() throws IOException {
+            final int result = super.read();
+            if (result == -1 && mPfd.canDetectErrors()) {
+                // Check for errors only on EOF, to minimize overhead.
+                mPfd.checkError();
+            }
+            return result;
+        }
+
+        @Override
+        public int read(byte[] b) throws IOException {
+            final int result = super.read(b);
+            if (result == -1 && mPfd.canDetectErrors()) {
+                mPfd.checkError();
+            }
+            return result;
+        }
+
+        @Override
+        public int read(byte[] b, int off, int len) throws IOException {
+            final int result = super.read(b, off, len);
+            if (result == -1 && mPfd.canDetectErrors()) {
+                mPfd.checkError();
+            }
+            return result;
+        }
     }
 
     /**
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 6c21398..7ff01da 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -695,6 +695,7 @@
             String line = null;
             int bytesWrittenInMiB = -1, bytesStashedInMiB = -1;
             int timeTotal = -1;
+            int sourceVersion = -1;
             while ((line = in.readLine()) != null) {
                 // Here is an example of lines in last_install:
                 // ...
@@ -729,6 +730,8 @@
 
                 if (line.startsWith("time")) {
                     timeTotal = scaled;
+                } else if (line.startsWith("source_version")) {
+                    sourceVersion = scaled;
                 } else if (line.startsWith("bytes_written")) {
                     bytesWrittenInMiB = (bytesWrittenInMiB == -1) ? scaled :
                             bytesWrittenInMiB + scaled;
@@ -742,6 +745,9 @@
             if (timeTotal != -1) {
                 MetricsLogger.histogram(context, "ota_time_total", timeTotal);
             }
+            if (sourceVersion != -1) {
+                MetricsLogger.histogram(context, "ota_source_version", sourceVersion);
+            }
             if (bytesWrittenInMiB != -1) {
                 MetricsLogger.histogram(context, "ota_written_in_MiBs", bytesWrittenInMiB);
             }
diff --git a/core/java/android/security/net/config/SystemCertificateSource.java b/core/java/android/security/net/config/SystemCertificateSource.java
index abef7b4..cfb195b 100644
--- a/core/java/android/security/net/config/SystemCertificateSource.java
+++ b/core/java/android/security/net/config/SystemCertificateSource.java
@@ -25,7 +25,10 @@
  * @hide
  */
 public final class SystemCertificateSource extends DirectoryCertificateSource {
-    private static final SystemCertificateSource INSTANCE = new SystemCertificateSource();
+    private static class NoPreloadHolder {
+        private static final SystemCertificateSource INSTANCE = new SystemCertificateSource();
+    }
+
     private final File mUserRemovedCaDir;
 
     private SystemCertificateSource() {
@@ -35,7 +38,7 @@
     }
 
     public static SystemCertificateSource getInstance() {
-        return INSTANCE;
+        return NoPreloadHolder.INSTANCE;
     }
 
     @Override
diff --git a/core/java/android/security/net/config/UserCertificateSource.java b/core/java/android/security/net/config/UserCertificateSource.java
index 1a7d924..d6e2b3a 100644
--- a/core/java/android/security/net/config/UserCertificateSource.java
+++ b/core/java/android/security/net/config/UserCertificateSource.java
@@ -25,7 +25,9 @@
  * @hide
  */
 public final class UserCertificateSource extends DirectoryCertificateSource {
-    private static final UserCertificateSource INSTANCE = new UserCertificateSource();
+    private static class NoPreloadHolder {
+        private static final UserCertificateSource INSTANCE = new UserCertificateSource();
+    }
 
     private UserCertificateSource() {
         super(new File(
@@ -33,7 +35,7 @@
     }
 
     public static UserCertificateSource getInstance() {
-        return INSTANCE;
+        return NoPreloadHolder.INSTANCE;
     }
 
     @Override
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
index b4131b4..415e70c 100644
--- a/core/java/android/view/SurfaceControl.java
+++ b/core/java/android/view/SurfaceControl.java
@@ -51,6 +51,7 @@
 
     private static native void nativeSetLayer(long nativeObject, int zorder);
     private static native void nativeSetPosition(long nativeObject, float x, float y);
+    private static native void nativeSetPositionAppliesWithResize(long nativeObject);
     private static native void nativeSetSize(long nativeObject, int w, int h);
     private static native void nativeSetTransparentRegionHint(long nativeObject, Region region);
     private static native void nativeSetAlpha(long nativeObject, float alpha);
@@ -407,6 +408,16 @@
         nativeSetPosition(mNativeObject, x, y);
     }
 
+    /**
+     * If the size changes in this transaction, position updates specified
+     * in this transaction will not complete until a buffer of the new size
+     * arrives.
+     */
+    public void setPositionAppliesWithResize() {
+        checkNotReleased();
+        nativeSetPositionAppliesWithResize(mNativeObject);
+    }
+
     public void setSize(int w, int h) {
         checkNotReleased();
         nativeSetSize(mNativeObject, w, h);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 88605db..5f6ee09 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -20538,6 +20538,10 @@
         if (ViewDebug.DEBUG_DRAG) {
             Log.d(VIEW_LOG_TAG, "startDragAndDrop: data=" + data + " flags=" + flags);
         }
+        if (mAttachInfo == null) {
+            Log.w(VIEW_LOG_TAG, "startDragAndDrop called on a detached view.");
+            return false;
+        }
         boolean okay = false;
 
         Point shadowSize = new Point();
@@ -20614,6 +20618,10 @@
         if (ViewDebug.DEBUG_DRAG) {
             Log.d(VIEW_LOG_TAG, "cancelDragAndDrop");
         }
+        if (mAttachInfo == null) {
+            Log.w(VIEW_LOG_TAG, "cancelDragAndDrop called on a detached view.");
+            return;
+        }
         if (mAttachInfo.mDragToken != null) {
             try {
                 mAttachInfo.mSession.cancelDragAndDrop(mAttachInfo.mDragToken);
@@ -20636,6 +20644,10 @@
         if (ViewDebug.DEBUG_DRAG) {
             Log.d(VIEW_LOG_TAG, "updateDragShadow");
         }
+        if (mAttachInfo == null) {
+            Log.w(VIEW_LOG_TAG, "updateDragShadow called on a detached view.");
+            return;
+        }
         if (mAttachInfo.mDragToken != null) {
             try {
                 Canvas canvas = mAttachInfo.mDragSurface.lockCanvas(null);
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 4742818..19b1cf3 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -1938,7 +1938,7 @@
                 mSurfaceHolder.setSurfaceFrameSize(mWidth, mHeight);
                 mSurfaceHolder.mSurfaceLock.unlock();
                 if (mSurface.isValid()) {
-                    if (!hadSurface || surfaceGenerationId != mSurface.getGenerationId()) {
+                    if (!hadSurface) {
                         mSurfaceHolder.ungetCallbacks();
 
                         mIsCreating = true;
@@ -1951,7 +1951,7 @@
                         }
                         surfaceChanged = true;
                     }
-                    if (surfaceChanged) {
+                    if (surfaceChanged || surfaceGenerationId != mSurface.getGenerationId()) {
                         mSurfaceHolderCallback.surfaceChanged(mSurfaceHolder,
                                 lp.format, mWidth, mHeight);
                         SurfaceHolder.Callback callbacks[] = mSurfaceHolder.getCallbacks();
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index d0d4507..52f35de 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -16,6 +16,7 @@
 
 package android.view.accessibility;
 
+import android.annotation.Nullable;
 import android.graphics.Rect;
 import android.os.Parcel;
 import android.os.Parcelable;
@@ -101,8 +102,9 @@
     /**
      * Gets the title of the window.
      *
-     * @return The title.
+     * @return The title of the window, or {@code null} if none is available.
      */
+    @Nullable
     public CharSequence getTitle() {
         return mTitle;
     }
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/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 8b02352..07d38d7 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -108,7 +108,7 @@
     private static final int MAGIC = 0xBA757475; // 'BATSTATS'
 
     // Current on-disk Parcel version
-    private static final int VERSION = 144 + (USE_OLD_HISTORY ? 1000 : 0);
+    private static final int VERSION = 146 + (USE_OLD_HISTORY ? 1000 : 0);
 
     // Maximum number of items we will record in the history.
     private static final int MAX_HISTORY_ITEMS = 2000;
@@ -509,6 +509,9 @@
     int mDischargeAmountScreenOff;
     int mDischargeAmountScreenOffSinceCharge;
 
+    private LongSamplingCounter mDischargeScreenOffCounter;
+    private LongSamplingCounter mDischargeCounter;
+
     static final int MAX_LEVEL_STEPS = 200;
 
     int mInitStepMode = 0;
@@ -565,6 +568,16 @@
         return mWakeupReasonStats;
     }
 
+    @Override
+    public LongCounter getDischargeScreenOffCoulombCounter() {
+        return mDischargeScreenOffCounter;
+    }
+
+    @Override
+    public LongCounter getDischargeCoulombCounter() {
+        return mDischargeCounter;
+    }
+
     public BatteryStatsImpl() {
         this(new SystemClocks());
     }
@@ -912,7 +925,6 @@
         final TimeBase mTimeBase;
         long mCount;
         long mLoadedCount;
-        long mLastCount;
         long mUnpluggedCount;
         long mPluggedCount;
 
@@ -921,7 +933,6 @@
             mPluggedCount = in.readLong();
             mCount = mPluggedCount;
             mLoadedCount = in.readLong();
-            mLastCount = 0;
             mUnpluggedCount = in.readLong();
             timeBase.add(this);
         }
@@ -949,20 +960,19 @@
         }
 
         public long getCountLocked(int which) {
-            long val = mCount;
+            long val = mTimeBase.isRunning() ? mCount : mPluggedCount;
             if (which == STATS_SINCE_UNPLUGGED) {
                 val -= mUnpluggedCount;
             } else if (which != STATS_SINCE_CHARGED) {
                 val -= mLoadedCount;
             }
-
             return val;
         }
 
         @Override
         public void logState(Printer pw, String prefix) {
             pw.println(prefix + "mCount=" + mCount
-                    + " mLoadedCount=" + mLoadedCount + " mLastCount=" + mLastCount
+                    + " mLoadedCount=" + mLoadedCount
                     + " mUnpluggedCount=" + mUnpluggedCount
                     + " mPluggedCount=" + mPluggedCount);
         }
@@ -976,7 +986,7 @@
          */
         void reset(boolean detachIfReset) {
             mCount = 0;
-            mLoadedCount = mLastCount = mPluggedCount = mUnpluggedCount = 0;
+            mLoadedCount = mPluggedCount = mUnpluggedCount = 0;
             if (detachIfReset) {
                 detach();
             }
@@ -993,7 +1003,6 @@
         void readSummaryFromParcelLocked(Parcel in) {
             mLoadedCount = in.readLong();
             mCount = mLoadedCount;
-            mLastCount = 0;
             mUnpluggedCount = mPluggedCount = mLoadedCount;
         }
     }
@@ -7566,6 +7575,8 @@
         mFlashlightOnTimer = new StopwatchTimer(mClocks, null, -9, null, mOnBatteryTimeBase);
         mCameraOnTimer = new StopwatchTimer(mClocks, null, -13, null, mOnBatteryTimeBase);
         mBluetoothScanTimer = new StopwatchTimer(mClocks, null, -14, null, mOnBatteryTimeBase);
+        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryScreenOffTimeBase);
+        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase);
         mOnBattery = mOnBatteryInternal = false;
         long uptime = mClocks.uptimeMillis() * 1000;
         long realtime = mClocks.elapsedRealtime() * 1000;
@@ -8123,6 +8134,8 @@
         mDischargeAmountScreenOffSinceCharge = 0;
         mDischargeStepTracker.init();
         mChargeStepTracker.init();
+        mDischargeScreenOffCounter.reset(false);
+        mDischargeCounter.reset(false);
     }
 
     public void resetAllStatsCmdLocked() {
@@ -9327,6 +9340,7 @@
             mHistoryCur.states2 |= HistoryItem.STATE2_CHARGING_FLAG;
             mHistoryCur.batteryStatus = (byte)status;
             mHistoryCur.batteryLevel = (byte)level;
+            mHistoryCur.batteryChargeUAh = chargeUAh;
             mMaxChargeStepLevel = mMinDischargeStepLevel =
                     mLastChargeStepLevel = mLastDischargeStepLevel = level;
             mLastChargingStateLevel = level;
@@ -9358,6 +9372,12 @@
             mHistoryCur.batteryPlugType = (byte)plugType;
             mHistoryCur.batteryTemperature = (short)temp;
             mHistoryCur.batteryVoltage = (char)volt;
+            if (chargeUAh < mHistoryCur.batteryChargeUAh) {
+                // Only record discharges
+                final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
+                mDischargeCounter.addCountLocked(chargeDiff);
+                mDischargeScreenOffCounter.addCountLocked(chargeDiff);
+            }
             mHistoryCur.batteryChargeUAh = chargeUAh;
             setOnBatteryLocked(elapsedRealtime, uptime, onBattery, oldStatus, level);
         } else {
@@ -9394,6 +9414,12 @@
             }
             if (chargeUAh >= (mHistoryCur.batteryChargeUAh+10)
                     || chargeUAh <= (mHistoryCur.batteryChargeUAh-10)) {
+                if (chargeUAh < mHistoryCur.batteryChargeUAh) {
+                    // Only record discharges
+                    final long chargeDiff = mHistoryCur.batteryChargeUAh - chargeUAh;
+                    mDischargeCounter.addCountLocked(chargeDiff);
+                    mDischargeScreenOffCounter.addCountLocked(chargeDiff);
+                }
                 mHistoryCur.batteryChargeUAh = chargeUAh;
                 changed = true;
             }
@@ -10075,6 +10101,8 @@
         mChargeStepTracker.readFromParcel(in);
         mDailyDischargeStepTracker.readFromParcel(in);
         mDailyChargeStepTracker.readFromParcel(in);
+        mDischargeCounter.readSummaryFromParcelLocked(in);
+        mDischargeScreenOffCounter.readSummaryFromParcelLocked(in);
         int NPKG = in.readInt();
         if (NPKG > 0) {
             mDailyPackageChanges = new ArrayList<>(NPKG);
@@ -10425,6 +10453,8 @@
         mChargeStepTracker.writeToParcel(out);
         mDailyDischargeStepTracker.writeToParcel(out);
         mDailyChargeStepTracker.writeToParcel(out);
+        mDischargeCounter.writeSummaryFromParcelLocked(out);
+        mDischargeScreenOffCounter.writeSummaryFromParcelLocked(out);
         if (mDailyPackageChanges != null) {
             final int NPKG = mDailyPackageChanges.size();
             out.writeInt(NPKG);
@@ -10880,6 +10910,8 @@
         mDischargeAmountScreenOffSinceCharge = in.readInt();
         mDischargeStepTracker.readFromParcel(in);
         mChargeStepTracker.readFromParcel(in);
+        mDischargeCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
+        mDischargeScreenOffCounter = new LongSamplingCounter(mOnBatteryTimeBase, in);
         mLastWriteTime = in.readLong();
 
         mKernelWakelockStats.clear();
@@ -11028,6 +11060,8 @@
         out.writeInt(mDischargeAmountScreenOffSinceCharge);
         mDischargeStepTracker.writeToParcel(out);
         mChargeStepTracker.writeToParcel(out);
+        mDischargeCounter.writeToParcel(out);
+        mDischargeScreenOffCounter.writeToParcel(out);
         out.writeLong(mLastWriteTime);
 
         if (inclUids) {
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 7e38d9b..3cf7a4e 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -1550,7 +1550,13 @@
     private ActionMode createStandaloneActionMode(ActionMode.Callback callback) {
         endOnGoingFadeAnimation();
         cleanupPrimaryActionMode();
-        if (mPrimaryActionModeView == null) {
+        // We want to create new mPrimaryActionModeView in two cases: if there is no existing
+        // instance at all, or if there is one, but it is detached from window. The latter case
+        // might happen when app is resized in multi-window mode and decor view is preserved
+        // along with the main app window. Keeping mPrimaryActionModeView reference doesn't cause
+        // app memory leaks because killMode() is called when the dismiss animation ends and from
+        // cleanupPrimaryActionMode() invocation above.
+        if (mPrimaryActionModeView == null || !mPrimaryActionModeView.isAttachedToWindow()) {
             if (mWindow.isFloating()) {
                 // Use the action bar theme.
                 final TypedValue outValue = new TypedValue();
@@ -1616,6 +1622,7 @@
                 ViewStub stub = (ViewStub) findViewById(R.id.action_mode_bar_stub);
                 if (stub != null) {
                     mPrimaryActionModeView = (ActionBarContextView) stub.inflate();
+                    mPrimaryActionModePopup = null;
                 }
             }
         }
@@ -2278,9 +2285,14 @@
                 }
                 if (mPrimaryActionModeView != null) {
                     endOnGoingFadeAnimation();
+                    // Store action mode view reference, so we can access it safely when animation
+                    // ends. mPrimaryActionModePopup is set together with mPrimaryActionModeView,
+                    // so no need to store reference to it in separate variable.
+                    final ActionBarContextView lastActionModeView = mPrimaryActionModeView;
                     mFadeAnim = ObjectAnimator.ofFloat(mPrimaryActionModeView, View.ALPHA,
                             1f, 0f);
                     mFadeAnim.addListener(new Animator.AnimatorListener() {
+
                                 @Override
                                 public void onAnimationStart(Animator animation) {
 
@@ -2288,12 +2300,17 @@
 
                                 @Override
                                 public void onAnimationEnd(Animator animation) {
-                                    mPrimaryActionModeView.setVisibility(GONE);
-                                    if (mPrimaryActionModePopup != null) {
-                                        mPrimaryActionModePopup.dismiss();
+                                    // If mPrimaryActionModeView has changed - it means that we've
+                                    // cleared the content while preserving decor view. We don't
+                                    // want to change the state of new instances accidentally here.
+                                    if (lastActionModeView == mPrimaryActionModeView) {
+                                        lastActionModeView.setVisibility(GONE);
+                                        if (mPrimaryActionModePopup != null) {
+                                            mPrimaryActionModePopup.dismiss();
+                                        }
+                                        lastActionModeView.killMode();
+                                        mFadeAnim = null;
                                     }
-                                    mPrimaryActionModeView.removeAllViews();
-                                    mFadeAnim = null;
                                 }
 
                                 @Override
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 18408aa..9ad750d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -528,16 +528,22 @@
 
     @Override
     public void setTitle(CharSequence title) {
+        setTitle(title, true);
+    }
+
+    public void setTitle(CharSequence title, boolean updateAccessibilityTitle) {
         if (mTitleView != null) {
             mTitleView.setText(title);
         } else if (mDecorContentParent != null) {
             mDecorContentParent.setWindowTitle(title);
         }
         mTitle = title;
-        WindowManager.LayoutParams params = getAttributes();
-        if (!TextUtils.equals(title, params.accessibilityTitle)) {
-            params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
-            dispatchWindowAttributesChanged(getAttributes());
+        if (updateAccessibilityTitle) {
+            WindowManager.LayoutParams params = getAttributes();
+            if (!TextUtils.equals(title, params.accessibilityTitle)) {
+                params.accessibilityTitle = TextUtils.stringOrSpannedString(title);
+                dispatchWindowAttributesChanged(getAttributes());
+            }
         }
     }
 
diff --git a/core/java/com/android/internal/widget/MessagingLinearLayout.java b/core/java/com/android/internal/widget/MessagingLinearLayout.java
index dc7b7f5..d2a43b7 100644
--- a/core/java/com/android/internal/widget/MessagingLinearLayout.java
+++ b/core/java/com/android/internal/widget/MessagingLinearLayout.java
@@ -48,6 +48,11 @@
 
     private int mIndentLines;
 
+    /**
+     * Id of the child that's also visible in the contracted layout.
+     */
+    private int mContractedChildId;
+
     public MessagingLinearLayout(Context context, @Nullable AttributeSet attrs) {
         super(context, attrs);
 
@@ -255,14 +260,29 @@
         return copy;
     }
 
-    @RemotableViewMethod
     /**
      * Sets how many lines should be indented to avoid a floating image.
      */
+    @RemotableViewMethod
     public void setNumIndentLines(int numberLines) {
         mIndentLines = numberLines;
     }
 
+    /**
+     * Set id of the child that's also visible in the contracted layout.
+     */
+    @RemotableViewMethod
+    public void setContractedChildId(int contractedChildId) {
+        mContractedChildId = contractedChildId;
+    }
+
+    /**
+     * Get id of the child that's also visible in the contracted layout.
+     */
+    public int getContractedChildId() {
+        return mContractedChildId;
+    }
+
     public static class LayoutParams extends MarginLayoutParams {
 
         boolean hide = false;
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
index a9ed9dc..ff75677 100644
--- a/core/jni/android_view_SurfaceControl.cpp
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -248,6 +248,15 @@
     }
 }
 
+static void nativeSetPositionAppliesWithResize(JNIEnv* env, jclass clazz,
+        jlong nativeObject) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setPositionAppliesWithResize();
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
 static void nativeSetSize(JNIEnv* env, jclass clazz, jlong nativeObject, jint w, jint h) {
     SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
     status_t err = ctrl->setSize(w, h);
@@ -658,6 +667,8 @@
             (void*)nativeSetLayer },
     {"nativeSetPosition", "(JFF)V",
             (void*)nativeSetPosition },
+    {"nativeSetPositionAppliesWithResize", "(J)V",
+            (void*)nativeSetPositionAppliesWithResize },
     {"nativeSetSize", "(JII)V",
             (void*)nativeSetSize },
     {"nativeSetTransparentRegionHint", "(JLandroid/graphics/Region;)V",
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index b03ba20..e9a3409 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -360,6 +360,7 @@
     <!-- Added in N -->
     <protected-broadcast android:name="android.intent.action.ANR" />
     <protected-broadcast android:name="android.intent.action.CALL" />
+    <protected-broadcast android:name="android.intent.action.CALL_PRIVILEGED" />
     <protected-broadcast android:name="android.intent.action.DROPBOX_ENTRY_ADDED" />
     <protected-broadcast android:name="android.intent.action.INPUT_METHOD_CHANGED" />
     <protected-broadcast android:name="android.intent.action.internal_sim_state_changed" />
@@ -480,6 +481,7 @@
 
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_AVAILABLE" />
     <protected-broadcast android:name="android.intent.action.MANAGED_PROFILE_UNAVAILABLE" />
+    <protected-broadcast android:name="com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK" />
 
     <!-- ====================================================================== -->
     <!--                          RUNTIME PERMISSIONS                           -->
@@ -1621,6 +1623,14 @@
     <permission android:name="android.permission.MANAGE_USERS"
         android:protectionLevel="signature|privileged" />
 
+    <!-- @hide Allows an application to create, remove users and get the list of
+         users on the device. Applications holding this permission can only create restricted,
+         guest, managed, and ephemeral users. For creating other kind of users,
+         {@link android.Manifest.permission#MANAGE_USERS} is needed.
+         This permission is not available to third party applications. -->
+    <permission android:name="android.permission.CREATE_USERS"
+        android:protectionLevel="signature" />
+
     <!-- @hide Allows an application to set the profile owners and the device owner.
          This permission is not available to third party applications.-->
     <permission android:name="android.permission.MANAGE_PROFILE_AND_DEVICE_OWNERS"
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-da/strings.xml b/core/res/res/values-da/strings.xml
index 6cd8d9f..e737f55 100644
--- a/core/res/res/values-da/strings.xml
+++ b/core/res/res/values-da/strings.xml
@@ -800,8 +800,8 @@
     <string name="permdesc_setAlarm" msgid="316392039157473848">"Tillader, at appen kan indstille en alarm i en installeret alarmapp. Nogle alarmapps har muligvis ikke denne funktion."</string>
     <string name="permlab_addVoicemail" msgid="5525660026090959044">"tilføje telefonsvarer"</string>
     <string name="permdesc_addVoicemail" msgid="6604508651428252437">"Tillader, at appen kan tilføje beskeder på din telefonsvarer."</string>
-    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"skifte tilladelser til geografisk placering i Browser"</string>
-    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillader, at appen kan ændre browserens tilladelser angående geografisk placering. Ondsindede apps kan benytte dette til at sende oplysninger om placering til vilkårlige websites."</string>
+    <string name="permlab_writeGeolocationPermissions" msgid="5962224158955273932">"skifte tilladelser til geoplacering i Browser"</string>
+    <string name="permdesc_writeGeolocationPermissions" msgid="1083743234522638747">"Tillader, at appen kan ændre browserens tilladelser angående geoplacering. Ondsindede apps kan benytte dette til at sende oplysninger om sted til vilkårlige websites."</string>
     <string name="save_password_message" msgid="767344687139195790">"Ønsker du, at browseren skal huske denne adgangskode?"</string>
     <string name="save_password_notnow" msgid="6389675316706699758">"Ikke nu"</string>
     <string name="save_password_remember" msgid="6491879678996749466">"Husk"</string>
diff --git a/core/res/res/values-de/strings.xml b/core/res/res/values-de/strings.xml
index 616d2b8..9245749 100644
--- a/core/res/res/values-de/strings.xml
+++ b/core/res/res/values-de/strings.xml
@@ -525,11 +525,11 @@
     <string name="policylab_resetPassword" msgid="4934707632423915395">"Displaysperre ändern"</string>
     <string name="policydesc_resetPassword" msgid="1278323891710619128">"Displaysperre ändern"</string>
     <string name="policylab_forceLock" msgid="2274085384704248431">"Bildschirm sperren"</string>
-    <string name="policydesc_forceLock" msgid="1141797588403827138">"Lege fest, wie und wann der Bildschirm gesperrt wird."</string>
+    <string name="policydesc_forceLock" msgid="1141797588403827138">"Festlegen, wie und wann der Bildschirm gesperrt wird"</string>
     <string name="policylab_wipeData" msgid="3910545446758639713">"Alle Daten löschen"</string>
     <string name="policydesc_wipeData" product="tablet" msgid="4306184096067756876">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Tablet ohne Warnung löschen"</string>
     <string name="policydesc_wipeData" product="tv" msgid="5816221315214527028">"Auf Werkseinstellungen zurücksetzen und Daten auf dem Fernseher ohne Warnung löschen"</string>
-    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Setze das Telefon auf die Werkseinstellungen zurück. Dabei werden alle Daten ohne Warnung gelöscht."</string>
+    <string name="policydesc_wipeData" product="default" msgid="5096895604574188391">"Auf Werkseinstellungen zurücksetzen und damit Daten auf dem Telefon ohne Warnung löschen"</string>
     <string name="policylab_wipeData_secondaryUser" msgid="8362863289455531813">"Nutzerdaten löschen"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tablet" msgid="6336255514635308054">"Daten dieses Nutzers auf diesem Tablet ohne vorherige Warnung löschen"</string>
     <string name="policydesc_wipeData_secondaryUser" product="tv" msgid="2086473496848351810">"Daten dieses Nutzers auf diesem Fernseher ohne vorherige Warnung löschen"</string>
@@ -543,7 +543,7 @@
     <string name="policylab_disableCamera" msgid="6395301023152297826">"Kameras deaktivieren"</string>
     <string name="policydesc_disableCamera" msgid="2306349042834754597">"Nutzung sämtlicher Gerätekameras unterbinden"</string>
     <string name="policylab_disableKeyguardFeatures" msgid="8552277871075367771">"Einige Funktionen der Displaysperre deaktivieren"</string>
-    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Verhindert die Verwendung einiger Funktionen der Displaysperre"</string>
+    <string name="policydesc_disableKeyguardFeatures" msgid="2044755691354158439">"Verwendung einiger Funktionen der Displaysperre verhindern"</string>
   <string-array name="phoneTypes">
     <item msgid="8901098336658710359">"Privat"</item>
     <item msgid="869923650527136615">"Mobil"</item>
diff --git a/core/res/res/values-hy-rAM/strings.xml b/core/res/res/values-hy-rAM/strings.xml
index ee89493..d2ff283 100644
--- a/core/res/res/values-hy-rAM/strings.xml
+++ b/core/res/res/values-hy-rAM/strings.xml
@@ -228,9 +228,9 @@
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Անձայն ռեժիմ"</string>
     <string name="global_action_silent_mode_on_status" msgid="3289841937003758806">"Ձայնը անջատված է"</string>
     <string name="global_action_silent_mode_off_status" msgid="1506046579177066419">"Ձայնը միացված է"</string>
-    <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Ինքնաթիռային ռեժիմ"</string>
-    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Ինքնաթիռային ռեժիմը միացված է"</string>
-    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Ինքնաթիռային ռեժիմը անջատված է"</string>
+    <string name="global_actions_toggle_airplane_mode" msgid="5884330306926307456">"Ինքնաթիռի ռեժիմ"</string>
+    <string name="global_actions_airplane_mode_on_status" msgid="2719557982608919750">"Ինքնաթիռի ռեժիմը միացված է"</string>
+    <string name="global_actions_airplane_mode_off_status" msgid="5075070442854490296">"Ինքնաթիռի ռեժիմը անջատված է"</string>
     <string name="global_action_settings" msgid="1756531602592545966">"Կարգավորումներ"</string>
     <string name="global_action_assist" msgid="3892832961594295030">"Օգնական"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"Ձայնային օգնութ"</string>
diff --git a/core/res/res/values-lt/strings.xml b/core/res/res/values-lt/strings.xml
index 0b062d1..adc071d42 100644
--- a/core/res/res/values-lt/strings.xml
+++ b/core/res/res/values-lt/strings.xml
@@ -344,11 +344,11 @@
     <string name="permdesc_writeContacts" product="default" msgid="589869224625163558">"Leidžiama programai keisti duomenis apie telefone saugomus kontaktus, įskaitant dažnį, kuriuo konkretiems asmenims skambinote, siuntėte el. laiškus ar bendravote kitais būdais. Šis leidimas suteikia teisę programoms ištrinti kontaktinius duomenis."</string>
     <string name="permlab_readCallLog" msgid="3478133184624102739">"skaityti skambučių žurnalą"</string>
     <string name="permdesc_readCallLog" product="tablet" msgid="3700645184870760285">"Leidžiama programai skaityti planšetinio kompiuterio skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Šis leidimas suteikia teisę programai išsaugoti skambučių žurnalo duomenis, o kenkėjiškos programos gali bendrinti skambučių žurnalą be jūsų žinios."</string>
-    <string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Programai leidžiama nuskaityti TV skambučių žurnalą, įskaitant duomenis apie gaunamus arba siunčiamus skambučius. Dėl šio leidimo programoms leidžiama išsaugoti skambučių žurnalo duomenis, o kenkėjiškos programos gali bendrinti šiuos duomenis be jūsų žinios."</string>
+    <string name="permdesc_readCallLog" product="tv" msgid="5611770887047387926">"Programai leidžiama nuskaityti TV skambučių žurnalą, įskaitant duomenis apie gaunamuosius arba siunčiamuosius skambučius. Dėl šio leidimo programoms leidžiama išsaugoti skambučių žurnalo duomenis, o kenkėjiškos programos gali bendrinti šiuos duomenis be jūsų žinios."</string>
     <string name="permdesc_readCallLog" product="default" msgid="5777725796813217244">"Leidžiama programai skaityti telefono skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Šis leidimas suteikia teisę programai išsaugoti skambučių žurnalo duomenis, o kenkėjiškos programos gali bendrinti skambučių žurnalą be jūsų žinios."</string>
     <string name="permlab_writeCallLog" msgid="8552045664743499354">"rašyti skambučių žurnalą"</string>
     <string name="permdesc_writeCallLog" product="tablet" msgid="6661806062274119245">"Programai leidžiama skaityti planšetinio kompiuterio skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Kenkėjiškos programos tai gali naudoti, kad ištrintų ar keistų jūsų skambučių žurnalą."</string>
-    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Programai leidžiama keisti TV skambučių žurnalą, įskaitant duomenis apie gaunamus ir siunčiamus skambučius. Taip kenkėjiškos programos gali ištrinti arba pakeisti skambučių žurnalą."</string>
+    <string name="permdesc_writeCallLog" product="tv" msgid="4225034892248398019">"Programai leidžiama keisti TV skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Taip kenkėjiškos programos gali ištrinti arba pakeisti skambučių žurnalą."</string>
     <string name="permdesc_writeCallLog" product="default" msgid="683941736352787842">"Programai leidžiama skaityti telefono skambučių žurnalą, įskaitant duomenis apie gaunamuosius ir siunčiamuosius skambučius. Kenkėjiškos programos tai gali naudoti, kad ištrintų ar keistų jūsų skambučių žurnalą."</string>
     <string name="permlab_bodySensors" msgid="4683341291818520277">"pas. k. jut. (pvz., pul. dažn. st. įr.)"</string>
     <string name="permdesc_bodySensors" product="default" msgid="4380015021754180431">"Programai leidžiama pasiekti duomenis, gautus iš jutiklių, stebinčių fizinę būseną, pvz., širdies ritmą."</string>
diff --git a/core/res/res/values-mn-rMN/strings.xml b/core/res/res/values-mn-rMN/strings.xml
index baf95b1..4f10c45 100644
--- a/core/res/res/values-mn-rMN/strings.xml
+++ b/core/res/res/values-mn-rMN/strings.xml
@@ -395,9 +395,9 @@
     <string name="permdesc_setTimeZone" product="tv" msgid="888864653946175955">"Апп-д телевизийн цагийн бүсийг өөрчлөхийг зөвшөөрдөг."</string>
     <string name="permdesc_setTimeZone" product="default" msgid="4499943488436633398">"Апп нь утасны цагийн бүсийг өөрчлөх боломжтой."</string>
     <string name="permlab_getAccounts" msgid="1086795467760122114">"төхөөрөмж дээрх акаунтыг олох"</string>
-    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Апп нь таблетэд мэдэгдэж байгаа акаунтын жагсаалтыг авах боломжтой. Энд таны суулгасан аппликешнүүдийн үүсгэсэн бүх акаунтууд хамрагдана."</string>
+    <string name="permdesc_getAccounts" product="tablet" msgid="2741496534769660027">"Апп нь таблетэд мэдэгдэж байгаа бүртгэлийн жагсаалтыг авах боломжтой. Энд таны суулгасан аппликешнүүдийн үүсгэсэн бүх акаунтууд хамрагдана."</string>
     <string name="permdesc_getAccounts" product="tv" msgid="4190633395633907543">"Телевизийн жагсаалтад байгаа акаунтуудын хаягийг апп-д авахыг зөвшөөрдөг. Энэ нь таны суулгасан бусад аппликэйшнүүдийн бий болгосон акаунтуудыг оруулж болно."</string>
-    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Апп нь утсанд мэдэгдэж байгаа акаунтын жагсаалтыг авах боломжтой. Энд таны суулгасан аппликешнүүдийн үүсгэсэн бүх акаунтууд хамрагдана."</string>
+    <string name="permdesc_getAccounts" product="default" msgid="3448316822451807382">"Апп нь утсанд мэдэгдэж байгаа бүртгэлийн жагсаалтыг авах боломжтой. Энд таны суулгасан аппликешнүүдийн үүсгэсэн бүх акаунтууд хамрагдана."</string>
     <string name="permlab_accessNetworkState" msgid="4951027964348974773">"сүлжээний холболтыг үзэх"</string>
     <string name="permdesc_accessNetworkState" msgid="8318964424675960975">"Апп нь сүлжээ байгаа болон холбогдсон эсэх зэрэг сүлжээний холболтын талаарх мэдээллийг харах боломжтой."</string>
     <string name="permlab_createNetworkSockets" msgid="7934516631384168107">"сүлжээнд бүрэн нэвтрэх"</string>
@@ -454,11 +454,11 @@
   </string-array>
     <string name="fingerprint_icon_content_description" msgid="2340202869968465936">"Хурууны хээний дүрс"</string>
     <string name="permlab_readSyncSettings" msgid="6201810008230503052">"синк тохиргоог унших"</string>
-    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Апп нь акаунтын синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп акаунттай синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string>
+    <string name="permdesc_readSyncSettings" msgid="2706745674569678644">"Апп нь бүртгэлийн синк тохиргоог унших боломжтой. Жишээ нь энэ нь Хүмүүс апп бүртгэлтэй синк хийгдсэн эсэхийг тодорхойлох боломжтой."</string>
     <string name="permlab_writeSyncSettings" msgid="5408694875793945314">"синкийг унтрааж асаах тохиргоо"</string>
-    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Апп нь акаунтын синк тохиргоог өөрчлөх боломжтой. Жишээ нь энэ нь Хүмүүс апп акаунттай синк хийхийг идэвхжүүлэх боломжтой."</string>
+    <string name="permdesc_writeSyncSettings" msgid="8956262591306369868">"Апп нь бүртгэлийн синк тохиргоог өөрчлөх боломжтой. Жишээ нь энэ нь Хүмүүс апп бүртгэлтэй синк хийхийг идэвхжүүлэх боломжтой."</string>
     <string name="permlab_readSyncStats" msgid="7396577451360202448">"синк статистикийг унших"</string>
-    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Апп нь синк үйлдэлийн түүх болон хэр их дата синк хийгдсэн зэрэг акаунтын синк статусыг унших боломжтой."</string>
+    <string name="permdesc_readSyncStats" msgid="1510143761757606156">"Апп нь синк үйлдэлийн түүх болон хэр их дата синк хийгдсэн зэрэг бүртгэлийн синк статусыг унших боломжтой."</string>
     <string name="permlab_sdcardRead" product="nosdcard" msgid="367275095159405468">"таны USB сангийн агуулгыг унших боломжтой"</string>
     <string name="permlab_sdcardRead" product="default" msgid="2188156462934977940">"таны SD картны агуулгыг унших боломжтой"</string>
     <string name="permdesc_sdcardRead" product="nosdcard" msgid="3446988712598386079">"Апп нь таны USB сангийн агуулгыг унших боломжтой."</string>
@@ -1261,7 +1261,7 @@
     <string name="gpsVerifYes" msgid="2346566072867213563">"Тийм"</string>
     <string name="gpsVerifNo" msgid="1146564937346454865">"Үгүй"</string>
     <string name="sync_too_many_deletes" msgid="5296321850662746890">"Устгах хязгаар хэтрэв"</string>
-    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>-р <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> акаунтын <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> зүйл устсан . Та юу хиймээр байна?"</string>
+    <string name="sync_too_many_deletes_desc" msgid="496551671008694245">"<xliff:g id="TYPE_OF_SYNC">%2$s</xliff:g>-р <xliff:g id="ACCOUNT_NAME">%3$s</xliff:g> бүртгэлийн <xliff:g id="NUMBER_OF_DELETED_ITEMS">%1$d</xliff:g> зүйл устсан . Та юу хиймээр байна?"</string>
     <string name="sync_really_delete" msgid="2572600103122596243">"Устгах"</string>
     <string name="sync_undo_deletes" msgid="2941317360600338602">"Устгасныг буцаах"</string>
     <string name="sync_do_nothing" msgid="3743764740430821845">"Одоо юу ч хийхгүй"</string>
@@ -1412,7 +1412,7 @@
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="4817627474419471518">"Та утсыг тайлах гэж <xliff:g id="NUMBER">%d</xliff:g> удаа буруу оролдлоо. Утас одоо үйлдвэрийн үндсэн утгаараа тохируулагдах болно."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="3253575572118914370">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та таблетаа тайлахын тулд имэйл бүртгэл шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4224651132862313471">"Та зурган түгжээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу оруулсан байна. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа буруу оруулсны дараагаар та телевизийнхээ түгжээг и-мэйл дансаа ашиглан тайлах хэрэгтэй болно.\n\n Та <xliff:g id="NUMBER_2">%3$d</xliff:g> секундийн дараа дахин оролдоно уу."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл акаунтаа ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="1437638152015574839">"Та тайлах хээг <xliff:g id="NUMBER_0">%1$d</xliff:g> удаа буруу зурлаа. <xliff:g id="NUMBER_1">%2$d</xliff:g> удаа дахин буруу оруулбал, та утсаа тайлахын тулд имэйл бүртгэлээ ашиглах шаардлагатай болно.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> секундын дараа дахин оролдоно уу."</string>
     <string name="kg_text_message_separator" product="default" msgid="4160700433287233771">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="7899202978204438708">"Устгах"</string>
     <string name="safe_media_volume_warning" product="default" msgid="2276318909314492312">"Дууг санал болгосноос чанга болгож өсгөх үү?\n\nУрт хугацаанд чанга хөгжим сонсох нь таны сонсголыг муутгаж болно."</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index fe136c3..221d055 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -245,19 +245,19 @@
     <string name="permgrouplab_contacts" msgid="3657758145679177612">"Contactos"</string>
     <string name="permgroupdesc_contacts" msgid="6951499528303668046">"aceder aos contactos"</string>
     <string name="permgrouplab_location" msgid="7275582855722310164">"Localização"</string>
-    <string name="permgroupdesc_location" msgid="1346617465127855033">"aceda à localização do seu dispositivo"</string>
+    <string name="permgroupdesc_location" msgid="1346617465127855033">"aceder à localização do seu dispositivo"</string>
     <string name="permgrouplab_calendar" msgid="5863508437783683902">"Calendário"</string>
-    <string name="permgroupdesc_calendar" msgid="3889615280211184106">"aceda ao calendário"</string>
+    <string name="permgroupdesc_calendar" msgid="3889615280211184106">"aceder ao calendário"</string>
     <string name="permgrouplab_sms" msgid="228308803364967808">"SMS"</string>
-    <string name="permgroupdesc_sms" msgid="4656988620100940350">"envie e veja mensagens SMS"</string>
+    <string name="permgroupdesc_sms" msgid="4656988620100940350">"enviar e ver mensagens SMS"</string>
     <string name="permgrouplab_storage" msgid="1971118770546336966">"Armazenamento"</string>
-    <string name="permgroupdesc_storage" msgid="637758554581589203">"aceda a fotos, multimédia e ficheiros no dispositivo"</string>
+    <string name="permgroupdesc_storage" msgid="637758554581589203">"aceder a fotos, multimédia e ficheiros no dispositivo"</string>
     <string name="permgrouplab_microphone" msgid="171539900250043464">"Microfone"</string>
     <string name="permgroupdesc_microphone" msgid="4988812113943554584">"gravar áudio"</string>
     <string name="permgrouplab_camera" msgid="4820372495894586615">"Câmara"</string>
     <string name="permgroupdesc_camera" msgid="3250611594678347720">"tirar fotografias e gravar vídeos"</string>
     <string name="permgrouplab_phone" msgid="5229115638567440675">"Telemóvel"</string>
-    <string name="permgroupdesc_phone" msgid="6234224354060641055">"faça e gira chamadas"</string>
+    <string name="permgroupdesc_phone" msgid="6234224354060641055">"fazer e gerir chamadas"</string>
     <string name="permgrouplab_sensors" msgid="416037179223226722">"Sensores de corpo"</string>
     <string name="permgroupdesc_sensors" msgid="7147968539346634043">"aceder a dados do sensor acerca dos seus sinais vitais"</string>
     <string name="capability_title_canRetrieveWindowContent" msgid="3901717936930170320">"Obter conteúdo da janela"</string>
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/core/res/res/values/themes.xml b/core/res/res/values/themes.xml
index aecda44..998eea5 100644
--- a/core/res/res/values/themes.xml
+++ b/core/res/res/values/themes.xml
@@ -174,6 +174,7 @@
 
         <!-- Window attributes -->
         <item name="windowBackground">@drawable/screen_background_selector_dark</item>
+        <item name="windowBackgroundFallback">?attr/colorBackground</item>
         <item name="windowClipToOutline">false</item>
         <item name="windowFrame">@null</item>
         <item name="windowNoTitle">false</item>
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 65e81312..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/screens_support.jd b/docs/html/guide/practices/screens_support.jd
index 4d93c835..2223dbf 100644
--- a/docs/html/guide/practices/screens_support.jd
+++ b/docs/html/guide/practices/screens_support.jd
@@ -988,7 +988,7 @@
 on different screens:</p>
 
 <ol>
-  <li>Use {@code wrap_content}, {@code fill_parent}, or {@code dp} units when specifying
+  <li>Use {@code wrap_content}, {@code match_parent}, or {@code dp} units when specifying
 dimensions in an XML layout file</li>
   <li>Do not use hard coded pixel values in your application code</li>
   <li>Do not use {@code AbsoluteLayout} (it's deprecated)</li>
@@ -998,7 +998,7 @@
 <p>The following sections provide more details.</p>
 
 
-<h3 id="use-relative">1. Use wrap_content, fill_parent, or the dp unit for layout dimensions</h3>
+<h3 id="use-relative">1. Use wrap_content, match_parent, or the dp unit for layout dimensions</h3>
 
 <p>When defining the <a
 href="{@docRoot}reference/android/view/ViewGroup.LayoutParams.html#attr_android:layout_width"
@@ -1006,7 +1006,7 @@
 href="{@docRoot}reference/android/view/ViewGroup.LayoutParams.html#attr_android:layout_height"
 >{@code android:layout_height}</a> for
 views in an XML layout file, using <code>"wrap_content"</code>,
-<code>"fill_parent"</code> or <code>dp</code> units guarantees that the view is
+<code>"match_parent"</code> or <code>dp</code> units guarantees that the view is
 given an appropriate size on the current device screen.</p>
 
 <p>For instance, a view with a <code>layout_width="100dp"</code> measures 100 pixels wide on
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/guide/topics/manifest/activity-element.jd b/docs/html/guide/topics/manifest/activity-element.jd
index e0f5e3d..f30263e 100644
--- a/docs/html/guide/topics/manifest/activity-element.jd
+++ b/docs/html/guide/topics/manifest/activity-element.jd
@@ -714,7 +714,7 @@
 &lt;activity
     android:name="com.example.app.ChildActivity"
     android:label="@string/title_child_activity"
-    android:parentActivityName="com.example.myfirstapp.MainActivity" >
+    android:parentActivityName="com.example.app.MainActivity" >
     &lt;!-- Parent activity meta-data to support API level 4+ -->
     &lt;meta-data
         android:name="android.support.PARENT_ACTIVITY"
diff --git a/docs/html/jd_extras_en.js b/docs/html/jd_extras_en.js
index 6295e0e..2137929 100644
--- a/docs/html/jd_extras_en.js
+++ b/docs/html/jd_extras_en.js
@@ -5379,10 +5379,15 @@
       "preview/support.html"
     ]
   },
+  "preview/landing/videos/first": {
+    "title": "",
+    "resources": [
+    "https://www.youtube.com/watch?v=CsulIu3UaUM"
+    ]
+  },
   "preview/landing/more": {
     "title": "",
     "resources": [
-      "https://www.youtube.com/watch?v=CsulIu3UaUM",
       "preview/features/multi-window.html",
       "preview/features/notification-updates.html",
       "preview/features/background-optimization.html",
diff --git a/docs/html/ndk/guides/graphics/getting-started.jd b/docs/html/ndk/guides/graphics/getting-started.jd
index 145e534..0c2d939 100644
--- a/docs/html/ndk/guides/graphics/getting-started.jd
+++ b/docs/html/ndk/guides/graphics/getting-started.jd
@@ -137,7 +137,7 @@
 
 <ol style="1">
 <li>Select your project in the Android Studio <em>Project</em> panel.</li>
-<li>From the <strong>Build</strong> menu, choose <strong>Make Module &lt;module-name&gt; </strong>.</li>
+<li>From the <strong>Build</strong> menu, choose <strong>Make Module &lt;module-name&gt; </strong>; or select <strong> Build APK </strong> to generate APK.</li>
 <li>Resolve any dependency issues, and then compile. As Figure 2 shows, you can select individual projects to compile by choosing them from the configuration pulldown.</li>
 
 <img src="../images/config-pulldown.png"
diff --git a/docs/html/ndk/guides/graphics/validation-layer.jd b/docs/html/ndk/guides/graphics/validation-layer.jd
index beac1c0..1a7d832 100644
--- a/docs/html/ndk/guides/graphics/validation-layer.jd
+++ b/docs/html/ndk/guides/graphics/validation-layer.jd
@@ -6,19 +6,8 @@
       <h2>On this page</h2>
 
       <ol>
+        <li><a href="#ilp">Add Validation Layers to Project</a></li>
         <li><a href="#gls">Getting Layer Source</a></li>
-        <li><a href="#ias">Android Studio Integration</a>
-        <ol>
-            <li><a href="#asbl">Building Layers</a></li>
-            <li><a href="#asil">Installing Layers</a></li>
-        </ol>
-        </li>
-        <li><a href="#cli">Integrating on the Command Line</a>
-            <ol>
-            <li><a href="#clibl">Building Layers</a></li>
-            <li><a href="#cliil">Installing Layers</a></li>
-            </ol>
-        </li>
         <li><a href="#verifying">Verifying Layer Build</a></li>
         <li><a href="#enabling">Enabling Layers</a></li>
         <li><a href="#debug">Enabling the Debug Callback</a></li>
@@ -52,272 +41,94 @@
 <p>
 This page explains how to:
 <ul>
+   <li>Integrate NDK's Layer Binaries.</li>
    <li>Get source code for validation layers.</li>
-   <li>Build the layers.</li>
-   <li>Incorporate the layers into your app.</li>
+   <li>Verifying Layer Build.</li>
+   <li>Enabling Layers in Vulkan Application.</li>
+
 </ul>
 </p>
 
+<h2 id="ilp">Add Validation Layers to Project</h2>
+
+<p>
+  NDK release 12 and higher includes pre-built validation layer binaries. At
+  instance and device creation time, when requested by your application, the
+  Vulkan loader finds them in the APK installed location and loads them.
+</p>
+
+<p>
+  To use the pre-built validation layer binaries, either modify the gradle build
+  configuration of your project or manually add the binaries into the JNI
+  libraries directory of your project.
+</p>
+
+
+<h3 id="vl-gradle">Adding validation layers with Gradle</h3>
+
+<p>
+  You can add the validation layer your project using either Andorid Studio's
+  support for CMake and Ndk-build, or using Studio's experimental plugin for
+  Gradle. In general, you should use the CMake and Ndk-build configuration.
+</p>
+
+
+<p>
+  To add the libraries using Android Studio's support for CMake/Ndk-build,
+  add the following to your project's gradle configuration:
+</p>
+
+<pre class="no-pretty-print">
+sourceSets {
+  main {
+    jniLibs {
+      srcDir "${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs"
+    }
+  }
+}</pre>
+
+<p>
+  To add the libraries using Android Studio's experimental plugin for Gradle,
+  add the following to your project's gradle configuration:
+</p>
+
+<pre class="no-pretty-print">
+sources {
+  main {
+    jniLibs {
+      source.srcDir "${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs"
+    }
+  }
+}</pre>
+
+
+<h3 id="vl-jni-lib">Adding validation layers to JNI libraries</h3>
+
+<p>
+  If configuring your project's gradle build file is not working, you can
+  manually add the validation layer binaries to your project's JNI libraries
+  directory by using the following command line options:
+</p>
+
+<pre class="no-pretty-print">
+$ cd ${your-app-project-root}
+$ mkdir -p app/src/main
+$ cp -fr ${your-ndk-dir}/sources/third_party/vulkan/src/build-android/jniLibs app/src/main/
+</pre>
+
+
 <h2 id="gls">Getting Layer Source</h2>
 <p>
-This section explains how to build layers from source.
-If you have precompiled layers, you can skip this section, and instead read about how to
-install your layers using <a href="#asil">Android Studio</a> or from the <a href="cliil">
-command line</a>.
-</p>
-<h3 id="ftn">From the NDK (Recommended)</h3>
-
-<p>
-<a href="{@docRoot}ndk/downloads/index.html">NDK Revision 12</a> and later contains source
-code for Android validation layers that is known-good, and ready to build. This code resides under
-the {@code &lt;ndk-root&gt;/sources/third_party/vulkan/src/build-android/generated/gradle-build}
-directory. This version of the layers should be sufficient for most needs. If so, your next task is
-to <a href="#building">build them</a>. Alternatively, you can pull source code from the
-Khronos Group repository.
-</pre>
-</p>
-
-<h3 id="ftr">From the repository</h3>
-
-<p>
-Although we recommend that you use the source code provided with the NDK, you can also pull more
-recent versions of the source code directly from the
+If your app needs the latest validation layer, you can pull the latest source from the Khronos Group
 <a class="external-link" href="https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers">
-GitHub repository</a> belonging to the Khronos Group. To do so, perform the following steps.
+GitHub repository</a> and follow the build instructions there.
 </p>
 
-<ol style="1">
-<li>
-Clone the Vulkan directory by entering the following command in your terminal window:
-
-<pre class="no-pretty-print">
-$ git clone git@github.com:KhronosGroup/Vulkan-LoaderAndValidationLayers.git
-</pre>
-
-<p class="note"><strong>Note: </strong>You must have a private SSH key associated with
-GitHub, or this command fails with a {@code Permission denied (publickey)} message.</p>
-</li>
-
-<li>
-Navigate to the directory containing the layer source code, and
-check out the repo's stable Android branch, called {@code android_layers}:
-
-<pre class="no-pretty-print">
-$ cd Vulkan-LoaderAndValidationLayers
-$ git checkout android_layers
-</pre>
-</li>
-
-<li>
-Begin preparation for building by entering the following commands on the command line:
-<ul>
-   <li>For Linux or OS X:
-   <ul>
-      <li>
-      <pre class="no-pretty-print">
-$ cd build-android
-$ ./android-generate</pre>
-      </li>
-   </ul>
-   </li>
-
-   <li>For Windows:
-   <ul>
-      <li>
-<pre class="no-pretty-print">
-&gt; cd build-android
-&gt; android-generate.bat</pre>
-      </li>
-   </ul>
-   </li>
-</ul>
-</li>
-
-<li>
-Continue by following the build instructions for your platform.
-These instructions are in the {@code BUILD.md} file contained in the local instance of the
-repository you cloned.
-</li>
-</ul>
-
-</ol>
-
-<h3 id="ias">Android Studio Integration</h3>
-<p>
-Android Studio builds the validation layers when it builds the rest of the app.
-This flow makes it easier for you to trace through the layers at runtime. Each layer's
-source code corresponds to a single Gradle project, which you can specify directly in your Android
-Studio app. For example, there is a {@code build.gradle} project for threading, and another
-one for parameter validation.
-</p>
-
-<h4 id="asbl">Building layers</h4>
-
-<p>
-To integrate layers directory into Android Studio application, perform these steps:
-</p>
-<li>
-Add layers to your Android Studio application's project by specifying their corresponding
-Gradle projects in {@code settings.gradle}, which is normally a peer to app directory.
-The following example shows how to do this, based on the assumption that you're
-<a href="#ftn">using the {@code build.gradle} files from the NDK</a>.
-
-<pre>
-// configure your path to the source code generated on your machine
-def layerProjRoot = file('/path/to/ndk-root/.../build-android/generated/gradle-build')
-String[] layers = ['threading',
-                   'parameter_validation',
-                   'object_tracker',
-                   'core_validation',
-                   'device_limits',
-                   'image',
-                   'swapchain',
-                   'unique_objects']
-for (layer in layers) {
-    include ":"+ layer
-    project(":" + layer.toString()).projectDir = new File("${layerProjRoot}/${layer}")
-}
-</pre>
-</li>
-
-Your next step is to provide the built layers to the app by installing them.
-
-<h4 id="asil">Installing layers</h4>
-
-<li>
-To install your layers, add the layer Gradle projects to your application's jniLibs dependencies
-in your {@code build.gradle} module. This module normally resides under the {@code app/} directory.
-The following example shows how to do this:
-
-<pre>
-android.sources {
-    main {
-        jni { ... }
-        jniLibs {
-            dependencies {
-                project ":threading"
-                project ":parameter_validation"
-                project ":object_tracker"
-                project ":core_validation"
-                project ":device_limits"
-                project ":image"
-                project ":swapchain"
-                project ":unique_objects"
-            }
-        }
-    }
-} // android.sources
-</pre>
-</li>
-<li>
-Develop, build, and debug as you usually would. When you build, Android Studio automatically
-builds the layers and copies them into your APK.
-</li>
-<li>
-Debug your application. Android Studio allows you to trace through the layer source code.
-</li>
-<li>
-For best performance, remove the layers before you do your release build.
-</li>
-</ol>
-
-
-<h3 id="cli">From the Command Line</h3>
-
-This section explains how to build and install your layers if your project does not use
-Android Studio.
-
-<h4 id="clibl">Building layers</h4>
-
-<p>
-To build validation layers on Linux or OS X, enter these commands on the command line:
-</p>
-<ul>
-<li>
-Using Gradle:
-<pre class="no-pretty-print">
-$ cd generated/gradle-build
-$ # configure SDK and NDK path in local.properties
-$ gradlew assembleAllDebug
-</pre>
-</li>
-<li>
-Using Android makefiles:
-<pre class="no-pretty-print">
-$ ndk-build</pre>
-</li>
-</ul>
-
-<p>
-To build validation layers on Windows, enter these commands on the command line:
-</p>
-<ul>
-<li>
-Using Gradle:
-<pre class="no-pretty-print">
-&gt; cd generated\gradle-build
-&gt; REM configure SDK and NDK path in local.properties
-&gt; gradlew.bat assembleAllDebug
-</pre>
-</li>
-<li>
-Using Android makefiles:
-<pre class="no-pretty-print">
-&gt; ndk-build.cmd
-</pre>
-</li>
-</ul>
-
-
-
-</p>
-</li>
-</ol>
-
-<h4 id="cliil">Installing layers</h4>
-
-<p>
-After building the layers, you must provide them to your app. To do so, you must first
-create a {@code jniLibs} folder in your app's project directory under
-{@code ./src/main/}, and copy the libs to it. The following example shows how to do this.
-</p>
-
-<pre class="no-pretty-print">
-$ mkdir ./src/main/jniLibs
-</pre>
-
-<p>
-The next step depends on whether you are using Gradle or Android makefiles. If you're using
-Gradle, each built layer resides in its own directory. Consolidate the layers into a single
-directory, as the following example shows:
-</p>
-
-<pre class="no-pretty-print">
-$ cp -r .../build-android/generated/gradle-build/threading/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/parameter_validation/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/object_tracker/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/core_validation/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/device_limits/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/image/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/swapchain/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-$ cp -r .../build-android/generated/gradle-build/unique_objects/build/outputs/native/debug/all/lib/* ./src/main/jniLibs/
-</pre>
-
-If you're using Android makefiles, the built layers reside in {@code lib} folders,
-with one {@code lib} folder under each architecture’s root directory. Consolidate the
-makefiles under the {@code jniLibs} directory as this example shows:
-</p>
-<pre class="no-pretty-print">
-$ cp -r .../build-android/libs/* ./src/main/jniLibs/
-</pre>
-</li>
-</ol>
-
 <h2 id="verifying">Verifying Layer Build</h2>
 
 <p>
-Regardless of whether you build using Gradle or Android makefiles, the build process produces
-a file structure like the following:
+Regardless of whether you build with NDK's prebuilt layers or you build from the latest source code,
+the build process produces final file structure like the following:
 </p>
 
 <pre class="no-pretty-print">
@@ -571,6 +382,7 @@
 
 </pre>
 
+<p>
 Once your app has registered and enabled the debug callback, the system routes debugging
 messages to a callback that you register. An example of such a callback appears below:
 </p>
diff --git a/docs/html/preview/_book.yaml b/docs/html/preview/_book.yaml
index 0d4b81b..ad67249 100644
--- a/docs/html/preview/_book.yaml
+++ b/docs/html/preview/_book.yaml
@@ -220,6 +220,8 @@
       value: TV 录制
     - name: zh-tw-lang
       value: 電視錄製
+  - title: Key Attestation
+    path: /preview/features/key-attestation.html
   - title: Network Security Configuration
     path: /preview/features/security-config.html
     path_attributes:
diff --git a/docs/html/preview/api-overview.jd b/docs/html/preview/api-overview.jd
index d457d5c..4abd956 100644
--- a/docs/html/preview/api-overview.jd
+++ b/docs/html/preview/api-overview.jd
@@ -701,48 +701,37 @@
 For more information, see <a href="{@docRoot}preview/features/direct-boot.html">Direct Boot</a>.</p>
 </p>
 
-
 <h2 id="key_attestation">Key Attestation</h2>
 
-<p>Hardware-backed keystores provide a much safer method to create, store,
-and use cryptographic keys on Android devices. They protect keys from the
-Linux kernel, potential Android vulnerabilities, and extraction
-from rooted devices.</p>
+<p>
+  Android N introduces <em>key attestation</em>, a new security tool that helps
+  you make sure that the key pairs stored within a device's <a class=
+  "external-link" href=
+  "https://source.android.com/security/keystore/"><em>hardware-backed
+  keystore</em></a> properly protect the sensitive information that your app
+  uses. By using this tool, you gain additional confidence that your app
+  interacts with keys that reside in secure hardware, even if the device
+  running your app is rooted. If you use keys from the hardware-backed keystore
+  in your apps, you should use this tool, particularly if you use the keys to
+  verify sensitive information within your app.
+</p>
 
-<p>To make it easier and more secure to use hardware-backed keystores,
-Android N introduces Key Attestation. Apps and off-devices can use Key
-Attestation to strongly determine whether an RSA or EC key pair is
-hardware-backed, what the properties of the key pair are, and what
-  constraints are applied to its usage and validity. </p>
+<p>
+  Key attestation allows you to verify that an RSA or EC key pair has been
+  created and stored in a device’s hardware-backed keystore within the device’s
+  trusted execution environment (TEE). The tool also allows you to use an
+  off-device service, such as your app's back-end server, to determine and
+  strongly verify the uses and validity of the key pair. These features provide
+  an additional level of security that protects the key pair, even if someone
+  roots the device or compromises the security of the Android platform running
+  on the device.
+</p>
 
-<p>Apps and off-device services can request information about a key pair
-through an X.509 attestation certificate which must be signed by a valid
-attestation key. The attestation key is an ECDSA signing key which is
-injected into the device’s hardware-backed keystore at the factory.
-Therefore, an attestation certificate signed by a valid attestation
-key confirms the existence of a hardware-backed keystore, along with
-  details of key pairs in that keystore.</p>
-
-<p>To ensure that the device is using a secure, official Android factory
-image, Key Attestation requires that the device <a
-class="external-link"
-href="https://source.android.com/security/verifiedboot/verified-boot.html#bootloader_requirements">bootloader</a>
-provide the following information to the <a class="external-link"
-href="https://source.android.com/security/trusty/index.html">Trusted
-Execution Environment (TEE)</a>:</p>
-
-<ul>
-<li>The OS version and patch level installed on the device</li>
-<li>The <a href="https://source.android.com/security/verifiedboot/index.html"
-class="external-link" >Verified Boot</a> public key and lock status</li>
-  </ul>
-
-<p>For more information about the hardware-backed keystore feature,
-see the guide for <a href="https://source.android.com/security/keystore/"
-class="external-link">Hardware-backed Keystore</a>.</p>
-
-<p>In addition to Key Attestation, Android N also introduces
-  fingerprint-bound keys that are not revoked on fingerprint enrollment.</p>
+<p>
+  For more information, see the
+  <a href="{@docRoot}preview/features/key-attestation.html">Key Attestation</a>
+  developer documentation.
+</p>
 
 <h2 id="network_security_config">Network Security Config</h2>
 
@@ -854,18 +843,26 @@
 <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="sustained_performance_api">Sustained Performance API</h2>
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/key-attestation.jd b/docs/html/preview/features/key-attestation.jd
new file mode 100644
index 0000000..98b8340
--- /dev/null
+++ b/docs/html/preview/features/key-attestation.jd
@@ -0,0 +1,845 @@
+page.title=Key Attestation
+page.metaDescription=New support in Android N for verifying security properties of hardware-backed keys.
+page.keywords="android N", "security", "TEE", "hardware-backed", "keystore", "certificate", "key attestation"
+
+@jd:body
+
+<div id="qv-wrapper">
+  <div id="qv">
+    <h2>In this document</h2>
+      <ol>
+        <li><a href="#verifying">Retrieving and Verifying a Hardware-backed Key Pair</a></li>
+        <li><a href="#certificate_schema">Certificate Extension Data Schema</a></li>
+      </ol>
+  </div>
+</div>
+
+<p>
+  Key Attestation gives you more confidence that the keys you use in your app
+  are stored in a device's hardware-backed keystore. The following sections
+  describe how to verify the properties of hardware-backed keys and how to
+  interpret the schema of the attestation certificate's extension data.
+</p>
+
+<h2 id="verifying">
+  Retrieving and Verifying a Hardware-backed Key Pair
+</h2>
+
+<p>
+  During key attestation, you specify the alias of a key pair. The attestation
+  tool, in return, provides a certificate chain, which you can use to verify
+  the properties of that key pair.
+</p>
+
+<p>
+  The root certificate within this chain is signed using an attestation key,
+  which the device manufacturer injects into the device’s hardware-backed
+  keystore at the factory.
+</p>
+
+<p class="note">
+  <strong>Note:</strong> On devices that ship with Android N and Google Play
+  services, the root certificate is issued by Google. You should verify that
+  this root certificate appears within Google’s list of root certificates.
+</p>
+
+<p>
+  To implement key attestation, complete the following steps:
+</p>
+
+<ol>
+  <li>
+    Use a {@link java.security.KeyStore KeyStore} object's
+    {@link java.security.KeyStore#getCertificateChain getCertificateChain()}
+    method to get a reference to the chain of X.509 certificates associated with
+    the hardware-backed keystore.
+  </li>
+
+  <li>
+    <p>
+      Check each certificate’s validity using a
+      {@link java.security.cert.CRL CRL} object's
+      {@link java.security.cert.CRL#isRevoked isRevoked()} method.
+    </p>
+
+    <p class="caution">
+      <strong>Caution:</strong> Although you can complete this process within
+      your app directly, it’s safer to check the certificates’ revocation lists
+      on a separate server that you trust.
+    </p>
+  </li>
+
+  <li>
+    <p>
+      Create an <code>Attestation</code> object, passing in the first element of
+      the certificate chain as an argument:</p>
+
+<pre>
+// "certificates" contains the certificate chain associated with a specific key
+// pair in the device's hardware-backed keystore.
+X509Certificate attestationCert = (X509Certificate) certificates[0];
+Attestation hardwareKeyAttestation = new Attestation(attestationCert);
+</pre>
+
+    <p>
+      An attestation object extracts the extension data within this certificate
+      and stores this information in a more accessible format. For more details
+      about the schema of the extension data, see <a href=
+      "#certificate_schema">Certificate Extension Data Schema</a>.
+    </p>
+  </li>
+
+  <li>
+    <p>
+      Use the accessor methods within the <code>Attestation</code> class to
+      retrieve the extension data from the certificate. These methods use the
+      same names and structure hierarchy as in the certificate extension data
+      schema.
+    </p>
+
+    <p>
+      For example, to view the verified boot key for the device’s TEE, use the
+      following method sequence:
+    </p>
+
+<pre>
+// "hardwareKeyAttestation" contains the first element of the attestation
+// certificate chain.
+AuthorizationList teeAuthList = hardwareKeyAttestation.getTeeEnforced();
+RootOfTrust teeRootOfTrust = teeAuthList.getRootOfTrust();
+byte[] teeVerifiedBootKey = teeRootOfTrust.getVerifiedBootKey();
+</pre>
+
+  </li>
+
+  <li>
+    <p>
+      Compare the extension data from the <code>Attestation</code> object with
+      the set of values that you expect the hardware-backed key to contain.
+    </p>
+
+    <p class="caution">
+      <strong>Caution:</strong> Although you can complete this process within
+      your app directly, it’s safer to check the certificate’s extension data
+      on a separate server that you trust.
+    </p>
+  </li>
+</ol>
+
+<h2 id="certificate_schema">
+  Certificate Extension Data Schema
+</h2>
+
+<p>
+  Key attestation verifies the extension data that appears in the first
+  certificate within the chain in a device’s hardware-backed keystore. The
+  certificate stores the information according to the following ASN.1 schema:
+</p>
+
+<pre class="no-pretty-print">
+KeyDescription ::= SEQUENCE {
+    attestationVersion  INTEGER,
+    attestationSecurityLevel  SecurityLevel,
+    keymasterVersion  INTEGER,
+    keymasterSecurityLevel  SecurityLevel,
+    attestationChallenge  OCTET_STRING,
+    <var>reserved  OCTET_STRING</var>,
+    softwareEnforced  AuthorizationList,
+    teeEnforced  AuthorizationList,
+}
+
+SecurityLevel ::= ENUMERATED {
+    Software  (0),
+    TrustedEnvironment  (1),
+}
+
+AuthorizationList ::= SEQUENCE {
+    purpose  [1] EXPLICIT SET OF INTEGER OPTIONAL,
+    algorithm  [2] EXPLICIT INTEGER OPTIONAL,
+    keySize  [3] EXPLICIT INTEGER OPTIONAL,
+    digest  [5] EXPLICIT SET OF INTEGER OPTIONAL,
+    padding  [6] EXPLICIT SET OF INTEGER OPTIONAL,
+    ecCurve  [10] EXPLICIT INTEGER OPTIONAL,
+    rsaPublicExponent  [200] EXPLICIT INTEGER OPTIONAL,
+    activeDateTime  [400] EXPLICIT INTEGER OPTIONAL,
+    originationExpireDateTime  [401] EXPLICIT INTEGER OPTIONAL,
+    usageExpireDateTime  [402] EXPLICIT INTEGER OPTIONAL,
+    noAuthRequired  [503] EXPLICIT NULL OPTIONAL,
+    userAuthType  [504] EXPLICIT INTEGER OPTIONAL,
+    authTimeout  [505] EXPLICIT INTEGER OPTIONAL,
+    allowWhileOnBody  [506] EXPLICIT NULL OPTIONAL,
+    allApplications  [600] EXPLICIT NULL OPTIONAL,
+    applicationId  [601] EXPLICIT OCTET_STRING OPTIONAL,
+    creationDateTime  [701] EXPLICIT INTEGER OPTIONAL,
+    origin  [702] EXPLICIT INTEGER OPTIONAL,
+    rollbackResistant  [703] EXPLICIT NULL OPTIONAL,
+    rootOfTrust  [704] EXPLICIT RootOfTrust OPTIONAL,
+    osVersion  [705] EXPLICIT INTEGER OPTIONAL,
+    osPatchLevel  [706] EXPLICIT INTEGER OPTIONAL,
+    attestationChallenge  [708] EXPLICIT INTEGER OPTIONAL,
+    attestationApplicationId  [709] EXPLICIT OCTET_STRING OPTIONAL,
+}
+
+RootOfTrust ::= SEQUENCE {
+    verifiedBootKey  OCTET_STRING,
+    deviceLocked  BOOLEAN,
+    verifiedBootState  VerifiedBootState,
+}
+
+VerifiedBootState ::= ENUMERATED {
+    Verified  (0),
+    SelfSigned  (1),
+    Unverified  (2),
+    Failed  (3),
+}
+</pre>
+
+<p>
+  The following list presents a description of each element within the schema:
+</p>
+
+<h3 id="certificate_schema_keydescription">
+  KeyDescription
+</h3>
+
+<p>
+  This sequence of values presents general information about the key pair being
+  verified through key attestation and provides easy access to additional
+  details.
+</p>
+
+<dl>
+  <dt>
+    <code>attestationVersion</code>
+  </dt>
+
+  <dd>
+    The version of the key attestation feature. Should be set to 1.
+  </dd>
+
+  <dt>
+    <code>attestationSecurity</code>
+  </dt>
+
+  <dd>
+    <p>
+      The <a href="#certificate_schema_securitylevel">security
+      level</a> of the attestation.
+    </p>
+
+    <p class="note">
+      <strong>Note:</strong> Although it is possible to attest keys that are
+      stored in the Android system&mdash;that is, if the
+      <code>attestationSecurity</code> value is set to Software&mdash;you
+      cannot trust these attestations if the Android system becomes compromised.
+    </p>
+  </dd>
+
+  <dt>
+    <code>keymasterVersion</code>
+  </dt>
+
+  <dd>
+    The version of the Keymaster hardware abstraction layer (HAL). Use 0 to
+    represent version 0.2 or 0.3, 1 to represent version 1.0, and 2 to represent
+    version 2.0.
+  </dd>
+
+  <dt>
+    <code>keymasterSecurity</code>
+  </dt>
+
+  <dd>
+    The <a href="#certificate_schema_securitylevel">security
+    level</a> of the Keymaster implementation.
+  </dd>
+
+  <dt>
+    <code>attestationChallenge</code>
+  </dt>
+
+  <dd>
+    The challenge string associated with a key pair that is verified using key
+    attestation.
+  </dd>
+
+  <dt>
+    <code><var>reserved</var></code>
+  </dt>
+
+  <dd>
+    Only system apps use this value. In all other apps, this value is empty.
+  </dd>
+
+  <dt>
+    <code>softwareEnforced</code>
+  </dt>
+
+  <dd>
+    Optional. The Keymaster <a href=
+    "#certificate_schema_authorizationlist">authorization
+    list</a> that is enforced by the Android system, not by the device’s TEE.
+  </dd>
+
+  <dt>
+    <code>teeEnforced</code>
+  </dt>
+
+  <dd>
+    Optional. The Keymaster <a href=
+    "#certificate_schema_authorizationlist">authorization
+    list</a> that is enforced by the device’s TEE.
+  </dd>
+</dl>
+
+<h3 id="certificate_schema_securitylevel">
+  SecurityLevel
+</h3>
+
+<p>
+  This data structure indicates the extent to which a software feature, such as
+  a key pair, is protected based on its location within the device.
+</p>
+
+<p>
+  Because the data structure is an enumeration, it takes on exactly one of the
+  following values:
+</p>
+
+<dl>
+  <dt>
+    Software
+  </dt>
+
+  <dd>
+    The logic for creating and managing the feature is implemented in the
+    Android system. For the purposes of creating and storing key pairs, this
+    location is less secure than the TEE but is more secure than your app's
+    process space.
+  </dd>
+
+  <dt>
+    TrustedEnvironment
+  </dt>
+
+  <dd>
+    The logic for creating and managing the feature is implemented in secure
+    hardware, such as a TEE. For the purposes of creating and storing key pairs,
+    this location is more secure because secure hardware is highly resistant to
+    remote compromise.
+  </dd>
+</dl>
+
+<h3 id="certificate_schema_authorizationlist">
+  AuthorizationList
+</h3>
+
+<p>
+  This data structure contains the key pair’s properties themselves, as defined
+  in the Keymaster hardware abstraction layer (HAL). You compare these values
+  to the device’s current state or to a set of expected values to verify that a
+  key pair is still valid for use in your app.
+</p>
+
+<p>
+  Each field name corresponds to a similarly-named Keymaster tag. For example,
+  the <code>keySize</code> field in an authorization list corresponds to the
+  <code>KM_TAG_KEY_SIZE</code> Keymaster tag.
+</p>
+
+<p>
+  Each field in the following list is optional:
+</p>
+
+<dl>
+  <dt>
+    <code>purpose</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_purpose">
+    KM_TAG_PURPOSE</a></code> Keymaster tag, which uses a tag ID value of 1.
+  </dd>
+
+  <dt>
+    <code>algorithm</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code><a href=
+      "https://source.android.com/security/keystore/implementer-ref.html#km_tag_algorithm">
+      KM_TAG_ALGORITHM</a></code> Keymaster tag, which uses a tag ID value of
+      2.
+    </p>
+
+    <p>
+      When an <code>AuthorizationList</code> object is associated with key
+      attestation, this value is always <code>KM_ALGORITHM_RSA</code> or
+      <code>KM_ALGORITHM_EC</code>.
+    </p>
+  </dd>
+
+  <dt>
+    <code>keySize</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_key_size">
+    KM_TAG_KEY_SIZE</a></code> Keymaster tag, which uses a tag ID value of 3.
+  </dd>
+
+  <dt>
+    <code>digest</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_digest">
+    KM_TAG_DIGEST</a></code> Keymaster tag, which uses a tag ID value of 5.
+  </dd>
+
+  <dt>
+    <code>padding</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_padding">
+    KM_TAG_PADDING</a></code> Keymaster tag, which uses a tag ID value of 6.
+  </dd>
+
+  <dt>
+    <code>ecCurve</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_EC_CURVE</code> Keymaster tag, which uses
+      a tag ID value of 10.
+    </p>
+
+    <p>
+      The set of parameters used to generate an elliptic curve (EC) key pair,
+      which uses ECDSA for signing and verification, within the Android system
+      keystore.
+    </p>
+  </dd>
+
+  <dt>
+    <code>rsaPublicExponent</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_rsa_public_exponent">
+    KM_TAG_RSA_PUBLIC_EXPONENT</a></code> Keymaster tag, which uses a tag ID
+    value of 200.
+  </dd>
+
+  <dt>
+    <code>activeDateTime</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_active_datetime">
+    KM_TAG_ACTIVE_DATETIME</a></code> Keymaster tag, which uses a tag ID value
+    of 400.
+  </dd>
+
+  <dt>
+    <code>originationExpireDateTime</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_origination_expire_datetime">
+    KM_TAG_ORIGINATION_EXPIRE_DATETIME</a></code> Keymaster tag, which uses a
+    tag ID value of 401.
+  </dd>
+
+  <dt>
+    <code>usageExpireDateTime</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_usage_expire_datetime">
+    KM_TAG_USAGE_EXPIRE_DATETIME</a></code> Keymaster tag, which uses a tag ID
+    value of 402.
+  </dd>
+
+  <dt>
+    <code>noAuthRequired</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code><a href=
+      "https://source.android.com/security/keystore/implementer-ref.html#km_tag_no_auth_required">
+      KM_TAG_NO_AUTH_REQUIRED</a></code> Keymaster tag, which uses a tag ID
+      value of 503.
+    </p>
+
+    <p>
+      When an <code>AuthorizationList</code> object is associated with key
+      attestation, this value is always true.
+    </p>
+  </dd>
+
+  <dt>
+    <code>userAuthType</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_user_auth_type">
+    KM_TAG_USER_AUTH_TYPE</a></code> Keymaster tag, which uses a tag ID value
+    of 504.
+  </dd>
+
+  <dt>
+    <code>authTimeout</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_auth_timeout">
+    KM_TAG_AUTH_TIMEOUT</a></code> Keymaster tag, which uses a tag ID value of
+    505.
+  </dd>
+
+  <dt>
+    <code>allowWhileOnBody</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_ALLOW_WHILE_ON_BODY</code> Keymaster tag,
+      which uses a tag ID value of 506.
+    </p>
+
+    <p>
+      Allows the key to be used after its authentication timeout period if the
+      user is still wearing the device on their body. Note that a secure
+      on-body sensor determines whether the device is being worn on the user’s
+      body.
+    </p>
+
+    <p>
+      When an <code>AuthorizationList</code> object is associated with key
+      attestation, this value is always true.
+    </p>
+  </dd>
+
+  <dt>
+    <code>allApplications</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_ALL_APPLICATIONS</code> Keymaster tag,
+      which uses a tag ID value of 600.
+    </p>
+
+    <p>
+      Indicates whether all apps on a device can access the key pair.
+    </p>
+
+    <p>
+      When an <code>AuthorizationList</code> object is associated with key
+      attestation, this value is always true.
+    </p>
+  </dd>
+
+  <dt>
+    <code>applicationId</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_application_id">
+    KM_TAG_APPLICATION_ID</a></code> Keymaster tag, which uses a tag ID value
+    of 601.
+  </dd>
+
+  <dt>
+    <code>creationDateTime</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_creation_datetime">
+    KM_TAG_CREATION_DATETIME</a></code> Keymaster tag, which uses a tag ID
+    value of 701.
+  </dd>
+
+  <dt>
+    <code>origin</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code><a href=
+      "https://source.android.com/security/keystore/implementer-ref.html#km_tag_origin">
+      KM_TAG_ORIGIN</a></code> Keymaster tag, which uses a tag ID value of 702.
+    </p>
+
+    <p>
+      When an <code>AuthorizationList</code> object is associated with key
+      attestation, this value is usually set to
+      <code>KM_ORIGIN_GENERATED</code>. If the attestation uses Keymaster
+      version 0.2 or 0.3, however, the origin may be set to
+      <code>KM_ORIGIN_UNKNOWN</code> instead.
+    </p>
+  </dd>
+
+  <dt>
+    <code>rollbackResistant</code>
+  </dt>
+
+  <dd>
+    Corresponds to the <code><a href=
+    "https://source.android.com/security/keystore/implementer-ref.html#km_tag_rollback_resistant">
+    KM_TAG_ROLLBACK_RESISTANT</a></code> Keymaster tag, which uses a tag ID
+    value of 703.
+  </dd>
+
+  <dt>
+    <code>rootOfTrust</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code><a href=
+      "https://source.android.com/security/keystore/implementer-ref.html#km_tag_root_of_trust">
+      KM_TAG_ROOT_OF_TRUST</a></code> Keymaster tag, which uses a tag ID value
+      of 704.
+    </p>
+
+    <p>
+      For more details, see the section describing the <code><a href=
+      "#certificate_schema_rootoftrust">RootOfTrust</a></code>
+      data structure.
+    </p>
+  </dd>
+
+  <dt>
+    <code>osVersion</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_OS_VERSION</code> Keymaster tag, which
+      uses a tag ID value of 705.
+    </p>
+
+    <p>
+      The version of the Android operating system associated with the
+      Keymaster, specified as a six-digit integer. For example, version 6.0.1
+      is represented as 060001.
+    </p>
+
+    <p>
+      Only Keymaster version 1.0 or higher includes this value in the
+      authorization list.
+    </p>
+  </dd>
+
+  <dt>
+    <code>osPatchLevel</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_PATCHLEVEL</code> Keymaster tag, which
+      uses a tag ID value of 706.
+    </p>
+
+    <p>
+      The month and year associated with the security patch that is being used
+      within the Keymaster, specified as a six-digit integer. For example, the
+      June 2016 patch is represented as 201606.
+    </p>
+
+    <p>
+      Only Keymaster version 1.0 or higher includes this value in the
+      authorization list.
+    </p>
+  </dd>
+
+  <dt>
+    <code>attestationChallenge</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_ATTESTATION_CHALLENGE</code> Keymaster
+      tag, which uses a tag ID value of 708.
+    </p>
+
+    <p>
+      The challenge string associated with the key pair that is defined in the
+      Keymaster.
+    </p>
+  </dd>
+
+  <dt>
+    <code>attestationApplicationId</code>
+  </dt>
+
+  <dd>
+    <p>
+      Corresponds to the <code>KM_TAG_ATTESTATION_APPLICATION_ID</code>
+      Keymaster tag, which uses a tag ID value of 709.
+    </p>
+
+    <p>
+      The unique ID of the attestation certificate that signed the key pair
+      that is in the Keymaster.
+    </p>
+  </dd>
+</dl>
+
+<h3 id="certificate_schema_rootoftrust">
+  RootOfTrust
+</h3>
+
+<p>
+  This collection of values defines key information about the device’s status.
+</p>
+
+<p>
+  Each field in the following list is required:
+</p>
+
+<dl>
+  <dt>
+    <code>verifiedBootKey</code>
+  </dt>
+
+  <dd>
+    <p>
+      A secure hash of the key that verifies the system image. It is recommended
+      that you use the SHA-256 algorithm for this hash.
+    </p>
+  </dd>
+
+  <dt>
+    <code>deviceLocked</code>
+  </dt>
+
+  <dd>
+    True if the device’s bootloader is locked, which enables Verified Boot
+    checking and prevents an unsigned device image from being flashed onto the
+    device. For more information about this feature, see the <a class=
+    "external-link" href=
+    "https://source.android.com/security/verifiedboot/verified-boot.html">Verifying
+    Boot</a> documentation.
+  </dd>
+
+  <dt>
+    <code>verifiedBootState</code>
+  </dt>
+
+  <dd>
+    The <a href="#certificate_schema_verifiedbootstate">boot
+    state</a> of the device, according to the Verified Boot feature.
+  </dd>
+
+  <dt>
+    <code>osVersion</code>
+  </dt>
+
+  <dd>
+    The current version of the Android operating system on the device,
+    specified as a six-digit integer. For example, version 6.0.1 is represented
+    as 060001.
+  </dd>
+
+  <dt>
+    <code>patchMonthYear</code>
+  </dt>
+
+  <dd>
+    The month and year associated with the security patch that is currently
+    installed on the device, specified as a six-digit integer. For example, the
+    June 2016 patch is represented as 201606.
+  </dd>
+</dl>
+
+<h3 id="certificate_schema_verifiedbootstate">
+  VerifiedBootState
+</h3>
+
+<p>
+  This data structure provides the device’s current boot state, which
+  represents the level of protection provided to the user and to apps after the
+  device finishes booting. For more information about this feature, see the
+  <a class="external-link" href=
+  "https://source.android.com/security/verifiedboot/verified-boot.html#boot_state">
+  Boot State</a> section within the Verifying Boot documentation.
+</p>
+
+<p>
+  This data structure is an enumeration, so it takes on exactly one of the
+  following values:
+</p>
+
+<dl>
+  <dt>
+    Verified
+  </dt>
+
+  <dd>
+    <p>
+      Indicates a full chain of trust, which includes the bootloader, the boot
+      partition, and all verified partitions.
+    </p>
+
+    <p>
+      When the device is in this boot state, the <code>verifiedBootKey</code> is
+      the hash of the device-embedded certificate, which the device manufacturer
+      adds to the device's ROM at the factory.
+    </p>
+  </dd>
+
+  <dt>
+    SelfSigned
+  </dt>
+
+  <dd>
+    <p>
+      Indicates that the device-embedded certificate has verified the device’s
+      boot partition and that the signature is valid.
+    </p>
+
+    <p>
+      When the device is in this boot state, the <code>verifiedBootKey</code> is
+      the hash of a user-installed certificate, which signs a boot partition
+      that the user adds to the device in place of the original,
+      manufacturer-provided boot partition.
+    </p>
+  </dd>
+
+  <dt>
+    Unverified
+  </dt>
+
+  <dd>
+    Indicates that the user can modify the device freely. Therefore, the user is
+    responsible for verifying the device’s integrity.
+  </dd>
+
+  <dt>
+    Failed
+  </dt>
+
+  <dd>
+    Indicates that the device has failed verification. The attestation
+    certificate should never use this value for <code>VerifiedBootState</code>.
+  </dd>
+</dl>
diff --git a/docs/html/preview/features/multi-window.jd b/docs/html/preview/features/multi-window.jd
index a4f389a..ca5bd0d 100644
--- a/docs/html/preview/features/multi-window.jd
+++ b/docs/html/preview/features/multi-window.jd
@@ -471,7 +471,7 @@
   </dd>
 
   <dt>
-    <code>Activity.requestDropPermissions()</code>
+    <code>Activity.requestDragAndDropPermissions()</code>
   </dt>
 
   <dd>
diff --git a/docs/html/preview/index.jd b/docs/html/preview/index.jd
index 918de48..0b21e68 100644
--- a/docs/html/preview/index.jd
+++ b/docs/html/preview/index.jd
@@ -114,7 +114,24 @@
     data-initial-results="3"></div>
 </div></section>
 
-<section class="dac-section dac-gray"><div class="wrap">
+
+<section class="dac-section dac-gray" id="videos"><div class="wrap">
+  <h1 class="dac-section-title">Videos</h1>
+  <div class="dac-section-subtitle">
+    New Android capabilities and the right way to use them in your apps.
+  </div>
+
+  <div class="resource-widget resource-flow-layout col-16"
+    data-query="collection:preview/landing/videos/first,type:youtube+tag:androidn"
+    data-sortOrder="-timestamp"
+    data-cardSizes="6x6"
+    data-items-per-page="6"
+    data-maxResults="15"
+    data-initial-results="3"></div>
+</div></section>
+
+
+<section class="dac-section dac-light" id="resources"><div class="wrap">
   <h1 class="dac-section-title">Resources</h1>
   <div class="dac-section-subtitle">
     Essential information to help you get your apps ready for Android N.
diff --git a/docs/html/preview/setup-sdk.jd b/docs/html/preview/setup-sdk.jd
index 3b479e2..58ca1d0 100644
--- a/docs/html/preview/setup-sdk.jd
+++ b/docs/html/preview/setup-sdk.jd
@@ -76,6 +76,12 @@
 
 <h3 id="docs-dl">Get the N Preview reference documentation</h3>
 
+<p class="note">
+  <strong>Note:</strong> The N Preview (API level 24) reference documentation
+  is now available online at <a href=
+  "{@docRoot}reference/">developer.android.com/reference/</a>.
+</p>
+
 <p>
   Detailed information about the Android N APIs is available in the N Preview
   reference documentation, which you can download from the following table.
@@ -95,7 +101,7 @@
       >n-preview-3-docs.zip</a></td>
     <td width="100%">
       MD5: 19bcfd057a1f9dd01ffbb3d8ff7b8d81<br>
-      SHA-1: 9224bd4445cd7f653c4c294d362ccb195a2101e7 
+      SHA-1: 9224bd4445cd7f653c4c294d362ccb195a2101e7
     </td>
   </tr>
 </table>
diff --git a/docs/html/training/basics/supporting-devices/languages.jd b/docs/html/training/basics/supporting-devices/languages.jd
index 7d4d474..ba7c016 100644
--- a/docs/html/training/basics/supporting-devices/languages.jd
+++ b/docs/html/training/basics/supporting-devices/languages.jd
@@ -41,7 +41,7 @@
 <p>To add support for more languages, create additional <code>values</code> directories inside
 <code>res/</code> that include a hyphen and the ISO language code at the end of the
 directory name. For example, <code>values-es/</code> is the directory containing simple
-resourcess for the Locales with the language code "es".  Android loads the appropriate resources
+resources for the Locales with the language code "es".  Android loads the appropriate resources
 according to the locale settings of the device at run time. For more information, see
  <a href="{@docRoot}guide/topics/resources/providing-resources.html#AlternativeResources">Providing Alternative Resources</a>.</p>
 
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/testing/performance.jd b/docs/html/training/testing/performance.jd
index 8592c0f..0c0ab7f 100644
--- a/docs/html/training/testing/performance.jd
+++ b/docs/html/training/testing/performance.jd
@@ -437,15 +437,25 @@
 </p>
 
 <ul>
-  <li>Rendering Performance 101
+  <li>
+    <a class="external-link" href="https://www.youtube.com/watch?v=HXQhu6qfTVU">
+      Rendering Performance 101</a>
   </li>
-  <li>Why 60fps?
+  <li>
+    <a class="external-link" href="https://www.youtube.com/watch?v=CaMTIgxCSqU">
+      Why 60fps?</a>
   </li>
-  <li>Android UI and the GPU
+  <li>
+    <a class="external-link" href="https://www.youtube.com/watch?v=WH9AFhgwmDw">
+      Android, UI, and the GPU</a>
   </li>
-  <li>Invalidations Layouts and performance
+  <li>
+    <a class="external-link" href="https://www.youtube.com/watch?v=we6poP0kw6E">
+      Invalidations, Layouts, and Performance</a>
   </li>
-  <li>Analyzing UI Performance with Systrace
+  <li>
+    <a href="{@docRoot}studio/profile/systrace.html">
+      Analyzing UI Performance with Systrace</a>
   </li>
 </ul>
 
diff --git a/docs/html/training/wearables/data-layer/events.jd b/docs/html/training/wearables/data-layer/events.jd
index 9bed9d5..20f219d 100644
--- a/docs/html/training/wearables/data-layer/events.jd
+++ b/docs/html/training/wearables/data-layer/events.jd
@@ -22,21 +22,21 @@
 <h2 id="Wait">Wait for the Status of Data Layer Calls</h2>
 
 <p>You'll notice that calls to the Data Layer API sometimes return a
-<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>,
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>,
 such as
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>.
-As soon as the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> is created,
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.html#putDataItem(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.PutDataRequest)"><code>putDataItem()</code></a>.
+As soon as the <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> is created,
 the operation is queued in the background. If you do nothing else after this, the operation
 eventually completes silently. However, you'll usually want to do something with the result
 after the operation completes, so the
-<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
 lets you wait for the result status, either synchronously or asynchronously.
 </p>
 
 <h3 id="async-waiting">Asynchronous calls</h3>
 <p>If your code is running on the main UI thread, do not make blocking calls
 to the Data Layer API. You can run the calls asynchronously by adding a callback method
-to the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> object,
+to the <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a> object,
 which fires when the operation is completed:</p>
 <pre>
 pendingResult.setResultCallback(new ResultCallback&lt;DataItemResult&gt;() {
@@ -51,12 +51,12 @@
 
 <h3 id="sync-waiting">Synchronous calls</h3>
 <p>If your code is running on a separate handler thread in a background service (which is the case
-in a <a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>),
+in a <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html"><code>WearableListenerService</code></a>),
 it's fine for the calls to block. In this case, you can call
-<a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html#await()"><code>await()</code></a>
-on the <a href="{@docRoot}reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html#await()"><code>await()</code></a>
+on the <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/PendingResult.html"><code>PendingResult</code></a>
 object, which blocks until the request completes and returns a
-<a href="{@docRoot}reference/com/google/android/gms/common/api/Result.html"><code>Result</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/Result.html"><code>Result</code></a>
 object:
 </p>
 
@@ -79,7 +79,7 @@
 </p>
 <ul>
    <li>Create a service that extends <a href
-="https://developer.android.com/reference/com/google/android/gms/wearable/WearableListenerService.html">
+="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html">
 {@code WearableListenerService}</a>.</li>
    <li>Create an activity that implements <a
 href="https://developer.android.com/reference/com/google/android/gms/wearable/DataApi.DataListener.html">
@@ -215,7 +215,7 @@
 
 <p>
 An intent filter for the
-<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html">
 {@code WearableListenerService}</a> example shown in the previous section might look like this:
 
 <pre>
@@ -250,14 +250,14 @@
 or path prefix, you must specify a wildcard or specific host.
 If you do not do so, the system ignores the path you specified.
 </p>
+
 <p>
 For more information on the filter types that Wear supports, see the
 API reference documentation for <a
 href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService">
 {@code WearableListenerService}</a>.
-
-
 </p>
+
 <p>
 For more information on data filters and matching rules, see the API reference
 documentation for the <a
@@ -265,7 +265,6 @@
 manifest element.
 </p>
 
-
 <p>When matching intent filters, there are two important rules to remember:</p>
 <ul>
     <li>If a scheme is not specified for the intent filter, the system ignores
@@ -282,10 +281,10 @@
 implementing one or more of the following interfaces:
 </p>
 <ul>
-  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>
+  <li><a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>
   DataApi.DataListener</code></a></li>
 
-  <li><a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.MessageListener.html">
+  <li><a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.MessageListener.html">
   <code>MessageApi.MessageListener</code></a></li>
 
   <li><a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi.CapabilityListener.html">{@code CapabilityApi.CapabilityListener}</a></li>
@@ -295,21 +294,21 @@
 <ol>
 <li>Implement the desired interfaces.</li>
 <li>In {@link android.app.Activity#onCreate onCreate()}, create an instance of
-<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html"><code>GoogleApiClient</code>
 </a>to work with the Data Layer API.</li>
 
 <li>
-In {@link android.app.Activity#onStart onStart()}, call <a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">
+In {@link android.app.Activity#onStart onStart()}, call <a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.html#connect()">
 <code>connect()</code></a> to connect the client to Google Play services.
 </li>
 
 <li>When the connection to Google Play services is established, the system calls
-<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>. This is where you call
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>. This is where you call
 
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)">
+<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()</code></a>,
 
-<a href="{@docRoot}android/reference/com/google/android/gms/wearable/CapabilityApi.CapabilityListener">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener, android.net.Uri, int)">
 <code>MessageApi.addListener()</code></a>, or
 
 <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi.html#addListener(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.wearable.CapabilityApi.CapabilityListener,%20android.net.Uri,%20int)">
@@ -317,14 +316,16 @@
 interested in listening for data layer events.</li>
 
 <li>In {@link android.app.Activity#onStop onStop()}, unregister any listeners with
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.removeListener()</code></a>,
-<a href="{@docRoot}reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.removeListener()</code></a>, or
-<a href="http://developer.android.com/reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient,%20com.google.android.gms.wearable.MessageApi.MessageListener)">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.DataApi.DataListener)"><code>DataApi.removeListener()</code></a>,
+
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.MessageApi.MessageListener)"><code>MessageApi.removeListener()</code></a>, or
+
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/CapabilityApi.html#removeListener(com.google.android.gms.common.api.GoogleApiClient, com.google.android.gms.wearable.CapabilityApi.CapabilityListener)">
 {@code CapabilityApi.removeListener()}</a>.</li>
 
 
 <p>An alternative to adding listeners in
-<a href="{@docRoot}reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/common/api/GoogleApiClient.ConnectionCallbacks.html#onConnected(android.os.Bundle)"><code>onConnected()</code></a>
 and removing them in
 {@link android.app.Activity#onStop onStop()} is to add a filtered listener in an activity’s {@link android.app.Activity#onResume onResume()} and
 remove it in {@link android.app.Activity#onPause onPause()}, so as to only receive data that is relevant to the
@@ -332,18 +333,18 @@
 
 
 <li>Implement
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.DataListener.html#onDataChanged(com.google.android.gms.wearable.DataEventBuffer)">
 <code>onDataChanged()</code></a>,
   <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/MessageApi.MessageListener.html#onMessageReceived(com.google.android.gms.wearable.MessageEvent)">
   <code>onMessageReceived()</code></a>,
   <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html#onCapabilityChanged(com.google.android.gms.wearable.CapabilityInfo)">
 {@code onCapabilityChanged()}</a>,
-or methods from <a href="http://developer.android.com/reference/com/google/android/gms/wearable/ChannelApi.ChannelListener.html">
+or methods from <a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/ChannelApi.ChannelListener.html">
 Channel API listener methods</a>, depending on the interfaces that you implemented.</li>
 </ol>
 
 <p>Here's an example that implements
-<a href="{@docRoot}reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>:</p>
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/DataApi.DataListener.html"><code>DataApi.DataListener</code></a>:</p>
 
 <pre>
 public class MainActivity extends Activity implements
@@ -403,7 +404,7 @@
 <h3>Using Filters with Listener Activities</h3>
 <p>
 Just as you can specify intent filters for manifest-based
-<a href="{@docRoot}reference/com/google/android/gms/wearable/WearableListenerService.html">
+<a href="https://developers.google.com/android/reference/com/google/android/gms/wearable/WearableListenerService.html">
 <code>WearableListenerService</code></a> objects, you can also use intent filters when registering a
 listener through the Wearable API. The same rules are applicable to both
 API-based listeners manifest-based listeners.
@@ -411,7 +412,7 @@
 
 <p>
 A common pattern is to register a listener with a specific path or path prefix
-in an activity’s{@link android.app.Activity#onResume onResume()} method, and to
+in an activity’s {@link android.app.Activity#onResume onResume()} method, and to
 remove the listener in the activity’s {@link android.app.Activity#onPause onPause()} method.
 Implementing listeners in this fashion allows your application to more selectively receive events,
 improving its design and efficiency.
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/Android.mk b/libs/hwui/Android.mk
index faf6a52..c9d4af6 100644
--- a/libs/hwui/Android.mk
+++ b/libs/hwui/Android.mk
@@ -256,6 +256,7 @@
     tests/unit/MatrixTests.cpp \
     tests/unit/OffscreenBufferPoolTests.cpp \
     tests/unit/RenderNodeTests.cpp \
+    tests/unit/RenderPropertiesTests.cpp \
     tests/unit/SkiaBehaviorTests.cpp \
     tests/unit/SnapshotTests.cpp \
     tests/unit/StringUtilsTests.cpp \
diff --git a/libs/hwui/BakedOpRenderer.cpp b/libs/hwui/BakedOpRenderer.cpp
index ea2e15b..6db345a 100644
--- a/libs/hwui/BakedOpRenderer.cpp
+++ b/libs/hwui/BakedOpRenderer.cpp
@@ -66,8 +66,13 @@
             offscreenBuffer->texture.id(), 0);
     GL_CHECKPOINT(LOW);
 
-    LOG_ALWAYS_FATAL_IF(glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE,
-            "framebuffer incomplete!");
+    int status = glCheckFramebufferStatus(GL_FRAMEBUFFER);
+    LOG_ALWAYS_FATAL_IF(status != GL_FRAMEBUFFER_COMPLETE,
+            "framebuffer incomplete, status %d, textureId %d, size %dx%d",
+            status,
+            offscreenBuffer->texture.id(),
+            offscreenBuffer->texture.width(),
+            offscreenBuffer->texture.height());
 
     // Change the viewport & ortho projection
     setViewport(offscreenBuffer->viewportWidth, offscreenBuffer->viewportHeight);
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index cb8e55f..b8a5ce6 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -86,7 +86,9 @@
             ATRACE_FORMAT("Optimize HW Layer DisplayList %s %ux%u",
                     layerNode->getName(), layerNode->getWidth(), layerNode->getHeight());
 
-            const Rect& layerDamage = layers.entries()[i].damage;
+            Rect layerDamage = layers.entries()[i].damage;
+            // TODO: ensure layer damage can't be larger than layer
+            layerDamage.doIntersect(0, 0, layer->viewportWidth, layer->viewportHeight);
             layerNode->computeOrdering();
 
             // map current light center into RenderNode's coordinate space
diff --git a/libs/hwui/RenderNode.cpp b/libs/hwui/RenderNode.cpp
index 6e848fd..be2dab9 100644
--- a/libs/hwui/RenderNode.cpp
+++ b/libs/hwui/RenderNode.cpp
@@ -319,6 +319,8 @@
         transformUpdateNeeded = true;
     } else if (!layerMatchesWidthAndHeight(mLayer, getWidth(), getHeight())) {
 #if HWUI_NEW_OPS
+        // TODO: remove now irrelevant, currently enqueued damage (respecting damage ordering)
+        // Or, ideally, maintain damage between frames on node/layer so ordering is always correct
         RenderState& renderState = mLayer->renderState;
         if (properties().fitsOnLayer()) {
             mLayer = renderState.layerPool().resize(mLayer, getWidth(), getHeight());
diff --git a/libs/hwui/RenderProperties.h b/libs/hwui/RenderProperties.h
index 3952798..696cc29 100644
--- a/libs/hwui/RenderProperties.h
+++ b/libs/hwui/RenderProperties.h
@@ -611,7 +611,9 @@
     bool fitsOnLayer() const {
         const DeviceInfo* deviceInfo = DeviceInfo::get();
         return mPrimitiveFields.mWidth <= deviceInfo->maxTextureSize()
-                        && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize();
+                        && mPrimitiveFields.mHeight <= deviceInfo->maxTextureSize()
+                        && mPrimitiveFields.mWidth > 0
+                        && mPrimitiveFields.mHeight > 0;
     }
 
     bool promotedToLayer() const {
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/libs/hwui/tests/unit/RenderPropertiesTests.cpp b/libs/hwui/tests/unit/RenderPropertiesTests.cpp
new file mode 100644
index 0000000..9001098
--- /dev/null
+++ b/libs/hwui/tests/unit/RenderPropertiesTests.cpp
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <RenderProperties.h>
+
+using namespace android;
+using namespace android::uirenderer;
+
+TEST(RenderProperties, layerValidity) {
+    DeviceInfo::initialize();
+
+    const int maxTextureSize = DeviceInfo::get()->maxTextureSize();
+    ASSERT_LE(2048, maxTextureSize);
+    ASSERT_GT(100000, maxTextureSize);
+
+    RenderProperties props;
+
+    // simple cases that all should fit on layers
+    props.setLeftTopRightBottom(0, 0, 100, 100);
+    ASSERT_TRUE(props.fitsOnLayer());
+    props.setLeftTopRightBottom(100, 2000, 300, 4000);
+    ASSERT_TRUE(props.fitsOnLayer());
+    props.setLeftTopRightBottom(-10, -10, 510, 512);
+    ASSERT_TRUE(props.fitsOnLayer());
+
+    // Too big - can't have layer bigger than max texture size
+    props.setLeftTopRightBottom(0, 0, maxTextureSize + 1, maxTextureSize + 1);
+    ASSERT_FALSE(props.fitsOnLayer());
+
+    // Too small - can't have 0 dimen layer
+    props.setLeftTopRightBottom(0, 0, 100, 0);
+    ASSERT_FALSE(props.fitsOnLayer());
+}
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/CtsShim/Android.mk b/packages/CtsShim/Android.mk
index cd5b288..fa6423e 100644
--- a/packages/CtsShim/Android.mk
+++ b/packages/CtsShim/Android.mk
@@ -53,3 +53,4 @@
 
 include $(BUILD_PREBUILT)
 
+include $(call all-makefiles-under,$(LOCAL_PATH))
diff --git a/packages/CtsShim/build/Android.mk b/packages/CtsShim/build/Android.mk
index b550c1c..bf6ae41 100644
--- a/packages/CtsShim/build/Android.mk
+++ b/packages/CtsShim/build/Android.mk
@@ -17,25 +17,6 @@
 LOCAL_PATH := $(my-dir)
 
 ###########################################################
-# Variant: Privileged app
-
-include $(CLEAR_VARS)
-# this needs to be a privileged application
-LOCAL_PRIVILEGED_MODULE := true
-
-LOCAL_MODULE_TAGS := optional
-LOCAL_SDK_VERSION := current
-LOCAL_PROGUARD_ENABLED := disabled
-LOCAL_DEX_PREOPT := false
-
-LOCAL_PACKAGE_NAME := CtsShimPriv
-
-LOCAL_MANIFEST_FILE := shim_priv/AndroidManifest.xml
-
-include $(BUILD_PACKAGE)
-
-
-###########################################################
 # Variant: Privileged app upgrade
 
 include $(CLEAR_VARS)
@@ -52,7 +33,34 @@
 LOCAL_MANIFEST_FILE := shim_priv_upgrade/AndroidManifest.xml
 
 include $(BUILD_PACKAGE)
+my_shim_priv_upgrade_apk := $(LOCAL_BUILT_MODULE)
 
+###########################################################
+# Variant: Privileged app
+
+include $(CLEAR_VARS)
+# this needs to be a privileged application
+LOCAL_PRIVILEGED_MODULE := true
+
+LOCAL_MODULE_TAGS := optional
+LOCAL_SDK_VERSION := current
+LOCAL_PROGUARD_ENABLED := disabled
+LOCAL_DEX_PREOPT := false
+
+LOCAL_PACKAGE_NAME := CtsShimPriv
+
+# Generate the upgrade key by taking the hash of the built CtsShimPrivUpgrade apk
+gen := $(call intermediates-dir-for,APPS,$(LOCAL_PACKAGE_NAME),,true)/AndroidManifest.xml
+$(gen): PRIVATE_CUSTOM_TOOL = sed -e "s/__HASH__/`sha512sum $(PRIVATE_INPUT_APK) | cut -d' ' -f1`/" $< >$@
+$(gen): PRIVATE_INPUT_APK := $(my_shim_priv_upgrade_apk)
+$(gen): $(LOCAL_PATH)/shim_priv/AndroidManifest.xml $(my_shim_priv_upgrade_apk)
+	$(transform-generated-source)
+
+my_shim_priv_upgrade_apk :=
+
+LOCAL_FULL_MANIFEST_FILE := $(gen)
+
+include $(BUILD_PACKAGE)
 
 ###########################################################
 # Variant: System app
diff --git a/packages/CtsShim/build/README b/packages/CtsShim/build/README
index 1f154e1..333b87c 100644
--- a/packages/CtsShim/build/README
+++ b/packages/CtsShim/build/README
@@ -6,31 +6,18 @@
 NOTE: The need to include a binary on the system image may be deprecated if a
 solution involving a temporarily writable /system partition is implemented.
 
-MAKING THE PREBUILTS
-In order to generate the upgrade key, the shim directory needs to be built multiple
-times. First to generate the upgrade APK [so its hash can be obtained] and again
-once the hash has been included as part of the pre-installed APK.
-
 build:
-    $ mmm frameworks/base/packages/CtsShim/build
+    $ tapas CtsShim CtsShimPriv CtsShimPrivUpgrade
+    $ m
 
-update the manifest:
-    $ sed -i -e "s/__HASH__/`sha512sum out/target/product/shamu/system/priv-app/CtsShimPrivUpgrade/CtsShimPrivUpgrade.apk | cut -d' ' -f1`/" \
-        frameworks/base/packages/CtsShim/build/shim_priv/AndroidManifest.xml
-
-build:
-    $ mmm frameworks/base/packages/CtsShim/build
-
-update prebuilts:
-    $ cp out/target/product/shamu/system/priv-app/CtsShimPrivUpgrade/CtsShimPrivUpgrade.apk \
+local testing:
+    $ cp $OUT/system/priv-app/CtsShimPrivUpgrade/CtsShimPrivUpgrade.apk \
         cts/hostsidetests/appsecurity/test-apps/PrivilegedUpdateApp
-    $ cp out/target/product/shamu/system/priv-app/CtsShimPriv/CtsShimPriv.apk \
+    $ cp $OUT/system/priv-app/CtsShimPriv/CtsShimPriv.apk \
         frameworks/base/packages/CtsShim
-    $ cp out/target/product/shamu/system/app/CtsShim/CtsShim.apk \
+    $ cp $OUT/system/app/CtsShim/CtsShim.apk \
         frameworks/base/packages/CtsShim
 
-revert manifest:
-    $ pushd frameworks/base && git checkout -- packages/CtsShim/build/shim_priv/AndroidManifest.xml && popd
-
-Finally, upload and submit both the cts/ and frameworks/base/ repos.
+For final submission, the APKs should be downloaded from the build server, then
+submitted to the cts/ and frameworks/base/ repos.
 
diff --git a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
index b0e5e4e..6588ee1 100644
--- a/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
+++ b/packages/DocumentsUI/src/com/android/documentsui/OpenExternalDirectoryActivity.java
@@ -20,6 +20,7 @@
 import static android.os.Environment.STANDARD_DIRECTORIES;
 import static android.os.storage.StorageVolume.EXTRA_DIRECTORY_NAME;
 import static android.os.storage.StorageVolume.EXTRA_STORAGE_VOLUME;
+
 import static com.android.documentsui.LocalPreferences.getScopedAccessPermissionStatus;
 import static com.android.documentsui.LocalPreferences.PERMISSION_ASK;
 import static com.android.documentsui.LocalPreferences.PERMISSION_ASK_AGAIN;
@@ -201,14 +202,23 @@
         final List<VolumeInfo> volumes = sm.getVolumes();
         if (DEBUG) Log.d(TAG, "Number of volumes: " + volumes.size());
         File internalRoot = null;
+        boolean found = true;
         for (VolumeInfo volume : volumes) {
             if (isRightVolume(volume, root, userId)) {
+                found = true;
                 internalRoot = volume.getInternalPathForUser(userId);
                 // Must convert path before calling getDocIdForFileCreateNewDir()
                 if (DEBUG) Log.d(TAG, "Converting " + root + " to " + internalRoot);
                 file = isRoot ? internalRoot : new File(internalRoot, directory);
+                volumeUuid = storageVolume.getUuid();
                 volumeLabel = sm.getBestVolumeDescription(volume);
-                volumeUuid = volume.getFsUuid();
+                if (TextUtils.isEmpty(volumeLabel)) {
+                    volumeLabel = storageVolume.getDescription(activity);
+                }
+                if (TextUtils.isEmpty(volumeLabel)) {
+                    volumeLabel = activity.getString(android.R.string.unknownName);
+                    Log.w(TAG, "No volume description  for " + volume + "; using " + volumeLabel);
+                }
                 break;
             }
         }
@@ -229,7 +239,7 @@
             return true;
         }
 
-        if (volumeLabel == null) {
+        if (!found) {
             Log.e(TAG, "Could not get volume for " + file);
             logInvalidScopedAccessRequest(activity, SCOPED_DIRECTORY_ACCESS_ERROR);
             return false;
@@ -277,15 +287,16 @@
     private static boolean isRightVolume(VolumeInfo volume, String root, int userId) {
         final File userPath = volume.getPathForUser(userId);
         final String path = userPath == null ? null : volume.getPathForUser(userId).getPath();
-        final boolean isVisible = volume.isVisibleForWrite(userId);
+        final boolean isMounted = volume.isMountedReadable();
         if (DEBUG)
-            Log.d(TAG, "Volume: " + volume + " userId: " + userId + " root: " + root
-                    + " volumePath: " + volume.getPath().getPath()
-                    + " pathForUser: " + path
-                    + " internalPathForUser: " + volume.getInternalPath()
-                    + " isVisible: " + isVisible);
+            Log.d(TAG, "Volume: " + volume
+                    + "\n\tuserId: " + userId
+                    + "\n\tuserPath: " + userPath
+                    + "\n\troot: " + root
+                    + "\n\tpath: " + path
+                    + "\n\tisMounted: " + isMounted);
 
-        return volume.isVisibleForWrite(userId) && root.equals(path);
+        return isMounted && root.equals(path);
     }
 
     private static Uri getGrantedUriPermission(Context context, ContentProviderClient provider,
@@ -455,7 +466,7 @@
                 message = TextUtils.expandTemplate(
                         getText(mIsPrimary ? R.string.open_external_dialog_request_primary_volume
                                 : R.string.open_external_dialog_request),
-                        mAppLabel, directory, mVolumeLabel);
+                                mAppLabel, directory, mVolumeLabel);
             }
             final TextView messageField = (TextView) view.findViewById(R.id.message);
             messageField.setText(message);
diff --git a/packages/PrintRecommendationService/res/values/strings.xml b/packages/PrintRecommendationService/res/values/strings.xml
index 348fcac..b6c45b7 100644
--- a/packages/PrintRecommendationService/res/values/strings.xml
+++ b/packages/PrintRecommendationService/res/values/strings.xml
@@ -26,6 +26,6 @@
     <string name="plugin_vendor_samsung">Samsung</string>
     <string name="plugin_vendor_epson">Epson</string>
     <string name="plugin_vendor_konica_minolta">Konica Minolta</string>
-    <string name="plugin_vendor_fuji">Fuji</string>
+    <string name="plugin_vendor_fuji_xerox">Fuji Xerox</string>
     <string name="plugin_vendor_morpia">Mopria</string>
 </resources>
diff --git a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
index 52889ce..703cf6f 100644
--- a/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
+++ b/packages/PrintRecommendationService/res/xml/vendorconfigs.xml
@@ -60,7 +60,7 @@
     </vendor>
 
     <vendor>
-        <name>@string/plugin_vendor_fuji</name>
+        <name>@string/plugin_vendor_fuji_xerox</name>
         <package>jp.co.fujixerox.prt.PrintUtil.PCL</package>
         <mdns-names>
             <mdns-name>FUJI XEROX</mdns-name>
diff --git a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java
index 7a2d0d8..b0da08b 100755
--- a/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java
+++ b/packages/PrintRecommendationService/src/com/android/printservice/recommendation/plugin/xerox/MDnsUtils.java
@@ -39,8 +39,10 @@
         String usbMfg = getString(attributes.get(ATTRIBUTE__USB_MFG));
         String usbMdl = getString(attributes.get(ATTRIBUTE__USB_MDL));
         String mfg = getString(attributes.get(ATTRIBUTE__MFG));
-        return containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) || containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues) && !(containsString(ty, EXCLUDE_FUJI) || containsString(product, EXCLUDE_FUJI) || containsString(usbMdl, EXCLUDE_FUJI));
-
+        return (containsVendor(product, vendorValues) || containsVendor(ty, vendorValues) ||
+                containsVendor(usbMfg, vendorValues) || containsVendor(mfg, vendorValues)) &&
+                !(containsString(ty, EXCLUDE_FUJI) || containsString(product, EXCLUDE_FUJI) ||
+                        containsString(usbMdl, EXCLUDE_FUJI));
     }
 
     public static String getVendor(NsdServiceInfo networkDevice) {
diff --git a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
index be3df54..c318275 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/ui/PrintActivity.java
@@ -614,6 +614,9 @@
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
+
+        mMediaSizeComparator.onConfigurationChanged(newConfig);
+
         if (mPrintPreviewController != null) {
             mPrintPreviewController.onOrientationChanged();
         }
diff --git a/packages/PrintSpooler/src/com/android/printspooler/util/MediaSizeUtils.java b/packages/PrintSpooler/src/com/android/printspooler/util/MediaSizeUtils.java
index 912ee1d..7289301 100644
--- a/packages/PrintSpooler/src/com/android/printspooler/util/MediaSizeUtils.java
+++ b/packages/PrintSpooler/src/com/android/printspooler/util/MediaSizeUtils.java
@@ -16,13 +16,16 @@
 
 package com.android.printspooler.util;
 
+import android.annotation.NonNull;
 import android.content.Context;
+import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
 import android.print.PrintAttributes.MediaSize;
-import android.util.ArrayMap;
 
 import com.android.printspooler.R;
 
 import java.util.Comparator;
+import java.util.HashMap;
 import java.util.Map;
 
 /**
@@ -30,7 +33,10 @@
  */
 public final class MediaSizeUtils {
 
-    private static Map<MediaSize, String> sMediaSizeToStandardMap;
+    private static Map<MediaSize, Integer> sMediaSizeToStandardMap;
+
+    /** The media size standard for all media sizes no standard is defined for */
+    private static int sMediaSizeStandardIso;
 
     private MediaSizeUtils() {
         /* do nothing - hide constructor */
@@ -47,22 +53,32 @@
         return MediaSize.getStandardMediaSizeById(mediaSizeId);
     }
 
-    private static String getStandardForMediaSize(Context context, MediaSize mediaSize) {
+    /**
+     * Get the standard the {@link MediaSize} belongs to.
+     *
+     * @param context   The context of the caller
+     * @param mediaSize The {@link MediaSize} to be resolved
+     *
+     * @return The standard the {@link MediaSize} belongs to
+     */
+    private static int getStandardForMediaSize(Context context, MediaSize mediaSize) {
         if (sMediaSizeToStandardMap == null) {
-            sMediaSizeToStandardMap = new ArrayMap<MediaSize, String>();
+            sMediaSizeStandardIso = Integer.parseInt(context.getString(
+                    R.string.mediasize_standard_iso));
+
+            sMediaSizeToStandardMap = new HashMap<>();
             String[] mediaSizeToStandardMapValues = context.getResources()
                     .getStringArray(R.array.mediasize_to_standard_map);
             final int mediaSizeToStandardCount = mediaSizeToStandardMapValues.length;
             for (int i = 0; i < mediaSizeToStandardCount; i += 2) {
                 String mediaSizeId = mediaSizeToStandardMapValues[i];
                 MediaSize key = MediaSize.getStandardMediaSizeById(mediaSizeId);
-                String value = mediaSizeToStandardMapValues[i + 1];
+                int value = Integer.parseInt(mediaSizeToStandardMapValues[i + 1]);
                 sMediaSizeToStandardMap.put(key, value);
             }
         }
-        String standard = sMediaSizeToStandardMap.get(mediaSize);
-        return (standard != null) ? standard : context.getString(
-                R.string.mediasize_standard_iso);
+        Integer standard = sMediaSizeToStandardMap.get(mediaSize);
+        return (standard != null) ? standard : sMediaSizeStandardIso;
     }
 
     /**
@@ -73,32 +89,76 @@
     public static final class MediaSizeComparator implements Comparator<MediaSize> {
         private final Context mContext;
 
+        /** Current configuration */
+        private Configuration mCurrentConfig;
+
+        /** The standard to use for the current locale */
+        private int mCurrentStandard;
+
+        /** Mapping from media size to label */
+        private final @NonNull Map<MediaSize, String> mMediaSizeToLabel;
+
         public MediaSizeComparator(Context context) {
             mContext = context;
+            mMediaSizeToLabel = new HashMap<>();
+            mCurrentStandard = Integer.parseInt(mContext.getString(R.string.mediasize_standard));
+        }
+
+        /**
+         * Handle a configuration change by reloading all resources.
+         *
+         * @param newConfig The new configuration that will be applied.
+         */
+        public void onConfigurationChanged(@NonNull Configuration newConfig) {
+            if (mCurrentConfig == null ||
+                    (newConfig.diff(mCurrentConfig) & ActivityInfo.CONFIG_LOCALE) != 0) {
+                mCurrentStandard = Integer
+                        .parseInt(mContext.getString(R.string.mediasize_standard));
+                mMediaSizeToLabel.clear();
+
+                mCurrentConfig = newConfig;
+            }
+        }
+
+        /**
+         * Get the label for a {@link MediaSize}.
+         *
+         * @param context   The context the label should be loaded for
+         * @param mediaSize The {@link MediaSize} to resolve
+         *
+         * @return The label for the media size
+         */
+        public @NonNull String getLabel(@NonNull Context context, @NonNull MediaSize mediaSize) {
+            String label = mMediaSizeToLabel.get(mediaSize);
+
+            if (label == null) {
+                label = mediaSize.getLabel(context.getPackageManager());
+                mMediaSizeToLabel.put(mediaSize, label);
+            }
+
+            return label;
         }
 
         @Override
         public int compare(MediaSize lhs, MediaSize rhs) {
-            String currentStandard = mContext.getString(R.string.mediasize_standard);
-            String lhsStandard = getStandardForMediaSize(mContext, lhs);
-            String rhsStandard = getStandardForMediaSize(mContext, rhs);
+            int lhsStandard = getStandardForMediaSize(mContext, lhs);
+            int rhsStandard = getStandardForMediaSize(mContext, rhs);
 
             // The current standard always wins.
-            if (lhsStandard.equals(currentStandard)) {
-                if (!rhsStandard.equals(currentStandard)) {
+            if (lhsStandard == mCurrentStandard) {
+                if (rhsStandard != mCurrentStandard) {
                     return -1;
                 }
-            } else if (rhsStandard.equals(currentStandard)) {
+            } else if (rhsStandard == mCurrentStandard) {
                 return 1;
             }
 
-            if (!lhsStandard.equals(rhsStandard)) {
+            if (lhsStandard != rhsStandard) {
                 // Different standards - use the standard ordering.
-                return lhsStandard.compareTo(rhsStandard);
+                return Integer.valueOf(lhsStandard).compareTo(rhsStandard);
             } else {
                 // Same standard - sort alphabetically by label.
-                return lhs.getLabel(mContext.getPackageManager()).
-                        compareTo(rhs.getLabel(mContext.getPackageManager()));
+                return getLabel(mContext, lhs).compareTo(getLabel(mContext, rhs));
             }
         }
     }
diff --git a/packages/Shell/AndroidManifest.xml b/packages/Shell/AndroidManifest.xml
index 9c0aa35d..2efefb3 100644
--- a/packages/Shell/AndroidManifest.xml
+++ b/packages/Shell/AndroidManifest.xml
@@ -90,7 +90,7 @@
     <uses-permission android:name="android.permission.WRITE_MEDIA_STORAGE" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS" />
     <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
-    <uses-permission android:name="android.permission.MANAGE_USERS" />
+    <uses-permission android:name="android.permission.CREATE_USERS" />
     <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
     <uses-permission android:name="android.permission.BLUETOOTH_STACK" />
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 19d612d..603d1e0 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -402,16 +402,16 @@
     <string name="monitoring_title" msgid="169206259253048106">"Overvågning af netværk"</string>
     <string name="disable_vpn" msgid="4435534311510272506">"Deaktiver VPN"</string>
     <string name="disconnect_vpn" msgid="1324915059568548655">"Afbryd VPN-forbindelse"</string>
-    <string name="monitoring_description_device_owned" msgid="5780988291898461883">"Din enhed administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er knyttet til din enhed, og din enheds placeringsoplysninger. Kontakt din administrator, hvis du vil have flere oplysninger."</string>
+    <string name="monitoring_description_device_owned" msgid="5780988291898461883">"Din enhed administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er knyttet til din enhed, og din enheds stedoplysninger. Kontakt din administrator, hvis du vil have flere oplysninger."</string>
     <string name="monitoring_description_vpn" msgid="4445150119515393526">"Du gav en app tilladelse til at konfigurere en VPN-forbindelse.\n\nDenne app kan overvåge din enhed og netværksaktivitet, bl.a. e-mails, apps og websites."</string>
-    <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"Din enhed administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er knyttet til din enhed, og din enheds placeringsoplysninger.\n\nDu har forbindelse til et VPN, som kan overvåge din netværksaktivitet, herunder e-mails, apps og websites.\n\nKontakt din administrator, hvis du vil have flere oplysninger."</string>
+    <string name="monitoring_description_vpn_device_owned" msgid="3090670777499161246">"Din enhed administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge og administrere indstillinger, virksomhedsadgang, apps, data, der er knyttet til din enhed, og din enheds stedoplysninger.\n\nDu har forbindelse til et VPN, som kan overvåge din netværksaktivitet, herunder e-mails, apps og websites.\n\nKontakt din administrator, hvis du vil have flere oplysninger."</string>
     <string name="monitoring_description_vpn_profile_owned" msgid="2054949132145039290">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger.\n\nDu er også forbundet til en VPN-forbindelse, som kan overvåge din netværksaktivitet."</string>
     <string name="legacy_vpn_name" msgid="6604123105765737830">"VPN"</string>
     <string name="monitoring_description_app" msgid="6259179342284742878">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites."</string>
     <string name="monitoring_description_app_personal" msgid="484599052118316268">"Du har forbindelse til <xliff:g id="APPLICATION">%1$s</xliff:g>, som kan overvåge din private netværksaktivitet, bl.a. e-mails, apps og websites."</string>
     <string name="monitoring_description_app_work" msgid="1754325860918060897">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Den er forbundet til <xliff:g id="APPLICATION">%2$s</xliff:g>, som kan overvåge din arbejdsrelaterede netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger."</string>
     <string name="monitoring_description_app_personal_work" msgid="4946600443852045903">"Din arbejdsprofil administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>. Den er forbundet til <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>, som kan overvåge din arbejdsrelaterede netværksaktivitet, bl.a. e-mails, apps og websites.\n\nDu er også forbundet til <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>, som kan overvåge din private netværksaktivitet."</string>
-    <string name="monitoring_description_vpn_app_device_owned" msgid="4970443827043261703">"Din enhed administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge og administrere indstillinger, virksomhedens adgang, data tilknyttet din enhed og enhedens placeringsoplysninger.\n\nDu er forbundet til <xliff:g id="APPLICATION">%2$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger."</string>
+    <string name="monitoring_description_vpn_app_device_owned" msgid="4970443827043261703">"Din enhed administreres af <xliff:g id="ORGANIZATION">%1$s</xliff:g>.\n\nDin administrator kan overvåge og administrere indstillinger, virksomhedens adgang, data tilknyttet din enhed og enhedens stedoplysninger.\n\nDu er forbundet til <xliff:g id="APPLICATION">%2$s</xliff:g>, som kan overvåge din netværksaktivitet, bl.a. e-mails, apps og websites.\n\nKontakt din administrator for at få flere oplysninger."</string>
     <string name="keyguard_indication_trust_disabled" msgid="7412534203633528135">"Enheden vil forblive låst, indtil du manuelt låser den op"</string>
     <string name="hidden_notifications_title" msgid="7139628534207443290">"Modtag underretninger hurtigere"</string>
     <string name="hidden_notifications_text" msgid="2326409389088668981">"Se dem, før du låser op"</string>
diff --git a/packages/SystemUI/res/values-hy-rAM/strings.xml b/packages/SystemUI/res/values-hy-rAM/strings.xml
index 01dcee2..5d01d15 100644
--- a/packages/SystemUI/res/values-hy-rAM/strings.xml
+++ b/packages/SystemUI/res/values-hy-rAM/strings.xml
@@ -153,7 +153,7 @@
     <string name="accessibility_cell_data_on" msgid="4310018593519761767">"Բջջային տվյալներն ակտիվ են"</string>
     <string name="accessibility_cell_data_off" msgid="8000803571751407635">"Բջջային ցանցով տվյալների փոխանցումն անջատված է"</string>
     <string name="accessibility_bluetooth_tether" msgid="4102784498140271969">"Bluetooth-ը կապվում է:"</string>
-    <string name="accessibility_airplane_mode" msgid="834748999790763092">"Ինքնաթիռային ռեժիմ"</string>
+    <string name="accessibility_airplane_mode" msgid="834748999790763092">"Ինքնաթիռի ռեժիմ"</string>
     <string name="accessibility_no_sims" msgid="3957997018324995781">"SIM քարտ չկա:"</string>
     <string name="accessibility_carrier_network_change_mode" msgid="4017301580441304305">"Օպերատորի ցանցի փոփոխում:"</string>
     <string name="accessibility_battery_details" msgid="7645516654955025422">"Բացել մարտկոցի տվյալները"</string>
@@ -189,10 +189,10 @@
     <string name="accessibility_quick_settings_wifi_changed_on" msgid="6440117170789528622">"Wifi-ը միացավ:"</string>
     <string name="accessibility_quick_settings_mobile" msgid="4876806564086241341">"Շարժական <xliff:g id="SIGNAL">%1$s</xliff:g>: <xliff:g id="TYPE">%2$s</xliff:g>: <xliff:g id="NETWORK">%3$s</xliff:g>:"</string>
     <string name="accessibility_quick_settings_battery" msgid="1480931583381408972">"Մարտկոցը <xliff:g id="STATE">%s</xliff:g> է:"</string>
-    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Ինքնաթիռային ռեժիմն անջատված է:"</string>
-    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Ինքնաթիռային ռեժիմը միացված է:"</string>
-    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Ինքնաթիռային ռեժիմն անջատվեց:"</string>
-    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Ինքնաթիռային ռեժիմը միացավ:"</string>
+    <string name="accessibility_quick_settings_airplane_off" msgid="7786329360056634412">"Ինքնաթիռի ռեժիմն անջատված է:"</string>
+    <string name="accessibility_quick_settings_airplane_on" msgid="6406141469157599296">"Ինքնաթիռի ռեժիմը միացված է:"</string>
+    <string name="accessibility_quick_settings_airplane_changed_off" msgid="66846307818850664">"Ինքնաթիռի ռեժիմն անջատվեց:"</string>
+    <string name="accessibility_quick_settings_airplane_changed_on" msgid="8983005603505087728">"Ինքնաթիռի ռեժիմը միացավ:"</string>
     <string name="accessibility_quick_settings_dnd_priority_on" msgid="1448402297221249355">"Չխանգարելու ընտրանքը միացված է: Ընդհատել միայն կարևոր ծանուցումների դեպքում:"</string>
     <string name="accessibility_quick_settings_dnd_none_on" msgid="6882582132662613537">"Չանհանգստացնել՝ ընդհանուր լուռ վիճակը:"</string>
     <string name="accessibility_quick_settings_dnd_alarms_on" msgid="9152834845587554157">"Չանհանգստացնել՝ միայն զարթուցիչ"</string>
@@ -451,7 +451,7 @@
     <string name="status_bar_ethernet" msgid="5044290963549500128">"Ethernet"</string>
     <string name="status_bar_alarm" msgid="8536256753575881818">"Զարթուցիչ"</string>
     <string name="status_bar_work" msgid="6022553324802866373">"Android for Work-ի պրոֆիլ"</string>
-    <string name="status_bar_airplane" msgid="7057575501472249002">"Ինքնաթիռային ռեժիմ"</string>
+    <string name="status_bar_airplane" msgid="7057575501472249002">"Ինքնաթիռի ռեժիմ"</string>
     <string name="add_tile" msgid="2995389510240786221">"Սալիկի ավելացում"</string>
     <string name="broadcast_tile" msgid="3894036511763289383">"Սալիկի հեռարձակում"</string>
     <string name="zen_alarm_warning_indef" msgid="3482966345578319605">"Ժամը <xliff:g id="WHEN">%1$s</xliff:g>-ի զարթուցիչը չի զանգի, եթե մինչ այդ չանջատեք այս կարգավորումը"</string>
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
index 51efbf0..932b4f5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFooter.java
@@ -127,7 +127,7 @@
     public void onClick(DialogInterface dialog, int which) {
         if (which == DialogInterface.BUTTON_NEGATIVE) {
             final Intent settingsIntent = new Intent(ACTION_VPN_SETTINGS);
-            mContext.startActivityAsUser(settingsIntent, UserHandle.CURRENT);
+            mHost.startActivityDismissingKeyguard(settingsIntent);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
index 8ec6a2f..777ed6a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/TileQueryHelper.java
@@ -28,6 +28,8 @@
 import android.os.Handler;
 import android.os.Looper;
 import android.service.quicksettings.TileService;
+import android.widget.Button;
+
 import com.android.systemui.R;
 import com.android.systemui.qs.QSTile;
 import com.android.systemui.qs.QSTile.DrawableIcon;
@@ -110,6 +112,8 @@
         }
         TileInfo info = new TileInfo();
         info.state = state;
+        info.state.minimalAccessibilityClassName = info.state.expandedAccessibilityClassName =
+                Button.class.getName();
         info.spec = spec;
         info.appLabel = appLabel;
         info.isSystem = isSystem;
diff --git a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
index 72a589f..e757560 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/tv/views/TaskCardView.java
@@ -56,6 +56,7 @@
     private ImageView mBadgeView;
     private Task mTask;
     private boolean mDismissState;
+    private boolean mTouchExplorationEnabled;
     private int mCornerRadius;
 
     private ViewFocusAnimator mViewFocusAnimator;
@@ -90,7 +91,8 @@
                 R.dimen.recents_task_view_rounded_corners_radius);
         mRecentsRowFocusAnimationHolder = new RecentsRowFocusAnimationHolder(this, mInfoFieldView);
         SystemServicesProxy ssp = Recents.getSystemServices();
-        if (!ssp.isTouchExplorationEnabled()) {
+        mTouchExplorationEnabled = ssp.isTouchExplorationEnabled();
+        if (!mTouchExplorationEnabled) {
             mDismissIconView.setVisibility(VISIBLE);
         } else {
             mDismissIconView.setVisibility(GONE);
@@ -237,10 +239,15 @@
     private void setDismissState(boolean dismissState) {
         if (mDismissState != dismissState) {
             mDismissState = dismissState;
-            if (dismissState) {
-                mDismissAnimationsHolder.startEnterAnimation();
-            } else {
-                mDismissAnimationsHolder.startExitAnimation();
+            // Check for touch exploration to ensure dismiss icon/text do not
+            // get animated. This should be removed based on decision from
+            // b/29208918
+            if (!mTouchExplorationEnabled) {
+                if (dismissState) {
+                    mDismissAnimationsHolder.startEnterAnimation();
+                } else {
+                    mDismissAnimationsHolder.startExitAnimation();
+                }
             }
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
index 41869dd..e503c56 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/views/RecentsTransitionHelper.java
@@ -209,7 +209,9 @@
             EventBus.getDefault().send(new LaunchTaskSucceededEvent(taskIndexFromFront));
         } else {
             // Dismiss the task if we fail to launch it
-            taskView.dismissTask();
+            if (taskView != null) {
+                taskView.dismissTask();
+            }
 
             // Keep track of failed launches
             EventBus.getDefault().send(new LaunchTaskFailedEvent());
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
new file mode 100644
index 0000000..ff2febf
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationMessagingTemplateViewWrapper.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.systemui.statusbar.notification;
+
+import com.android.internal.widget.MessagingLinearLayout;
+import com.android.systemui.statusbar.ExpandableNotificationRow;
+import com.android.systemui.statusbar.TransformableView;
+
+import android.content.Context;
+import android.service.notification.StatusBarNotification;
+import android.view.View;
+
+/**
+ * Wraps a notification containing a messaging template
+ */
+public class NotificationMessagingTemplateViewWrapper extends NotificationTemplateViewWrapper {
+
+    private View mContractedMessage;
+
+    protected NotificationMessagingTemplateViewWrapper(Context ctx, View view,
+            ExpandableNotificationRow row) {
+        super(ctx, view, row);
+    }
+
+    private void resolveViews() {
+        mContractedMessage = null;
+
+        View container = mView.findViewById(com.android.internal.R.id.notification_messaging);
+        if (container instanceof MessagingLinearLayout
+                && ((MessagingLinearLayout) container).getChildCount() > 0) {
+            MessagingLinearLayout messagingContainer = (MessagingLinearLayout) container;
+
+            // Only consider the first child - transforming to a position other than the first
+            // looks bad because we have to move across other messages that are fading in.
+            View child = messagingContainer.getChildAt(0);
+            if (child.getId() == messagingContainer.getContractedChildId()) {
+                mContractedMessage = child;
+            }
+        }
+    }
+
+    @Override
+    public void notifyContentUpdated(StatusBarNotification notification) {
+        // Reinspect the notification. Before the super call, because the super call also updates
+        // the transformation types and we need to have our values set by then.
+        resolveViews();
+        super.notifyContentUpdated(notification);
+    }
+
+    @Override
+    protected void updateTransformedTypes() {
+        // This also clears the existing types
+        super.updateTransformedTypes();
+        if (mContractedMessage != null) {
+            mTransformationHelper.addTransformedView(TransformableView.TRANSFORMING_VIEW_TEXT,
+                    mContractedMessage);
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
index 22519e6..16348dfe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/NotificationViewWrapper.java
@@ -50,6 +50,8 @@
                 return new NotificationBigTextTemplateViewWrapper(ctx, v, row);
             } else if ("media".equals(v.getTag()) || "bigMediaNarrow".equals(v.getTag())) {
                 return new NotificationMediaTemplateViewWrapper(ctx, v, row);
+            } else if ("messaging".equals(v.getTag())) {
+                return new NotificationMessagingTemplateViewWrapper(ctx, v, row);
             }
             return new NotificationTemplateViewWrapper(ctx, v, row);
         } else if (v instanceof NotificationHeaderView) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
index 6d0fbb15..58fbd4c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/AutoTileManager.java
@@ -80,14 +80,16 @@
             new NightModeController.Listener() {
         @Override
         public void onNightModeChanged() {
-            mHost.addTile("night");
-            Prefs.putBoolean(mContext, Key.QS_NIGHT_ADDED, true);
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mHost.getNightModeController().removeListener(mNightModeListener);
-                }
-            });
+            if (mHost.getNightModeController().isEnabled()) {
+                mHost.addTile("night");
+                Prefs.putBoolean(mContext, Key.QS_NIGHT_ADDED, true);
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        mHost.getNightModeController().removeListener(mNightModeListener);
+                    }
+                });
+            }
         }
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
index 186005c..a92422a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DateView.java
@@ -21,7 +21,8 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.TypedArray;
-import android.text.format.DateFormat;
+import android.icu.text.DateFormat;
+import android.icu.text.DisplayContext;
 import android.util.AttributeSet;
 import android.widget.TextView;
 
@@ -36,7 +37,7 @@
 
     private final Date mCurrentTime = new Date();
 
-    private SimpleDateFormat mDateFormat;
+    private DateFormat mDateFormat;
     private String mLastText;
     private String mDatePattern;
 
@@ -100,8 +101,9 @@
     protected void updateClock() {
         if (mDateFormat == null) {
             final Locale l = Locale.getDefault();
-            final String fmt = DateFormat.getBestDateTimePattern(l, mDatePattern);
-            mDateFormat = new SimpleDateFormat(fmt, l);
+            DateFormat format = DateFormat.getInstanceForSkeleton(mDatePattern, l);
+            format.setContext(DisplayContext.CAPITALIZATION_FOR_STANDALONE);
+            mDateFormat = format;
         }
 
         mCurrentTime.setTime(System.currentTimeMillis());
diff --git a/rs/java/android/renderscript/RenderScript.java b/rs/java/android/renderscript/RenderScript.java
index 3d1370a..3333aa8 100644
--- a/rs/java/android/renderscript/RenderScript.java
+++ b/rs/java/android/renderscript/RenderScript.java
@@ -752,20 +752,12 @@
         rsnScriptForEach(mContext, id, slot, ains, aout, params, limits);
     }
 
-    native void rsnScriptReduce(long con, long id, int slot, long ain,
+    native void rsnScriptReduce(long con, long id, int slot, long[] ains,
                                 long aout, int[] limits);
-    synchronized void nScriptReduce(long id, int slot, long ain, long aout,
+    synchronized void nScriptReduce(long id, int slot, long ains[], long aout,
                                     int[] limits) {
         validate();
-        rsnScriptReduce(mContext, id, slot, ain, aout, limits);
-    }
-
-    native void rsnScriptReduceNew(long con, long id, int slot, long[] ains,
-                                   long aout, int[] limits);
-    synchronized void nScriptReduceNew(long id, int slot, long ains[], long aout,
-                                       int[] limits) {
-        validate();
-        rsnScriptReduceNew(mContext, id, slot, ains, aout, limits);
+        rsnScriptReduce(mContext, id, slot, ains, aout, limits);
     }
 
     native void rsnScriptInvokeV(long con, long id, int slot, byte[] params);
diff --git a/rs/java/android/renderscript/Script.java b/rs/java/android/renderscript/Script.java
index fc3280b..13d5fcd 100644
--- a/rs/java/android/renderscript/Script.java
+++ b/rs/java/android/renderscript/Script.java
@@ -286,35 +286,6 @@
     }
 
     /**
-     * Only intended for use by generated reflected code.  (Simple reduction)
-     *
-     * @hide
-     */
-    protected void reduce(int slot, Allocation ain, Allocation aout, LaunchOptions sc) {
-        mRS.validate();
-        mRS.validateObject(ain);
-        mRS.validateObject(aout);
-
-        if (ain == null || aout == null) {
-            throw new RSIllegalArgumentException(
-                "Both ain and aout are required to be non-null.");
-        }
-
-        long in_id = ain.getID(mRS);
-        long out_id = aout.getID(mRS);
-
-        int[] limits = null;
-        if (sc != null) {
-            limits = new int[2];
-
-            limits[0] = sc.xstart;
-            limits[1] = sc.xend;
-        }
-
-        mRS.nScriptReduce(getID(mRS), slot, in_id, out_id, limits);
-    }
-
-    /**
      * Only intended for use by generated reflected code.  (General reduction)
      *
      */
@@ -350,7 +321,7 @@
             limits[5] = sc.zend;
         }
 
-        mRS.nScriptReduceNew(getID(mRS), slot, in_ids, out_id, limits);
+        mRS.nScriptReduce(getID(mRS), slot, in_ids, out_id, limits);
     }
 
     long[] mInIdsBuffer;
diff --git a/rs/jni/android_renderscript_RenderScript.cpp b/rs/jni/android_renderscript_RenderScript.cpp
index e0f5934..aa2a607 100644
--- a/rs/jni/android_renderscript_RenderScript.cpp
+++ b/rs/jni/android_renderscript_RenderScript.cpp
@@ -2094,67 +2094,10 @@
 
 static void
 nScriptReduce(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
-              jlong ain, jlong aout, jintArray limits)
+              jlongArray ains, jlong aout, jintArray limits)
 {
     if (kLogApi) {
-        ALOGD("nScriptReduce, con(%p), s(%p), slot(%i) ain(%" PRId64 ") aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ain, aout);
-    }
-
-    RsScriptCall sc, *sca = nullptr;
-    uint32_t sc_size = 0;
-
-    jint  limit_len = 0;
-    jint *limit_ptr = nullptr;
-
-    // If the caller passed limits, reflect them in the RsScriptCall.
-    if (limits != nullptr) {
-        limit_len = _env->GetArrayLength(limits);
-        limit_ptr = _env->GetIntArrayElements(limits, nullptr);
-        if (limit_ptr == nullptr) {
-            ALOGE("Failed to get Java array elements");
-            return;
-        }
-
-        // We expect to be passed an array [x1, x2] which specifies
-        // the sub-range for a 1-dimensional reduction.
-        assert(limit_len == 2);
-        UNUSED(limit_len);  // As the assert might not be compiled.
-
-        sc.xStart     = limit_ptr[0];
-        sc.xEnd       = limit_ptr[1];
-        sc.yStart     = 0;
-        sc.yEnd       = 0;
-        sc.zStart     = 0;
-        sc.zEnd       = 0;
-        sc.strategy   = RS_FOR_EACH_STRATEGY_DONT_CARE;
-        sc.arrayStart = 0;
-        sc.arrayEnd = 0;
-        sc.array2Start = 0;
-        sc.array2End = 0;
-        sc.array3Start = 0;
-        sc.array3End = 0;
-        sc.array4Start = 0;
-        sc.array4End = 0;
-
-        sca = &sc;
-        sc_size = sizeof(sc);
-    }
-
-    rsScriptReduce((RsContext)con, (RsScript)script, slot,
-                   (RsAllocation)ain, (RsAllocation)aout,
-                   sca, sc_size);
-
-    if (limits != nullptr) {
-        _env->ReleaseIntArrayElements(limits, limit_ptr, JNI_ABORT);
-    }
-}
-
-static void
-nScriptReduceNew(JNIEnv *_env, jobject _this, jlong con, jlong script, jint slot,
-                 jlongArray ains, jlong aout, jintArray limits)
-{
-    if (kLogApi) {
-        ALOGD("nScriptReduceNew, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
+        ALOGD("nScriptReduce, con(%p), s(%p), slot(%i) ains(%p) aout(%" PRId64 ")", (RsContext)con, (void *)script, slot, ains, aout);
     }
 
     if (ains == nullptr) {
@@ -2233,9 +2176,9 @@
         sc_size = sizeof(sc);
     }
 
-    rsScriptReduceNew((RsContext)con, (RsScript)script, slot,
-                      in_allocs, in_len, (RsAllocation)aout,
-                      sca, sc_size);
+    rsScriptReduce((RsContext)con, (RsScript)script, slot,
+                   in_allocs, in_len, (RsAllocation)aout,
+                   sca, sc_size);
 
     _env->ReleaseLongArrayElements(ains, in_ptr, JNI_ABORT);
 
@@ -2951,8 +2894,7 @@
 {"rsnScriptInvokeV",                 "(JJI[B)V",                              (void*)nScriptInvokeV },
 
 {"rsnScriptForEach",                 "(JJI[JJ[B[I)V",                         (void*)nScriptForEach },
-{"rsnScriptReduce",                  "(JJIJJ[I)V",                            (void*)nScriptReduce },
-{"rsnScriptReduceNew",               "(JJI[JJ[I)V",                           (void*)nScriptReduceNew },
+{"rsnScriptReduce",                  "(JJI[JJ[I)V",                           (void*)nScriptReduce },
 
 {"rsnScriptSetVarI",                 "(JJII)V",                               (void*)nScriptSetVarI },
 {"rsnScriptGetVarI",                 "(JJI)I",                                (void*)nScriptGetVarI },
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index acc2ec3..334b228 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -9849,7 +9849,11 @@
 
         synchronized(this) {
             if (mActiveRestoreSession != null) {
-                Slog.d(TAG, "Restore session requested but one already active");
+                Slog.i(TAG, "Restore session requested but one already active");
+                return null;
+            }
+            if (mBackupRunning) {
+                Slog.i(TAG, "Restore session requested but currently running backups");
                 return null;
             }
             mActiveRestoreSession = new ActiveRestoreSession(packageName, transport);
diff --git a/services/core/java/com/android/server/BluetoothManagerService.java b/services/core/java/com/android/server/BluetoothManagerService.java
index 3eadb5c..9154b8e 100644
--- a/services/core/java/com/android/server/BluetoothManagerService.java
+++ b/services/core/java/com/android/server/BluetoothManagerService.java
@@ -222,7 +222,7 @@
                             } catch (RemoteException e) {
                                 Slog.e(TAG,"Unable to call onBrEdrDown", e);
                             } finally {
-                                mBluetoothLock.readLock().lock();
+                                mBluetoothLock.readLock().unlock();
                             }
                         } else if (st == BluetoothAdapter.STATE_ON){
                             // disable without persisting the setting
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index acf8009..41d8b4f 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -3552,14 +3552,14 @@
                     .build();
 
             try {
-                notificationManager.notify(NOTIFICATION_ID, id, notification);
+                notificationManager.notifyAsUser(NOTIFICATION_ID, id, notification, UserHandle.ALL);
             } catch (NullPointerException npe) {
                 loge("setNotificationVisible: visible notificationManager npe=" + npe);
                 npe.printStackTrace();
             }
         } else {
             try {
-                notificationManager.cancel(NOTIFICATION_ID, id);
+                notificationManager.cancelAsUser(NOTIFICATION_ID, id, UserHandle.ALL);
             } catch (NullPointerException npe) {
                 loge("setNotificationVisible: cancel notificationManager npe=" + npe);
                 npe.printStackTrace();
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index e0b4960..36ec2eb 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -1431,6 +1431,13 @@
                 for (UpdateRecord record : records) {
                     if (isCurrentProfile(UserHandle.getUserId(record.mReceiver.mUid))) {
                         LocationRequest locationRequest = record.mRequest;
+
+                        // Don't assign battery blame for update records whose
+                        // client has no permission to receive location data.
+                        if (!providerRequest.locationRequests.contains(locationRequest)) {
+                            continue;
+                        }
+
                         if (locationRequest.getInterval() <= thresholdInterval) {
                             if (record.mReceiver.mWorkSource != null
                                     && record.mReceiver.mWorkSource.size() > 0
diff --git a/services/core/java/com/android/server/MountService.java b/services/core/java/com/android/server/MountService.java
index c89b6ea..9c75a00 100644
--- a/services/core/java/com/android/server/MountService.java
+++ b/services/core/java/com/android/server/MountService.java
@@ -3031,7 +3031,8 @@
                 if (forWrite) {
                     match = vol.isVisibleForWrite(userId);
                 } else {
-                    match = vol.isVisibleForRead(userId) || includeInvisible;
+                    match = vol.isVisibleForRead(userId)
+                            || (includeInvisible && vol.getPath() != null);
                 }
                 if (!match) continue;
 
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 2d6b5ef8..897aa20 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -5375,17 +5375,18 @@
         userId = mUserController.handleIncomingUser(pid, uid, userId, false,
                 ALLOW_FULL_ONLY, "clearApplicationUserData", null);
 
-        final DevicePolicyManagerInternal dpmi = LocalServices
-                .getService(DevicePolicyManagerInternal.class);
-        if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
-            throw new SecurityException("Cannot clear data for a device owner or a profile owner");
-        }
 
         long callingId = Binder.clearCallingIdentity();
         try {
             IPackageManager pm = AppGlobals.getPackageManager();
             int pkgUid = -1;
             synchronized(this) {
+                if (getPackageManagerInternalLocked().canPackageBeWiped(
+                        userId, packageName)) {
+                    throw new SecurityException(
+                            "Cannot clear data for a device owner or a profile owner");
+                }
+
                 try {
                     pkgUid = pm.getPackageUid(packageName, MATCH_UNINSTALLED_PACKAGES, userId);
                 } catch (RemoteException e) {
@@ -6036,7 +6037,7 @@
         if (appId < 0 && packageName != null) {
             try {
                 appId = UserHandle.getAppId(AppGlobals.getPackageManager()
-                        .getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, userId));
+                        .getPackageUid(packageName, MATCH_DEBUG_TRIAGED_MISSING, 0));
             } catch (RemoteException e) {
             }
         }
@@ -13881,7 +13882,12 @@
                             args.length - opti);
                 }
                 synchronized (this) {
-                    dumpBroadcastStatsLocked(fd, pw, args, opti, true, dumpPackage);
+                    if (dumpCheckinFormat) {
+                        dumpBroadcastStatsCheckinLocked(fd, pw, args, opti, dumpCheckin,
+                                dumpPackage);
+                    } else {
+                        dumpBroadcastStatsLocked(fd, pw, args, opti, true, dumpPackage);
+                    }
                 }
             } else if ("intents".equals(cmd) || "i".equals(cmd)) {
                 String[] newArgs;
@@ -17778,6 +17784,11 @@
                                 getPackageManagerInternalLocked().getApplicationInfo(
                                         ssp,
                                         userId);
+                        if (aInfo == null) {
+                            Slog.w(TAG, "Dropping ACTION_PACKAGE_REPLACED for non-existent pkg:"
+                                    + " ssp=" + ssp + " data=" + data);
+                            return ActivityManager.BROADCAST_SUCCESS;
+                        }
                         mStackSupervisor.updateActivityApplicationInfoLocked(aInfo);
                         sendPackageBroadcastLocked(IApplicationThread.PACKAGE_REPLACED,
                                 new String[] {ssp}, userId);
diff --git a/services/core/java/com/android/server/am/ActivityStack.java b/services/core/java/com/android/server/am/ActivityStack.java
index d83a750..df85cfa 100644
--- a/services/core/java/com/android/server/am/ActivityStack.java
+++ b/services/core/java/com/android/server/am/ActivityStack.java
@@ -2581,11 +2581,14 @@
     }
 
     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;
             }
         }
 
@@ -2595,7 +2598,10 @@
             ActivityStack lastStack = mStackSupervisor.getLastStack();
             final boolean fromHome = lastStack.isHomeStack();
             if (!isHomeStack() && (fromHome || topTask() != task)) {
-                int returnToType = APPLICATION_ACTIVITY_TYPE;
+                // 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;
                 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/ActivityStackSupervisor.java b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
index 0e4c9a4..52c002d 100644
--- a/services/core/java/com/android/server/am/ActivityStackSupervisor.java
+++ b/services/core/java/com/android/server/am/ActivityStackSupervisor.java
@@ -1097,21 +1097,7 @@
             // Don't debug things in the system process
             if (!aInfo.processName.equals("system")) {
                 if ((startFlags & ActivityManager.START_FLAG_DEBUG) != 0) {
-                    final ProcessRecord app = mService.getProcessRecordLocked(
-                            aInfo.processName, aInfo.applicationInfo.uid, true);
-                    // If the process already started, we can't wait for debugger and shouldn't
-                    // modify the debug settings.
-                    // For non-persistent debug, normally we set the debug app here, and restores
-                    // to the original at attachApplication time. However, if the app process
-                    // already exists, we won't get another attachApplication, and the debug setting
-                    // never gets restored. Furthermore, if we get two such calls back-to-back,
-                    // both mOrigDebugApp and mDebugApp will become the same app, and it won't be
-                    // cleared even if we get attachApplication after the app process is killed.
-                    if (app == null || app.thread == null) {
-                        mService.setDebugApp(aInfo.processName, true, false);
-                    } else {
-                        Slog.w(TAG, "Ignoring waitForDebugger because process already exists");
-                    }
+                    mService.setDebugApp(aInfo.processName, true, false);
                 }
 
                 if ((startFlags & ActivityManager.START_FLAG_NATIVE_DEBUGGING) != 0) {
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/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index 61b1317..522e42b 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -166,8 +166,9 @@
     private Intent mNewTaskIntent;
     private ActivityStack mSourceStack;
     private ActivityStack mTargetStack;
-    // TODO: Is the mMoveHome flag really needed?
-    private boolean mMovedHome;
+    // Indicates that we moved other task and are going to put something on top soon, so
+    // we don't want to show it redundantly or accidentally change what's shown below.
+    private boolean mMovedOtherTask;
     private boolean mMovedToFront;
     private boolean mNoAnimation;
     private boolean mKeepCurTransition;
@@ -204,7 +205,7 @@
         mSourceStack = null;
 
         mTargetStack = null;
-        mMovedHome = false;
+        mMovedOtherTask = false;
         mMovedToFront = false;
         mNoAnimation = false;
         mKeepCurTransition = false;
@@ -1013,7 +1014,6 @@
                 resumeTargetStackIfNeeded();
                 return START_RETURN_INTENT_TO_CALLER;
             }
-
             setTaskFromIntentActivity(mReusedActivity);
 
             if (!mAddingToTask && mReuseTask == null) {
@@ -1082,7 +1082,7 @@
                 Slog.e(TAG, "Attempted Lock Task Mode violation mStartActivity=" + mStartActivity);
                 return START_RETURN_LOCK_TASK_MODE_VIOLATION;
             }
-            if (!mMovedHome) {
+            if (!mMovedOtherTask) {
                 updateTaskReturnToType(mStartActivity.task, mLaunchFlags, topStack);
             }
         } else if (mSourceRecord != null) {
@@ -1443,7 +1443,7 @@
                 if (mLaunchTaskBehind && mSourceRecord != null) {
                     intentActivity.setTaskToAffiliateWith(mSourceRecord.task);
                 }
-                mMovedHome = true;
+                mMovedOtherTask = true;
 
                 // If the launch flags carry both NEW_TASK and CLEAR_TASK, the task's activities
                 // will be cleared soon by ActivityStarter in setTaskFromIntentActivity().
@@ -1521,6 +1521,10 @@
             mReuseTask = intentActivity.task;
             mReuseTask.performClearTaskLocked();
             mReuseTask.setIntent(mStartActivity);
+            // When we clear the task - focus will be adjusted, which will bring another task
+            // to top before we launch the activity we need. This will temporary swap their
+            // mTaskToReturnTo values and we don't want to overwrite them accidentally.
+            mMovedOtherTask = true;
         } else if ((mLaunchFlags & FLAG_ACTIVITY_CLEAR_TOP) != 0
                 || mLaunchSingleInstance || mLaunchSingleTask) {
             ActivityRecord top = intentActivity.task.performClearTaskLocked(mStartActivity,
diff --git a/services/core/java/com/android/server/am/RecentTasks.java b/services/core/java/com/android/server/am/RecentTasks.java
index cea76f2..ab5d4b6 100644
--- a/services/core/java/com/android/server/am/RecentTasks.java
+++ b/services/core/java/com/android/server/am/RecentTasks.java
@@ -621,6 +621,9 @@
         for (int i = 0; i < recentsCount; i++) {
             final TaskRecord tr = get(i);
             if (task != tr) {
+                if (task.stack != tr.stack) {
+                    continue;
+                }
                 if (task.userId != tr.userId) {
                     continue;
                 }
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/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 87141b4..f2fde0f 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -102,11 +102,11 @@
 import android.Manifest;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
+import android.annotation.UserIdInt;
 import android.app.ActivityManager;
 import android.app.ActivityManagerNative;
 import android.app.IActivityManager;
 import android.app.ResourcesManager;
-import android.app.admin.DevicePolicyManagerInternal;
 import android.app.admin.IDevicePolicyManager;
 import android.app.admin.SecurityLog;
 import android.app.backup.IBackupManager;
@@ -622,6 +622,8 @@
     @GuardedBy("mPackages")
     final ArraySet<String> mFrozenPackages = new ArraySet<>();
 
+    final ProtectedPackages mProtectedPackages = new ProtectedPackages();
+
     boolean mRestoredSettings;
 
     // System configuration read by SystemConfig.
@@ -16338,8 +16340,9 @@
                 for (int curUser : users) {
                     long timeout = SystemClock.uptimeMillis() + 5000;
                     synchronized (conn) {
-                        long now = SystemClock.uptimeMillis();
-                        while (conn.mContainerService == null && now < timeout) {
+                        long now;
+                        while (conn.mContainerService == null &&
+                                (now = SystemClock.uptimeMillis()) < timeout) {
                             try {
                                 conn.wait(timeout - now);
                             } catch (InterruptedException e) {
@@ -16393,9 +16396,7 @@
         enforceCrossUserPermission(Binder.getCallingUid(), userId,
                 true /* requireFullPermission */, false /* checkShell */, "clear application data");
 
-        final DevicePolicyManagerInternal dpmi = LocalServices
-                .getService(DevicePolicyManagerInternal.class);
-        if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+        if (mProtectedPackages.canPackageBeWiped(userId, packageName)) {
             throw new SecurityException("Cannot clear data for a device owner or a profile owner");
         }
         // Queue up an async operation since the package deletion may take a little while.
@@ -17722,10 +17723,8 @@
                         + Binder.getCallingPid()
                         + ", uid=" + uid + ", package uid=" + pkgSetting.appId);
             }
-            // Don't allow changing profile and device owners. Calling into DPMS, so no locking.
-            final DevicePolicyManagerInternal dpmi = LocalServices
-                    .getService(DevicePolicyManagerInternal.class);
-            if (dpmi != null && dpmi.hasDeviceOwnerOrProfileOwner(packageName, userId)) {
+            // Don't allow changing profile and device owners.
+            if (mProtectedPackages.canPackageStateBeChanged(userId, packageName)) {
                 throw new SecurityException("Cannot disable a device owner or a profile owner");
             }
         }
@@ -20822,6 +20821,20 @@
                 int userId) {
             return PackageManagerService.this.getHomeActivitiesAsUser(allHomeCandidates, userId);
         }
+
+        @Override
+        public void setDeviceAndProfileOwnerPackages(
+                int deviceOwnerUserId, String deviceOwnerPackage,
+                SparseArray<String> profileOwnerPackages) {
+            mProtectedPackages.setDeviceAndProfileOwnerPackages(
+                    deviceOwnerUserId, deviceOwnerPackage, profileOwnerPackages);
+        }
+
+        @Override
+        public boolean canPackageBeWiped(int userId, String packageName) {
+            return mProtectedPackages.canPackageBeWiped(userId,
+                    packageName);
+        }
     }
 
     @Override
diff --git a/services/core/java/com/android/server/pm/ProtectedPackages.java b/services/core/java/com/android/server/pm/ProtectedPackages.java
new file mode 100644
index 0000000..7bdea18
--- /dev/null
+++ b/services/core/java/com/android/server/pm/ProtectedPackages.java
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.server.pm;
+
+import android.annotation.UserIdInt;
+import android.os.UserHandle;
+import android.util.SparseArray;
+
+/**
+ * Manages package names that need special protection.
+ *
+ * TODO: This class should persist the information by itself, and also keeps track of device admin
+ * packages for all users.  Then PMS.isPackageDeviceAdmin() should use it instead of talking
+ * to DPMS.
+ */
+public class ProtectedPackages {
+    @UserIdInt
+    private int mDeviceOwnerUserId;
+
+    private String mDeviceOwnerPackage;
+
+    private SparseArray<String> mProfileOwnerPackages;
+
+    private final Object mLock = new Object();
+
+    /**
+     * Sets the device/profile owner information.
+     */
+    public void setDeviceAndProfileOwnerPackages(
+            int deviceOwnerUserId, String deviceOwnerPackage,
+            SparseArray<String> profileOwnerPackages) {
+        synchronized (mLock) {
+            mDeviceOwnerUserId = deviceOwnerUserId;
+            mDeviceOwnerPackage =
+                    (deviceOwnerUserId == UserHandle.USER_NULL) ? null : deviceOwnerPackage;
+            mProfileOwnerPackages = (profileOwnerPackages == null) ? null
+                    : profileOwnerPackages.clone();
+        }
+    }
+
+    private boolean hasDeviceOwnerOrProfileOwner(int userId, String packageName) {
+        if (packageName == null) {
+            return false;
+        }
+        synchronized (mLock) {
+            if (mDeviceOwnerPackage != null) {
+                if ((mDeviceOwnerUserId == userId)
+                        && (packageName.equals(mDeviceOwnerPackage))) {
+                    return true;
+                }
+            }
+            if (mProfileOwnerPackages != null) {
+                if (packageName.equals(mProfileOwnerPackages.get(userId))) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Whether a package or the components in a package's enabled state can be changed
+     * by other callers than itself.
+     */
+    public boolean canPackageStateBeChanged(@UserIdInt int userId, String packageName) {
+        return hasDeviceOwnerOrProfileOwner(userId, packageName);
+    }
+
+    /**
+     * Whether a package's data be cleared.
+     */
+    public boolean canPackageBeWiped(@UserIdInt int userId, String packageName) {
+        return hasDeviceOwnerOrProfileOwner(userId, packageName);
+    }
+}
diff --git a/services/core/java/com/android/server/pm/UserManagerService.java b/services/core/java/com/android/server/pm/UserManagerService.java
index b916790..dd34ebcf 100644
--- a/services/core/java/com/android/server/pm/UserManagerService.java
+++ b/services/core/java/com/android/server/pm/UserManagerService.java
@@ -30,6 +30,7 @@
 import android.app.IActivityManager;
 import android.app.IStopUserCallback;
 import android.app.KeyguardManager;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
@@ -167,6 +168,12 @@
     private static final String RESTRICTIONS_FILE_PREFIX = "res_";
     private static final String XML_SUFFIX = ".xml";
 
+    private static final int ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION =
+            UserInfo.FLAG_MANAGED_PROFILE
+            | UserInfo.FLAG_EPHEMERAL
+            | UserInfo.FLAG_RESTRICTED
+            | UserInfo.FLAG_GUEST;
+
     private static final int MIN_USER_ID = 10;
     // We need to keep process uid within Integer.MAX_VALUE.
     private static final int MAX_USER_ID = Integer.MAX_VALUE / UserHandle.PER_USER_RANGE;
@@ -322,6 +329,27 @@
 
     private final LockPatternUtils mLockPatternUtils;
 
+    private final String ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK =
+            "com.android.server.pm.DISABLE_QUIET_MODE_AFTER_UNLOCK";
+
+    private final BroadcastReceiver mDisableQuietModeCallback = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK.equals(intent.getAction())) {
+                final IntentSender target = intent.getParcelableExtra(Intent.EXTRA_INTENT);
+                final int userHandle = intent.getIntExtra(Intent.EXTRA_USER_ID, 0);
+                setQuietModeEnabled(userHandle, false);
+                if (target != null) {
+                    try {
+                        mContext.startIntentSender(target, null, 0, 0, 0);
+                    } catch (IntentSender.SendIntentException e) {
+                        /* ignore */
+                    }
+                }
+            }
+        }
+    };
+
     /**
      * Whether all users should be created ephemeral.
      */
@@ -414,6 +442,9 @@
             // user restriction was not a default guest restriction.
             setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, currentGuestUser.id);
         }
+        mContext.registerReceiver(mDisableQuietModeCallback,
+                new IntentFilter(ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK),
+                null, mHandler);
     }
 
     @Override
@@ -465,7 +496,7 @@
 
     @Override
     public @NonNull List<UserInfo> getUsers(boolean excludeDying) {
-        checkManageUsersPermission("query users");
+        checkManageOrCreateUsersPermission("query users");
         synchronized (mUsersLock) {
             ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
             final int userSize = mUsers.size();
@@ -703,6 +734,7 @@
 
     @Override
     public boolean trySetQuietModeDisabled(int userHandle, IntentSender target) {
+        checkManageUsersPermission("silence profile");
         if (StorageManager.isUserKeyUnlocked(userHandle)
                 || !mLockPatternUtils.isSecure(userHandle)) {
             // if the user is already unlocked, no need to show a profile challenge
@@ -723,9 +755,24 @@
             if (unlockIntent == null) {
                 return false;
             }
+            final Intent callBackIntent = new Intent(
+                    ACTION_DISABLE_QUIET_MODE_AFTER_UNLOCK);
             if (target != null) {
-                unlockIntent.putExtra(Intent.EXTRA_INTENT, target);
+                callBackIntent.putExtra(Intent.EXTRA_INTENT, target);
             }
+            callBackIntent.putExtra(Intent.EXTRA_USER_ID, userHandle);
+            callBackIntent.setPackage(mContext.getPackageName());
+            callBackIntent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND);
+            final PendingIntent pendingIntent = PendingIntent.getBroadcast(
+                    mContext,
+                    0,
+                    callBackIntent,
+                    PendingIntent.FLAG_CANCEL_CURRENT |
+                            PendingIntent.FLAG_ONE_SHOT |
+                            PendingIntent.FLAG_IMMUTABLE);
+            // After unlocking the challenge, it will disable quiet mode and run the original
+            // intentSender
+            unlockIntent.putExtra(Intent.EXTRA_INTENT, pendingIntent.getIntentSender());
             unlockIntent.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);
             mContext.startActivity(unlockIntent);
         } finally {
@@ -1407,6 +1454,41 @@
     }
 
     /**
+     * Enforces that only the system UID or root's UID or apps that have the
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
+     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}
+     * can make certain calls to the UserManager.
+     *
+     * @param message used as message if SecurityException is thrown
+     * @throws SecurityException if the caller is not system or root
+     * @see #hasManageOrCreateUsersPermission()
+     */
+    private static final void checkManageOrCreateUsersPermission(String message) {
+        if (!hasManageOrCreateUsersPermission()) {
+            throw new SecurityException(
+                    "You either need MANAGE_USERS or CREATE_USERS permission to: " + message);
+        }
+    }
+
+    /**
+     * Similar to {@link #checkManageOrCreateUsersPermission(String)} but when the caller is tries
+     * to create user/profiles other than what is allowed for
+     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS} permission, then it will only
+     * allow callers with {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} permission.
+     */
+    private static final void checkManageOrCreateUsersPermission(int creationFlags) {
+        if ((creationFlags & ~ALLOWED_FLAGS_FOR_CREATE_USERS_PERMISSION) == 0) {
+            if (!hasManageOrCreateUsersPermission()) {
+                throw new SecurityException("You either need MANAGE_USERS or CREATE_USERS "
+                        + "permission to create an user with flags: " + creationFlags);
+            }
+        } else if (!hasManageUsersPermission()) {
+            throw new SecurityException("You need MANAGE_USERS permission to create an user "
+                    + " with flags: " + creationFlags);
+        }
+    }
+
+    /**
      * @return whether the calling UID is system UID or root's UID or the calling app has the
      * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS}.
      */
@@ -1420,6 +1502,23 @@
     }
 
     /**
+     * @return whether the calling UID is system UID or root's UID or the calling app has the
+     * {@link android.Manifest.permission#MANAGE_USERS MANAGE_USERS} or
+     * {@link android.Manifest.permission#CREATE_USERS CREATE_USERS}.
+     */
+    private static final boolean hasManageOrCreateUsersPermission() {
+        final int callingUid = Binder.getCallingUid();
+        return UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)
+                || callingUid == Process.ROOT_UID
+                || ActivityManager.checkComponentPermission(
+                        android.Manifest.permission.MANAGE_USERS,
+                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED
+                || ActivityManager.checkComponentPermission(
+                        android.Manifest.permission.CREATE_USERS,
+                        callingUid, -1, true) == PackageManager.PERMISSION_GRANTED;
+    }
+
+    /**
      * Enforces that only the system UID or root's UID (on any user) can make certain calls to the
      * UserManager.
      *
@@ -2005,13 +2104,13 @@
 
     @Override
     public UserInfo createProfileForUser(String name, int flags, int userId) {
-        checkManageUsersPermission("Only the system can create users");
+        checkManageOrCreateUsersPermission(flags);
         return createUserInternal(name, flags, userId);
     }
 
     @Override
     public UserInfo createUser(String name, int flags) {
-        checkManageUsersPermission("Only the system can create users");
+        checkManageOrCreateUsersPermission(flags);
         return createUserInternal(name, flags, UserHandle.USER_NULL);
     }
 
@@ -2255,7 +2354,7 @@
      */
     @Override
     public boolean removeUser(int userHandle) {
-        checkManageUsersPermission("Only the system can remove users");
+        checkManageOrCreateUsersPermission("Only the system can remove users");
         if (getUserRestrictions(UserHandle.getCallingUserId()).getBoolean(
                 UserManager.DISALLOW_REMOVE_USER, false)) {
             Log.w(LOG_TAG, "Cannot remove user. DISALLOW_REMOVE_USER is enabled.");
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 6987744..568f94c 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -2589,8 +2589,13 @@
             final PhoneWindow win = new PhoneWindow(context);
             win.setIsStartingWindow(true);
 
-            final Resources r = context.getResources();
-            win.setTitle(r.getText(labelRes, nonLocalizedLabel));
+            CharSequence label = context.getResources().getText(labelRes, null);
+            // Only change the accessibility title if the label is localized
+            if (label != null) {
+                win.setTitle(label, true);
+            } else {
+                win.setTitle(nonLocalizedLabel, false);
+            }
 
             win.setType(
                 WindowManager.LayoutParams.TYPE_APPLICATION_STARTING);
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index 3700c71..b4c4bd8 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -46,11 +46,12 @@
 import android.service.vr.IVrManager;
 import android.service.vr.IVrStateCallbacks;
 import android.service.vr.VrListenerService;
+import android.util.ArrayMap;
 import android.util.ArraySet;
 import android.util.Slog;
 import android.util.SparseArray;
-
 import com.android.internal.R;
+import com.android.server.LocalServices;
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.utils.ManagedApplicationService.PendingEvent;
@@ -67,6 +68,7 @@
 import java.util.Collection;
 import java.util.Date;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -197,29 +199,44 @@
 
     private final class NotificationAccessManager {
         private final SparseArray<ArraySet<String>> mAllowedPackages = new SparseArray<>();
+        private final ArrayMap<String, Integer> mNotificationAccessPackageToUserId =
+                new ArrayMap<>();
 
         public void update(Collection<String> packageNames) {
             int currentUserId = ActivityManager.getCurrentUser();
 
-            UserHandle currentUserHandle = new UserHandle(currentUserId);
-
             ArraySet<String> allowed = mAllowedPackages.get(currentUserId);
             if (allowed == null) {
                 allowed = new ArraySet<>();
             }
 
+            // Make sure we revoke notification access for listeners in other users
+            final int listenerCount = mNotificationAccessPackageToUserId.size();
+            for (int i = listenerCount - 1; i >= 0; i--) {
+                final int grantUserId = mNotificationAccessPackageToUserId.valueAt(i);
+                if (grantUserId != currentUserId) {
+                    String packageName = mNotificationAccessPackageToUserId.keyAt(i);
+                    revokeNotificationListenerAccess(packageName, grantUserId);
+                    revokeNotificationPolicyAccess(packageName);
+                    revokeCoarseLocationPermissionIfNeeded(packageName, grantUserId);
+                    mNotificationAccessPackageToUserId.removeAt(i);
+                }
+            }
+
             for (String pkg : allowed) {
                 if (!packageNames.contains(pkg)) {
-                    revokeNotificationListenerAccess(pkg);
+                    revokeNotificationListenerAccess(pkg, currentUserId);
                     revokeNotificationPolicyAccess(pkg);
-                    revokeCoarseLocationAccess(pkg, currentUserHandle);
+                    revokeCoarseLocationPermissionIfNeeded(pkg, currentUserId);
+                    mNotificationAccessPackageToUserId.remove(pkg);
                 }
             }
             for (String pkg : packageNames) {
                 if (!allowed.contains(pkg)) {
                     grantNotificationPolicyAccess(pkg);
-                    grantNotificationListenerAccess(pkg, currentUserHandle);
-                    grantCoarseLocationAccess(pkg, currentUserHandle);
+                    grantNotificationListenerAccess(pkg, currentUserId);
+                    grantCoarseLocationPermissionIfNeeded(pkg, currentUserId);
+                    mNotificationAccessPackageToUserId.put(pkg, currentUserId);
                 }
             }
 
@@ -229,7 +246,6 @@
         }
     }
 
-
     /**
      * Called when a user, package, or setting changes that could affect whether or not the
      * currently bound VrListenerService is changed.
@@ -535,17 +551,33 @@
         }
     }
 
-    private void updateOverlayStateLocked(ComponentName exemptedComponent) {
+    private void updateOverlayStateLocked(String exemptedPackage, int newUserId, int oldUserId) {
+        AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
+
+        // If user changed drop restrictions for the old user.
+        if (oldUserId != newUserId) {
+            appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+                    false, mOverlayToken, null, oldUserId);
+        }
+
+        // Apply the restrictions for the current user based on vr state
+        String[] exemptions = (exemptedPackage == null) ? new String[0] :
+                new String[] { exemptedPackage };
+
+        appOpsManager.setUserRestrictionForUser(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
+                mVrModeEnabled, mOverlayToken, exemptions, newUserId);
+    }
+
+    private void updateDependentAppOpsLocked(String newVrServicePackage, int newUserId,
+            String oldVrServicePackage, int oldUserId) {
+        // If VR state changed and we also have a VR service change.
+        if (Objects.equals(newVrServicePackage, oldVrServicePackage)) {
+            return;
+        }
         final long identity = Binder.clearCallingIdentity();
         try {
-            AppOpsManager appOpsManager = getContext().getSystemService(AppOpsManager.class);
-            if (appOpsManager != null) {
-                String[] exemptions = (exemptedComponent == null) ? new String[0] :
-                        new String[] { exemptedComponent.getPackageName() };
-
-                appOpsManager.setUserRestriction(AppOpsManager.OP_SYSTEM_ALERT_WINDOW,
-                        mVrModeEnabled, mOverlayToken, exemptions);
-            }
+            // Set overlay exception state based on VR enabled and current service
+            updateOverlayStateLocked(newVrServicePackage, newUserId, oldUserId);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -578,8 +610,12 @@
                 return validUserComponent; // Disabled -> Disabled transition does nothing.
             }
 
+            String oldVrServicePackage = mCurrentVrService != null
+                    ? mCurrentVrService.getComponent().getPackageName() : null;
+            final int oldUserId = mCurrentVrModeUser;
+
             // Always send mode change events.
-            changeVrModeLocked(enabled, (enabled && validUserComponent) ? component : null);
+            changeVrModeLocked(enabled);
 
             if (!enabled || !validUserComponent) {
                 // Unbind whatever is running
@@ -606,12 +642,25 @@
                 }
             }
 
-            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent))  {
+            if (calling != null && !Objects.equals(calling, mCurrentVrModeComponent)) {
                 mCurrentVrModeComponent = calling;
+                sendUpdatedCaller = true;
+            }
+
+            if (mCurrentVrModeUser != userId) {
                 mCurrentVrModeUser = userId;
                 sendUpdatedCaller = true;
             }
 
+            String newVrServicePackage = mCurrentVrService != null
+                    ? mCurrentVrService.getComponent().getPackageName() : null;
+            final int newUserId = mCurrentVrModeUser;
+
+            // Update AppOps settings that change state when entering/exiting VR mode, or changing
+            // the current VrListenerService.
+            updateDependentAppOpsLocked(newVrServicePackage, newUserId,
+                    oldVrServicePackage, oldUserId);
+
             if (mCurrentVrService != null && sendUpdatedCaller) {
                 final ComponentName c = mCurrentVrModeComponent;
                 mCurrentVrService.sendEvent(new PendingEvent() {
@@ -645,18 +694,6 @@
         return true;
     }
 
-    private void grantCoarseLocationAccess(String pkg, UserHandle userId) {
-        PackageManager pm = mContext.getPackageManager();
-        pm.grantRuntimePermission(pkg, android.Manifest.permission.ACCESS_COARSE_LOCATION,
-                userId);
-    }
-
-    private void revokeCoarseLocationAccess(String pkg, UserHandle userId) {
-        PackageManager pm = mContext.getPackageManager();
-        pm.revokeRuntimePermission(pkg,
-                android.Manifest.permission.ACCESS_COARSE_LOCATION, userId);
-    }
-
     private void grantNotificationPolicyAccess(String pkg) {
         NotificationManager nm = mContext.getSystemService(NotificationManager.class);
         nm.setNotificationPolicyAccessGranted(pkg, true);
@@ -670,14 +707,14 @@
         nm.setNotificationPolicyAccessGranted(pkg, false);
     }
 
-    private void grantNotificationListenerAccess(String pkg, UserHandle userId) {
+    private void grantNotificationListenerAccess(String pkg, int userId) {
         PackageManager pm = mContext.getPackageManager();
         ArraySet<ComponentName> possibleServices = EnabledComponentsObserver.loadComponentNames(pm,
-                userId.getIdentifier(), NotificationListenerService.SERVICE_INTERFACE,
+                userId, NotificationListenerService.SERVICE_INTERFACE,
                 android.Manifest.permission.BIND_NOTIFICATION_LISTENER_SERVICE);
         ContentResolver resolver = mContext.getContentResolver();
 
-        ArraySet<String> current = getCurrentNotifListeners(resolver);
+        ArraySet<String> current = getNotificationListeners(resolver, userId);
 
         for (ComponentName c : possibleServices) {
             String flatName = c.flattenToString();
@@ -689,14 +726,16 @@
 
         if (current.size() > 0) {
             String flatSettings = formatSettings(current);
-            Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                    flatSettings);
+            Settings.Secure.putStringForUser(resolver,
+                    Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+                    flatSettings, userId);
         }
     }
 
-    private void revokeNotificationListenerAccess(String pkg) {
+    private void revokeNotificationListenerAccess(String pkg, int userId) {
         ContentResolver resolver = mContext.getContentResolver();
-        ArraySet<String> current = getCurrentNotifListeners(resolver);
+
+        ArraySet<String> current = getNotificationListeners(resolver, userId);
 
         ArrayList<String> toRemove = new ArrayList<>();
 
@@ -710,14 +749,37 @@
         current.removeAll(toRemove);
 
         String flatSettings = formatSettings(current);
-        Settings.Secure.putString(resolver, Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
-                flatSettings);
-
+        Settings.Secure.putStringForUser(resolver,
+                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS,
+                flatSettings, userId);
     }
 
-    private ArraySet<String> getCurrentNotifListeners(ContentResolver resolver) {
-        String flat = Settings.Secure.getString(resolver,
-                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS);
+    private void grantCoarseLocationPermissionIfNeeded(String pkg, int userId) {
+        // Don't clobber the user if permission set in current state explicitly
+        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
+            mContext.getPackageManager().grantRuntimePermission(pkg,
+                    Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+        }
+    }
+
+    private void revokeCoarseLocationPermissionIfNeeded(String pkg, int userId) {
+        // Don't clobber the user if permission set in current state explicitly
+        if (!isPermissionUserUpdated(Manifest.permission.ACCESS_COARSE_LOCATION, pkg, userId)) {
+            mContext.getPackageManager().revokeRuntimePermission(pkg,
+                    Manifest.permission.ACCESS_COARSE_LOCATION, new UserHandle(userId));
+        }
+    }
+
+    private boolean isPermissionUserUpdated(String permission, String pkg, int userId) {
+        final int flags = mContext.getPackageManager().getPermissionFlags(
+                permission, pkg, new UserHandle(userId));
+        return (flags & (PackageManager.FLAG_PERMISSION_USER_SET
+                | PackageManager.FLAG_PERMISSION_USER_FIXED)) != 0;
+    }
+
+    private ArraySet<String> getNotificationListeners(ContentResolver resolver, int userId) {
+        String flat = Settings.Secure.getStringForUser(resolver,
+                Settings.Secure.ENABLED_NOTIFICATION_LISTENERS, userId);
 
         ArraySet<String> current = new ArraySet<>();
         if (flat != null) {
@@ -763,9 +825,8 @@
      * Note: Must be called while holding {@code mLock}.
      *
      * @param enabled new state of the VR mode.
-     * @param exemptedComponent a component to exempt from AppOps restrictions for overlays.
      */
-    private void changeVrModeLocked(boolean enabled, ComponentName exemptedComponent) {
+    private void changeVrModeLocked(boolean enabled) {
         if (mVrModeEnabled != enabled) {
             mVrModeEnabled = enabled;
 
@@ -773,7 +834,6 @@
             Slog.i(TAG, "VR mode " + ((mVrModeEnabled) ? "enabled" : "disabled"));
             setVrModeNative(mVrModeEnabled);
 
-            updateOverlayStateLocked(exemptedComponent);
             onVrModeChangedLocked();
         }
     }
diff --git a/services/core/java/com/android/server/wm/AccessibilityController.java b/services/core/java/com/android/server/wm/AccessibilityController.java
index 101f56f..8be5dfb 100644
--- a/services/core/java/com/android/server/wm/AccessibilityController.java
+++ b/services/core/java/com/android/server/wm/AccessibilityController.java
@@ -1203,9 +1203,6 @@
             window.layer = windowState.mLayer;
             window.token = windowState.mClient.asBinder();
             window.title = windowState.mAttrs.accessibilityTitle;
-            if (window.title == null) {
-                window.title = windowState.mAttrs.getTitle();
-            }
             window.accessibilityIdOfAnchor = windowState.mAttrs.accessibilityIdOfAnchor;
 
             WindowState attachedWindow = windowState.mAttachedWindow;
diff --git a/services/core/java/com/android/server/wm/WindowStateAnimator.java b/services/core/java/com/android/server/wm/WindowStateAnimator.java
index e46ed8d..36d9697 100644
--- a/services/core/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/core/java/com/android/server/wm/WindowStateAnimator.java
@@ -824,22 +824,11 @@
             mTmpSize.bottom = mTmpSize.top + 1;
         }
 
-        final int displayId = w.getDisplayId();
-        float scale = 1.0f;
-        // Magnification is supported only for the default display.
-        if (mService.mAccessibilityController != null && displayId == DEFAULT_DISPLAY) {
-            final MagnificationSpec spec =
-                    mService.mAccessibilityController.getMagnificationSpecForWindowLocked(w);
-            if (spec != null && !spec.isNop()) {
-                scale = spec.scale;
-            }
-        }
-
         // Adjust for surface insets.
-        mTmpSize.left -= scale * attrs.surfaceInsets.left;
-        mTmpSize.top -= scale * attrs.surfaceInsets.top;
-        mTmpSize.right += scale * attrs.surfaceInsets.right;
-        mTmpSize.bottom += scale * attrs.surfaceInsets.bottom;
+        mTmpSize.left -= attrs.surfaceInsets.left;
+        mTmpSize.top -= attrs.surfaceInsets.top;
+        mTmpSize.right += attrs.surfaceInsets.right;
+        mTmpSize.bottom += attrs.surfaceInsets.bottom;
     }
 
     boolean hasSurface() {
@@ -1300,9 +1289,13 @@
     void updateSurfaceWindowCrop(Rect clipRect, Rect finalClipRect, boolean recoveringMemory) {
         if (DEBUG_WINDOW_CROP) Slog.d(TAG, "updateSurfaceWindowCrop: win=" + mWin
                 + " clipRect=" + clipRect + " finalClipRect=" + finalClipRect);
-        if (!clipRect.equals(mLastClipRect)) {
-            mLastClipRect.set(clipRect);
-            mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
+        if (clipRect != null) {
+            if (!clipRect.equals(mLastClipRect)) {
+                mLastClipRect.set(clipRect);
+                mSurfaceController.setCropInTransaction(clipRect, recoveringMemory);
+            }
+        } else {
+            mSurfaceController.clearCropInTransaction(recoveringMemory);
         }
         if (!finalClipRect.equals(mLastFinalClipRect)) {
             mLastFinalClipRect.set(finalClipRect);
@@ -1314,7 +1307,6 @@
     }
 
     private int resolveStackClip() {
-
         // App animation overrides window animation stack clip mode.
         if (mAppAnimator != null && mAppAnimator.animation != null) {
             return mAppAnimator.getStackClip();
@@ -1420,6 +1412,9 @@
         // aren't observing known issues here outside of PiP resizing. (Typically
         // the other windows that use -1 are PopupWindows which aren't likely
         // to be rendering while we resize).
+
+        boolean wasForceScaled = mForceScaleUntilResize;
+
         if (!w.inPinnedWorkspace() || (!w.mRelayoutCalled || w.mInRelayout)) {
             mSurfaceResized = mSurfaceController.setSizeInTransaction(
                     mTmpSize.width(), mTmpSize.height(), recoveringMemory);
@@ -1428,13 +1423,17 @@
         }
         mForceScaleUntilResize = mForceScaleUntilResize && !mSurfaceResized;
 
-
         calculateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect);
+
+        float surfaceWidth = mSurfaceController.getWidth();
+        float surfaceHeight = mSurfaceController.getHeight();
+
         if ((task != null && task.mStack.getForceScaleToCrop()) || mForceScaleUntilResize) {
             int hInsets = w.getAttrs().surfaceInsets.left + w.getAttrs().surfaceInsets.right;
             int vInsets = w.getAttrs().surfaceInsets.top + w.getAttrs().surfaceInsets.bottom;
-            float surfaceWidth = mSurfaceController.getWidth();
-            float surfaceHeight = mSurfaceController.getHeight();
+            if (!mForceScaleUntilResize) {
+                mSurfaceController.forceScaleableInTransaction(true);
+            }
             // We want to calculate the scaling based on the content area, not based on
             // the entire surface, so that we scale in sync with windows that don't have insets.
             mExtraHScale = (mTmpClipRect.width() - hInsets) / (float)(surfaceWidth - hInsets);
@@ -1455,7 +1454,8 @@
             posX += w.getAttrs().surfaceInsets.left * (1 - mExtraHScale);
             posY += w.getAttrs().surfaceInsets.top * (1 - mExtraVScale);
 
-            mSurfaceController.setPositionInTransaction(posX, posY, recoveringMemory);
+            mSurfaceController.setPositionInTransaction((float)Math.floor(posX),
+                    (float)Math.floor(posY), recoveringMemory);
 
             // Since we are scaled to fit in our previously desired crop, we can now
             // expose the whole window in buffer space, and not risk extending
@@ -1467,7 +1467,7 @@
             // We need to ensure for each surface, that we disable transformation matrix
             // scaling in the same transaction which we resize the surface in.
             // As we are in SCALING_MODE_SCALE_TO_WINDOW, SurfaceFlinger will
-            // then take over the scaling until the new buffer arrives, and things 
+            // then take over the scaling until the new buffer arrives, and things
             // will be seamless.
             mForceScaleUntilResize = true;
         } else {
@@ -1475,7 +1475,25 @@
                     recoveringMemory);
         }
 
-        updateSurfaceWindowCrop(mTmpClipRect, mTmpFinalClipRect, recoveringMemory);
+        // If we are ending the scaling mode. We switch to SCALING_MODE_FREEZE
+        // to prevent further updates until buffer latch. Normally position
+        // would continue to apply immediately. But we need a different position
+        // before and after resize (since we have scaled the shadows, as discussed
+        // above).
+        if (wasForceScaled && !mForceScaleUntilResize) {
+            mSurfaceController.setPositionAppliesWithResizeInTransaction(true);
+            mSurfaceController.forceScaleableInTransaction(false);
+        }
+
+        Rect clipRect = mTmpClipRect;
+        if (w.inPinnedWorkspace()) {
+            clipRect = null;
+            task.mStack.getDimBounds(mTmpFinalClipRect);
+            mTmpFinalClipRect.inset(-w.mAttrs.surfaceInsets.left, -w.mAttrs.surfaceInsets.top,
+                    -w.mAttrs.surfaceInsets.right, -w.mAttrs.surfaceInsets.bottom);
+        }
+
+        updateSurfaceWindowCrop(clipRect, mTmpFinalClipRect, recoveringMemory);
 
         mSurfaceController.setMatrixInTransaction(mDsDx * w.mHScale * mExtraHScale,
                 mDtDx * w.mVScale * mExtraVScale,
diff --git a/services/core/java/com/android/server/wm/WindowSurfaceController.java b/services/core/java/com/android/server/wm/WindowSurfaceController.java
index 9646a49..fd0bb99 100644
--- a/services/core/java/com/android/server/wm/WindowSurfaceController.java
+++ b/services/core/java/com/android/server/wm/WindowSurfaceController.java
@@ -26,6 +26,7 @@
 import static android.view.Surface.SCALING_MODE_FREEZE;
 import static android.view.Surface.SCALING_MODE_SCALE_TO_WINDOW;
 
+import android.graphics.PixelFormat;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -78,7 +79,15 @@
 
         title = name;
 
-        if (DEBUG_SURFACE_TRACE) {
+        // For opaque child windows placed under parent windows,
+        // we use a special SurfaceControl which mirrors commands
+        // to a black-out layer placed one Z-layer below the surface.
+        // This prevents holes to whatever app/wallpaper is underneath.
+        if (animator.mWin.isChildWindow() &&
+                animator.mWin.mSubLayer < 0) {
+            mSurfaceControl = new SurfaceControlWithBackground(s,
+                    name, w, h, format, flags);
+        } else if (DEBUG_SURFACE_TRACE) {
             mSurfaceControl = new SurfaceTrace(
                     s, name, w, h, format, flags);
         } else {
@@ -194,6 +203,20 @@
         }
     }
 
+    void clearCropInTransaction(boolean recoveringMemory) {
+        if (SHOW_TRANSACTIONS) logSurface(
+                "CLEAR CROP", null);
+        try {
+            Rect clipRect = new Rect(0, 0, -1, -1);
+            mSurfaceControl.setWindowCrop(clipRect);
+        } catch (RuntimeException e) {
+            Slog.w(TAG, "Error setting clearing crop of " + this, e);
+            if (!recoveringMemory) {
+                mAnimator.reclaimSomeSurfaceMemory("crop", true);
+            }
+        }
+    }
+
     void setFinalCropInTransaction(Rect clipRect) {
         if (SHOW_TRANSACTIONS) logSurface(
                 "FINAL CROP " + clipRect.toShortString(), null);
@@ -236,6 +259,10 @@
         }
     }
 
+    void setPositionAppliesWithResizeInTransaction(boolean recoveringMemory) {
+        mSurfaceControl.setPositionAppliesWithResize();
+    }
+
     void setMatrixInTransaction(float dsdx, float dtdx, float dsdy, float dtdy,
             boolean recoveringMemory) {
         try {
@@ -554,6 +581,13 @@
         }
 
         @Override
+        public void setPositionAppliesWithResize() {
+            if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setPositionAppliesWithResize(): OLD: "
+                    + this + ". Called by" + Debug.getCallers(9));
+            super.setPositionAppliesWithResize();
+        }
+
+        @Override
         public void setSize(int w, int h) {
             if (w != mSize.x || h != mSize.y) {
                 if (LOG_SURFACE_TRACE) Slog.v(SURFACE_TAG, "setSize(" + w + "," + h + "): OLD:"
@@ -719,4 +753,125 @@
                     + " (" + mDsdx + "," + mDtdx + "," + mDsdy + "," + mDtdy + ")";
         }
     }
+
+    private static class SurfaceControlWithBackground extends SurfaceControl {
+        private SurfaceControl mBackgroundControl;
+        private boolean mOpaque = true;
+        private boolean mVisible = false;
+
+        public SurfaceControlWithBackground(SurfaceSession s,
+                       String name, int w, int h, int format, int flags)
+                   throws OutOfResourcesException {
+            super(s, name, w, h, format, flags);
+            mBackgroundControl = new SurfaceControl(s, name, w, h,
+                    PixelFormat.OPAQUE, flags | SurfaceControl.FX_SURFACE_DIM);
+            mOpaque = (flags & SurfaceControl.OPAQUE) != 0;
+        }
+
+        @Override
+        public void setAlpha(float alpha) {
+            super.setAlpha(alpha);
+            mBackgroundControl.setAlpha(alpha);
+        }
+
+        @Override
+        public void setLayer(int zorder) {
+            super.setLayer(zorder);
+            mBackgroundControl.setLayer(zorder - 1);
+        }
+
+        @Override
+        public void setPosition(float x, float y) {
+            super.setPosition(x, y);
+            mBackgroundControl.setPosition(x, y);
+        }
+
+        @Override
+        public void setSize(int w, int h) {
+            super.setSize(w, h);
+            mBackgroundControl.setSize(w, h);
+        }
+
+        @Override
+        public void setWindowCrop(Rect crop) {
+            super.setWindowCrop(crop);
+            mBackgroundControl.setWindowCrop(crop);
+        }
+
+        @Override
+        public void setFinalCrop(Rect crop) {
+            super.setFinalCrop(crop);
+            mBackgroundControl.setFinalCrop(crop);
+        }
+
+        @Override
+        public void setLayerStack(int layerStack) {
+            super.setLayerStack(layerStack);
+            mBackgroundControl.setLayerStack(layerStack);
+        }
+
+        @Override
+        public void setOpaque(boolean isOpaque) {
+            super.setOpaque(isOpaque);
+            mOpaque = isOpaque;
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void setSecure(boolean isSecure) {
+            super.setSecure(isSecure);
+        }
+
+        @Override
+        public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+            super.setMatrix(dsdx, dtdx, dsdy, dtdy);
+            mBackgroundControl.setMatrix(dsdx, dtdx, dsdy, dtdy);
+        }
+
+        @Override
+        public void hide() {
+            mVisible = false;
+            super.hide();
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void show() {
+            mVisible = true;
+            super.show();
+            updateBackgroundVisibility();
+        }
+
+        @Override
+        public void destroy() {
+            super.destroy();
+            mBackgroundControl.destroy();
+        }
+
+        @Override
+        public void release() {
+            super.release();
+            mBackgroundControl.release();
+        }
+
+        @Override
+        public void setTransparentRegionHint(Region region) {
+            super.setTransparentRegionHint(region);
+            mBackgroundControl.setTransparentRegionHint(region);
+        }
+
+        @Override
+        public void deferTransactionUntil(IBinder handle, long frame) {
+            super.deferTransactionUntil(handle, frame);
+            mBackgroundControl.deferTransactionUntil(handle, frame);
+        }
+
+        private void updateBackgroundVisibility() {
+            if (mOpaque && mVisible) {
+                mBackgroundControl.show();
+            } else {
+                mBackgroundControl.hide();
+            }
+        }
+    }
 }
diff --git a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
index 9a7e64b3..b528016 100644
--- a/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
+++ b/services/devicepolicy/java/com/android/server/devicepolicy/DevicePolicyManagerService.java
@@ -1338,7 +1338,8 @@
         }
 
         Owners newOwners() {
-            return new Owners(mContext, getUserManager(), getUserManagerInternal());
+            return new Owners(getUserManager(), getUserManagerInternal(),
+                    getPackageManagerInternal());
         }
 
         UserManager getUserManager() {
@@ -8134,45 +8135,27 @@
         }
 
         @Override
-        public boolean hasDeviceOwnerOrProfileOwner(String packageName, int userId) {
-            if (!mHasFeature || packageName == null) {
-                return false;
-            }
-            if (userId < 0) {
-                throw new UnsupportedOperationException("userId should be >= 0");
-            }
-            synchronized (DevicePolicyManagerService.this) {
-                if (packageName.equals(mOwners.getProfileOwnerPackage(userId))) {
-                    return true;
-                }
-                if (userId == mOwners.getDeviceOwnerUserId()
-                        && packageName.equals(mOwners.getDeviceOwnerPackageName())) {
-                    return true;
-                }
-            }
-            return false;
-        }
-
-        @Override
         public Intent createPackageSuspendedDialogIntent(String packageName, int userId) {
             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 b316cbd..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,10 @@
 
 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;
 import android.os.UserHandle;
@@ -27,7 +28,9 @@
 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;
 
 import com.android.internal.util.FastXmlSerializer;
@@ -52,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";
@@ -86,6 +89,7 @@
 
     private final UserManager mUserManager;
     private final UserManagerInternal mUserManagerInternal;
+    private final PackageManagerInternal mPackageManagerInternal;
 
     // Internal state for the device owner package.
     private OwnerInfo mDeviceOwner;
@@ -98,77 +102,117 @@
     // Local system update policy controllable by device owner.
     private SystemUpdatePolicy mSystemUpdatePolicy;
 
-    public Owners(Context context, UserManager userManager,
-            UserManagerInternal userManagerInternal) {
+    private final Object mLock = new Object();
+
+    public Owners(UserManager userManager,
+            UserManagerInternal userManagerInternal,
+            PackageManagerInternal packageManagerInternal) {
         mUserManager = userManager;
         mUserManagerInternal = userManagerInternal;
+        mPackageManagerInternal = packageManagerInternal;
     }
 
     /**
      * 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));
+    }
+
+    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);
         }
-        if (hasDeviceOwner() && hasProfileOwner(getDeviceOwnerUserId())) {
-            Slog.w(TAG, String.format("User %d has both DO and PO, which is not supported",
-                    getDeviceOwnerUserId()));
-        }
+        mPackageManagerInternal.setDeviceAndProfileOwnerPackages(
+                mDeviceOwnerUserId, (mDeviceOwner != null ? mDeviceOwner.packageName : null),
+                po);
     }
 
     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) {
@@ -176,128 +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);
+            mUserManagerInternal.setDeviceManaged(true);
+            pushToPackageManagerLocked();
+        }
     }
 
     void clearDeviceOwner() {
-        mDeviceOwner = null;
-        mDeviceOwnerUserId = UserHandle.USER_NULL;
+        synchronized (mLock) {
+            mDeviceOwner = null;
+            mDeviceOwnerUserId = UserHandle.USER_NULL;
 
-        mUserManagerInternal.setDeviceManaged(false);
+            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);
+        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);
+        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;
@@ -363,7 +451,7 @@
     }
 
     void writeDeviceOwner() {
-        synchronized (this) {
+        synchronized (mLock) {
             if (DEBUG) {
                 Log.d(TAG, "Writing to device owner file");
             }
@@ -372,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/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
index 744443f..6cb4a82 100644
--- a/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
+++ b/services/tests/servicestests/src/com/android/server/devicepolicy/DevicePolicyManagerServiceTestable.java
@@ -28,10 +28,8 @@
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.os.UserManagerInternal;
-import android.os.storage.StorageManager;
 import android.telephony.TelephonyManager;
 import android.util.ArrayMap;
-import android.util.Log;
 import android.util.Pair;
 import android.view.IWindowManager;
 
@@ -57,7 +55,7 @@
         private final File mProfileOwnerBase;
 
         public OwnersTestable(DpmMockContext context) {
-            super(context, context.userManager, context.userManagerInternal);
+            super(context.userManager, context.userManagerInternal, context.packageManagerInternal);
             mLegacyFile = new File(context.dataDir, LEGACY_FILE);
             mDeviceOwnerFile = new File(context.dataDir, DEVICE_OWNER_FILE);
             mProfileOwnerBase = new File(context.dataDir, PROFILE_OWNER_FILE_BASE);
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,