Merge "Ignore "mLastHidden" state when deciding whether to turnScreenOn." into oc-dr1-dev
diff --git a/Android.mk b/Android.mk
index cc34767..3b44255 100644
--- a/Android.mk
+++ b/Android.mk
@@ -247,6 +247,7 @@
 	core/java/android/nfc/INfcCardEmulation.aidl \
 	core/java/android/nfc/INfcFCardEmulation.aidl \
 	core/java/android/nfc/INfcUnlockHandler.aidl \
+	core/java/android/nfc/INfcDta.aidl \
 	core/java/android/nfc/ITagRemovedCallback.aidl \
 	core/java/android/os/IBatteryPropertiesListener.aidl \
 	core/java/android/os/IBatteryPropertiesRegistrar.aidl \
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index abf48a8..35cb2f1 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -5413,8 +5413,8 @@
                     int uid = Process.myUid();
                     String[] packages = getPackageManager().getPackagesForUid(uid);
                     if (packages != null) {
-                        ThreadedRenderer.setupDiskCache(cacheDir);
-                        RenderScriptCacheDir.setupDiskCache(cacheDir);
+                        ThreadedRenderer.setupDiskCache(codeCacheDir);
+                        RenderScriptCacheDir.setupDiskCache(codeCacheDir);
                     }
                 } catch (RemoteException e) {
                     Trace.traceEnd(Trace.TRACE_TAG_ACTIVITY_MANAGER);
diff --git a/core/java/android/app/Notification.java b/core/java/android/app/Notification.java
index 46e597a..531afa4 100644
--- a/core/java/android/app/Notification.java
+++ b/core/java/android/app/Notification.java
@@ -33,6 +33,7 @@
 import android.content.pm.PackageManager.NameNotFoundException;
 import android.content.pm.ShortcutInfo;
 import android.content.res.ColorStateList;
+import android.content.res.Resources;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Color;
@@ -1090,6 +1091,11 @@
     public static final String EXTRA_CONTAINS_CUSTOM_VIEW = "android.contains.customView";
 
     /**
+     * @hide
+     */
+    public static final String EXTRA_REDUCED_IMAGES = "android.reduced.images";
+
+    /**
      * {@link #extras} key: the audio contents of this notification.
      *
      * This is for use when rendering the notification on an audio-focused interface;
@@ -4545,11 +4551,16 @@
                     savedBundle.getBoolean(EXTRA_SHOW_CHRONOMETER));
             publicExtras.putBoolean(EXTRA_CHRONOMETER_COUNT_DOWN,
                     savedBundle.getBoolean(EXTRA_CHRONOMETER_COUNT_DOWN));
-            publicExtras.putCharSequence(EXTRA_TITLE,
-                    mContext.getString(com.android.internal.R.string.notification_hidden_text));
             mN.extras = publicExtras;
-            final RemoteViews view = ambient ? makeAmbientNotification()
-                    : applyStandardTemplate(getBaseLayoutResource());
+            RemoteViews view;
+            if (ambient) {
+                publicExtras.putCharSequence(EXTRA_TITLE,
+                        mContext.getString(com.android.internal.R.string.notification_hidden_text));
+                view = makeAmbientNotification();
+            } else{
+                view = makeNotificationHeader(false /* ambient */);
+                view.setBoolean(R.id.notification_header, "setExpandOnlyOnButton", true);
+            }
             mN.extras = savedBundle;
             mN.mLargeIcon = largeIcon;
             mN.largeIcon = largeIconLegacy;
@@ -4943,9 +4954,13 @@
             buildUnstyled();
 
             if (mStyle != null) {
+                mStyle.reduceImageSizes(mContext);
+                mStyle.purgeResources();
                 mStyle.buildStyled(mN);
             }
 
+            mN.reduceImageSizes(mContext);
+
             if (mContext.getApplicationInfo().targetSdkVersion < Build.VERSION_CODES.N
                     && (useExistingRemoteView())) {
                 if (mN.contentView == null) {
@@ -5135,6 +5150,52 @@
     }
 
     /**
+     * Reduces the image sizes to conform to a maximum allowed size. This also processes all custom
+     * remote views.
+     *
+     * @hide
+     */
+    void reduceImageSizes(Context context) {
+        if (extras.getBoolean(EXTRA_REDUCED_IMAGES)) {
+            return;
+        }
+        if (mLargeIcon != null || largeIcon != null) {
+            Resources resources = context.getResources();
+            Class<? extends Style> style = getNotificationStyle();
+            int maxWidth = resources.getDimensionPixelSize(R.dimen.notification_right_icon_size);
+            int maxHeight = maxWidth;
+            if (MediaStyle.class.equals(style)
+                    || DecoratedMediaCustomViewStyle.class.equals(style)) {
+                maxHeight = resources.getDimensionPixelSize(
+                        R.dimen.notification_media_image_max_height);
+                maxWidth = resources.getDimensionPixelSize(
+                        R.dimen.notification_media_image_max_width);
+            }
+            if (mLargeIcon != null) {
+                mLargeIcon.scaleDownIfNecessary(maxWidth, maxHeight);
+            }
+            if (largeIcon != null) {
+                largeIcon = Icon.scaleDownIfNecessary(largeIcon, maxWidth, maxHeight);
+            }
+        }
+        reduceImageSizesForRemoteView(contentView, context);
+        reduceImageSizesForRemoteView(headsUpContentView, context);
+        reduceImageSizesForRemoteView(bigContentView, context);
+        extras.putBoolean(EXTRA_REDUCED_IMAGES, true);
+    }
+
+    private void reduceImageSizesForRemoteView(RemoteViews remoteView, Context context) {
+        if (remoteView != null) {
+            Resources resources = context.getResources();
+            int maxWidth = resources.getDimensionPixelSize(
+                    R.dimen.notification_custom_view_max_image_width);
+            int maxHeight = resources.getDimensionPixelSize(
+                    R.dimen.notification_custom_view_max_image_height);
+            remoteView.reduceImageSizes(maxWidth, maxHeight);
+        }
+    }
+
+    /**
      * @return whether this notification is a foreground service notification
      */
     private boolean isForegroundService() {
@@ -5435,6 +5496,14 @@
         public boolean displayCustomViewInline() {
             return false;
         }
+
+        /**
+         * Reduces the image sizes contained in this style.
+         *
+         * @hide
+         */
+        public void reduceImageSizes(Context context) {
+        }
     }
 
     /**
@@ -5533,6 +5602,27 @@
         /**
          * @hide
          */
+        @Override
+        public void reduceImageSizes(Context context) {
+            super.reduceImageSizes(context);
+            Resources resources = context.getResources();
+            if (mPicture != null) {
+                int maxPictureWidth = resources.getDimensionPixelSize(
+                        R.dimen.notification_big_picture_max_height);
+                int maxPictureHeight = resources.getDimensionPixelSize(
+                        R.dimen.notification_big_picture_max_width);
+                mPicture = Icon.scaleDownIfNecessary(mPicture, maxPictureWidth, maxPictureHeight);
+            }
+            if (mBigLargeIcon != null) {
+                int rightIconSize = resources.getDimensionPixelSize(
+                        R.dimen.notification_right_icon_size);
+                mBigLargeIcon.scaleDownIfNecessary(rightIconSize, rightIconSize);
+            }
+        }
+
+        /**
+         * @hide
+         */
         public RemoteViews makeBigContentView() {
             // Replace mN.mLargeIcon with mBigLargeIcon if mBigLargeIconSet
             // This covers the following cases:
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 235b8d4..fe2168b 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -18,14 +18,12 @@
 
 import android.annotation.IntDef;
 import android.annotation.NonNull;
-import android.annotation.Nullable;
 import android.annotation.SdkConstant;
 import android.annotation.SystemService;
 import android.annotation.TestApi;
 import android.app.Notification.Builder;
 import android.content.ComponentName;
 import android.content.Context;
-import android.content.Intent;
 import android.content.pm.ParceledListSlice;
 import android.graphics.drawable.Icon;
 import android.net.Uri;
@@ -33,7 +31,6 @@
 import android.os.Bundle;
 import android.os.Handler;
 import android.os.IBinder;
-import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.RemoteException;
@@ -41,7 +38,6 @@
 import android.os.StrictMode;
 import android.os.UserHandle;
 import android.provider.Settings.Global;
-import android.service.notification.NotificationListenerService.Ranking;
 import android.service.notification.StatusBarNotification;
 import android.service.notification.ZenModeConfig;
 import android.util.ArraySet;
@@ -312,6 +308,7 @@
             }
         }
         if (localLOGV) Log.v(TAG, pkg + ": notify(" + id + ", " + notification + ")");
+        notification.reduceImageSizes(mContext);
         final Notification copy = Builder.maybeCloneStrippedForDelivery(notification);
         try {
             service.enqueueNotificationWithTag(pkg, mContext.getOpPackageName(), tag, id,
@@ -418,12 +415,16 @@
      * Creates a notification channel that notifications can be posted to.
      *
      * This can also be used to restore a deleted channel and to update an existing channel's
-     * name and description.
+     * name, description, and/or importance.
      *
      * <p>The name and description should only be changed if the locale changes
      * or in response to the user renaming this channel. For example, if a user has a channel
      * named 'John Doe' that represents messages from a 'John Doe', and 'John Doe' changes his name
      * to 'John Smith,' the channel can be renamed to match.
+     *
+     * <p>The importance of an existing channel will only be changed if the new importance is lower
+     * than the current value and the user has not altered any settings on this channel.
+     *
      * All other fields are ignored for channels that already exist.
      *
      * @param channel  the channel to create.  Note that the created channel may differ from this
diff --git a/core/java/android/app/WallpaperColors.java b/core/java/android/app/WallpaperColors.java
index b9d3e75..d0791cf 100644
--- a/core/java/android/app/WallpaperColors.java
+++ b/core/java/android/app/WallpaperColors.java
@@ -136,12 +136,12 @@
         }
 
         final int bitmapArea = bitmap.getWidth() * bitmap.getHeight();
+        boolean shouldRecycle = false;
         if (bitmapArea > MAX_WALLPAPER_EXTRACTION_AREA) {
+            shouldRecycle = true;
             Size optimalSize = calculateOptimalSize(bitmap.getWidth(), bitmap.getHeight());
-            Bitmap scaledBitmap = Bitmap.createScaledBitmap(bitmap, optimalSize.getWidth(),
+            bitmap = Bitmap.createScaledBitmap(bitmap, optimalSize.getWidth(),
                     optimalSize.getHeight(), true /* filter */);
-            bitmap.recycle();
-            bitmap = scaledBitmap;
         }
 
         final Palette palette = Palette
@@ -181,6 +181,11 @@
         }
 
         int hints = calculateHints(bitmap);
+
+        if (shouldRecycle) {
+            bitmap.recycle();
+        }
+
         return new WallpaperColors(primary, secondary, tertiary, hints);
     }
 
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index ef61703..7d2f8d1 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -126,8 +126,8 @@
      * File creation mode: allow all other applications to have read access to
      * the created file.
      * <p>
-     * As of {@link android.os.Build.VERSION_CODES#N} attempting to use this
-     * mode will throw a {@link SecurityException}.
+     * Starting from {@link android.os.Build.VERSION_CODES#N}, attempting to use this
+     * mode throws a {@link SecurityException}.
      *
      * @deprecated Creating world-readable files is very dangerous, and likely
      *             to cause security holes in applications. It is strongly
@@ -146,7 +146,7 @@
      * File creation mode: allow all other applications to have write access to
      * the created file.
      * <p>
-     * As of {@link android.os.Build.VERSION_CODES#N} attempting to use this
+     * Starting from {@link android.os.Build.VERSION_CODES#N}, attempting to use this
      * mode will throw a {@link SecurityException}.
      *
      * @deprecated Creating world-writable files is very dangerous, and likely
@@ -1129,13 +1129,47 @@
      * </ul>
      * <p>
      * Starting in {@link android.os.Build.VERSION_CODES#KITKAT}, no permissions
-     * are required to read or write to the returned path; it's always
-     * accessible to the calling app. This only applies to paths generated for
-     * package name of the calling application. To access paths belonging to
-     * other packages,
-     * {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE} and/or
-     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} are required.
+     * are required to read or write to the path that this method returns.
+     * However, starting from {@link android.os.Build.VERSION_CODES#M},
+     * to read the OBB expansion files, you must declare the
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission in the app manifest and ask for
+     * permission at runtime as follows:
+     * </p>
      * <p>
+     * {@code <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
+     * android:maxSdkVersion="23" />}
+     * </p>
+     * <p>
+     * Starting from {@link android.os.Build.VERSION_CODES#N},
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE}
+     * permission is not required, so don’t ask for this
+     * permission at runtime. To handle both cases, your app must first try to read the OBB file,
+     * and if it fails, you must request
+     * {@link android.Manifest.permission#READ_EXTERNAL_STORAGE} permission at runtime.
+     * </p>
+     *
+     * <p>
+     * The following code snippet shows how to do this:
+     * </p>
+     *
+     * <pre>
+     * File obb = new File(obb_filename);
+     * boolean open_failed = false;
+     *
+     * try {
+     *     BufferedReader br = new BufferedReader(new FileReader(obb));
+     *     open_failed = false;
+     *     ReadObbFile(br);
+     * } catch (IOException e) {
+     *     open_failed = true;
+     * }
+     *
+     * if (open_failed) {
+     *     // request READ_EXTERNAL_STORAGE permission before reading OBB file
+     *     ReadObbFileWithPermission();
+     * }
+     * </pre>
+     *
      * On devices with multiple users (as described by {@link UserManager}),
      * multiple users may share the same OBB storage location. Applications
      * should ensure that multiple instances running under different users don't
diff --git a/core/java/android/content/SyncStatusInfo.java b/core/java/android/content/SyncStatusInfo.java
index 663e6e4..abf9cc9 100644
--- a/core/java/android/content/SyncStatusInfo.java
+++ b/core/java/android/content/SyncStatusInfo.java
@@ -26,7 +26,7 @@
 public class SyncStatusInfo implements Parcelable {
     private static final String TAG = "Sync";
 
-    static final int VERSION = 3;
+    static final int VERSION = 4;
 
     private static final int MAX_EVENT_COUNT = 10;
 
@@ -102,6 +102,7 @@
             parcel.writeLong(mLastEventTimes.get(i));
             parcel.writeString(mLastEvents.get(i));
         }
+        parcel.writeInt(numSourcePeriodic);
     }
 
     public SyncStatusInfo(Parcel parcel) {
@@ -146,6 +147,16 @@
                 }
             }
         }
+        if (version < 4) {
+            // Before version 4, numSourcePeriodic wasn't persisted.
+            numSourcePeriodic = numSyncs - numSourceLocal - numSourcePoll - numSourceServer
+                    - numSourceUser;
+            if (numSourcePeriodic < 0) { // Sanity check.
+                numSourcePeriodic = 0;
+            }
+        } else {
+            numSourcePeriodic = parcel.readInt();
+        }
     }
 
     public SyncStatusInfo(SyncStatusInfo other) {
diff --git a/core/java/android/content/pm/LauncherApps.java b/core/java/android/content/pm/LauncherApps.java
index ed41e79..aa9562f 100644
--- a/core/java/android/content/pm/LauncherApps.java
+++ b/core/java/android/content/pm/LauncherApps.java
@@ -608,15 +608,15 @@
     }
 
     /**
-     * Get {@link ApplicationInfo} for a profile
+     * Returns {@link ApplicationInfo} about an application installed for a specific user profile.
      *
      * @param packageName The package name of the application
      * @param flags Additional option flags {@link PackageManager#getApplicationInfo}
      * @param user The UserHandle of the profile.
      *
-     * @return An {@link ApplicationInfo} containing information about the package or
-     *         null if the package isn't installed for the given user, or the target user
-     *         is not enabled.
+     * @return {@link ApplicationInfo} containing information about the package. Returns
+     *         {@code null} if the package isn't installed for the given profile, or the profile
+     *         isn't enabled.
      */
     public ApplicationInfo getApplicationInfo(@NonNull String packageName,
             @ApplicationInfoFlags int flags, @NonNull UserHandle user)
diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java
index b39f9a5..bcba938e 100644
--- a/core/java/android/content/pm/PackageParser.java
+++ b/core/java/android/content/pm/PackageParser.java
@@ -40,7 +40,7 @@
 import static android.content.pm.PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
 import static android.os.Build.VERSION_CODES.O;
 import static android.os.Trace.TRACE_TAG_PACKAGE_MANAGER;
-import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_ROTATE;
+import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 
 import android.annotation.IntRange;
 import android.annotation.NonNull;
@@ -4283,7 +4283,7 @@
                 sa.getString(R.styleable.AndroidManifestActivity_enableVrMode);
 
             a.info.rotationAnimation =
-                sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_ROTATE);
+                sa.getInt(R.styleable.AndroidManifestActivity_rotationAnimation, ROTATION_ANIMATION_UNSPECIFIED);
 
             a.info.colorMode = sa.getInt(R.styleable.AndroidManifestActivity_colorMode,
                     ActivityInfo.COLOR_MODE_DEFAULT);
diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl
index f991efe..6801618 100644
--- a/core/java/android/nfc/INfcAdapter.aidl
+++ b/core/java/android/nfc/INfcAdapter.aidl
@@ -29,6 +29,7 @@
 import android.nfc.INfcFCardEmulation;
 import android.nfc.INfcUnlockHandler;
 import android.nfc.ITagRemovedCallback;
+import android.nfc.INfcDta;
 import android.os.Bundle;
 
 /**
@@ -40,7 +41,7 @@
     INfcCardEmulation getNfcCardEmulationInterface();
     INfcFCardEmulation getNfcFCardEmulationInterface();
     INfcAdapterExtras getNfcAdapterExtrasInterface(in String pkg);
-
+    INfcDta getNfcDtaInterface(in String pkg);
     int getState();
     boolean disable(boolean saveState);
     boolean enable();
diff --git a/core/java/android/nfc/INfcDta.aidl b/core/java/android/nfc/INfcDta.aidl
new file mode 100644
index 0000000..4cc5927
--- /dev/null
+++ b/core/java/android/nfc/INfcDta.aidl
@@ -0,0 +1,34 @@
+ /*
+  * Copyright (C) 2017 NXP Semiconductors
+  *
+  * Licensed under the Apache License, Version 2.0 (the "License");
+  * you may not use this file except in compliance with the License.
+  * You may obtain a copy of the License at
+  *
+  *      http://www.apache.org/licenses/LICENSE-2.0
+  *
+  * Unless required by applicable law or agreed to in writing, software
+  * distributed under the License is distributed on an "AS IS" BASIS,
+  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  * See the License for the specific language governing permissions and
+  * limitations under the License.
+  */
+package android.nfc;
+
+import android.os.Bundle;
+
+/**
+ * {@hide}
+ */
+interface INfcDta {
+
+    void enableDta();
+    void disableDta();
+    boolean enableServer(String serviceName, int serviceSap, int miu,
+            int rwSize,int testCaseId);
+    void disableServer();
+    boolean enableClient(String serviceName, int miu, int rwSize,
+            int testCaseId);
+    void disableClient();
+    boolean registerMessageService(String msgServiceName);
+}
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 48869c7..debef63 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -16,8 +16,6 @@
 
 package android.nfc;
 
-import java.util.HashMap;
-
 import android.annotation.RequiresPermission;
 import android.annotation.SdkConstant;
 import android.annotation.SdkConstant.SdkConstantType;
@@ -43,6 +41,7 @@
 import android.util.Log;
 
 import java.io.IOException;
+import java.util.HashMap;
 
 /**
  * Represents the local NFC adapter.
@@ -627,6 +626,23 @@
     }
 
     /**
+     * Returns the binder interface to the NFC-DTA test interface.
+     * @hide
+     */
+    public INfcDta getNfcDtaInterface() {
+        if (mContext == null) {
+            throw new UnsupportedOperationException("You need a context on NfcAdapter to use the "
+                    + " NFC extras APIs");
+        }
+        try {
+            return sService.getNfcDtaInterface(mContext.getPackageName());
+        } catch (RemoteException e) {
+            attemptDeadServiceRecovery(e);
+            return null;
+        }
+    }
+
+    /**
      * NFC service dead - attempt best effort recovery
      * @hide
      */
diff --git a/core/java/android/nfc/dta/NfcDta.java b/core/java/android/nfc/dta/NfcDta.java
new file mode 100644
index 0000000..8801662
--- /dev/null
+++ b/core/java/android/nfc/dta/NfcDta.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.dta;
+
+import android.content.Context;
+import android.nfc.INfcDta;
+import android.nfc.NfcAdapter;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.util.HashMap;
+
+/**
+ * This class provides the primary API for DTA operations.
+ * @hide
+ */
+public final class NfcDta {
+    private static final String TAG = "NfcDta";
+
+    private static INfcDta sService;
+    private static HashMap<Context, NfcDta> sNfcDtas = new HashMap<Context, NfcDta>();
+
+    private final Context mContext;
+
+    private NfcDta(Context context, INfcDta service) {
+        mContext = context.getApplicationContext();
+        sService = service;
+    }
+
+    /**
+     * Helper to get an instance of this class.
+     *
+     * @param adapter A reference to an NfcAdapter object.
+     * @return
+     */
+    public static synchronized NfcDta getInstance(NfcAdapter adapter) {
+        if (adapter == null) throw new NullPointerException("NfcAdapter is null");
+        Context context = adapter.getContext();
+        if (context == null) {
+            Log.e(TAG, "NfcAdapter context is null.");
+            throw new UnsupportedOperationException();
+        }
+
+        NfcDta manager = sNfcDtas.get(context);
+        if (manager == null) {
+            INfcDta service = adapter.getNfcDtaInterface();
+            if (service == null) {
+                Log.e(TAG, "This device does not implement the INfcDta interface.");
+                throw new UnsupportedOperationException();
+            }
+            manager = new NfcDta(context, service);
+            sNfcDtas.put(context, manager);
+        }
+        return manager;
+    }
+
+    /**
+     * Enables DTA mode
+     *
+     * @return true/false if enabling was successful
+     */
+    public boolean enableDta() {
+        try {
+            sService.enableDta();
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Disables DTA mode
+     *
+     * @return true/false if disabling was successful
+     */
+    public boolean disableDta() {
+        try {
+            sService.disableDta();
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Enables Server
+     *
+     * @return true/false if enabling was successful
+     */
+    public boolean enableServer(String serviceName, int serviceSap, int miu,
+            int rwSize, int testCaseId) {
+        try {
+            return sService.enableServer(serviceName, serviceSap, miu, rwSize, testCaseId);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Disables Server
+     *
+     * @return true/false if disabling was successful
+     */
+    public boolean disableServer() {
+        try {
+            sService.disableServer();
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Enables Client
+     *
+     * @return true/false if enabling was successful
+     */
+    public boolean enableClient(String serviceName, int miu, int rwSize,
+            int testCaseId) {
+        try {
+            return sService.enableClient(serviceName, miu, rwSize, testCaseId);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+
+    /**
+     * Disables client
+     *
+     * @return true/false if disabling was successful
+     */
+    public boolean disableClient() {
+        try {
+            sService.disableClient();
+        } catch (RemoteException e) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * Registers Message Service
+     *
+     * @return true/false if registration was successful
+     */
+    public boolean registerMessageService(String msgServiceName) {
+        try {
+            return sService.registerMessageService(msgServiceName);
+        } catch (RemoteException e) {
+            return false;
+        }
+    }
+}
diff --git a/core/java/android/os/BatteryStats.java b/core/java/android/os/BatteryStats.java
index b178d81..4160ed7 100644
--- a/core/java/android/os/BatteryStats.java
+++ b/core/java/android/os/BatteryStats.java
@@ -201,7 +201,7 @@
      * New in version 22:
      *   - BLE scan result background count, BLE unoptimized scan time
      */
-    static final String CHECKIN_VERSION = "23";
+    static final String CHECKIN_VERSION = "24";
 
     /**
      * Old version, we hit 9 and ran out of room, need to remove.
@@ -5606,8 +5606,10 @@
                         pw.print(',');
                         if (rec.stepDetails.statPlatformIdleState != null) {
                             pw.print(rec.stepDetails.statPlatformIdleState);
+                            if (rec.stepDetails.statSubsystemPowerState != null) {
+                                pw.print(',');
+                            }
                         }
-                        pw.println();
 
                         if (rec.stepDetails.statSubsystemPowerState != null) {
                             pw.print(rec.stepDetails.statSubsystemPowerState);
diff --git a/core/java/android/os/RecoverySystem.java b/core/java/android/os/RecoverySystem.java
index 7fa1c5a..673a8ba 100644
--- a/core/java/android/os/RecoverySystem.java
+++ b/core/java/android/os/RecoverySystem.java
@@ -24,11 +24,11 @@
 import android.annotation.SystemService;
 import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.pm.PackageManager;
-import android.os.UserManager;
 import android.provider.Settings;
 import android.telephony.euicc.EuiccManager;
 import android.text.TextUtils;
@@ -751,9 +751,7 @@
         // Block until the ordered broadcast has completed.
         condition.block();
 
-        // TODO(b/63693573): Uncomment this once the pSIM slot is restored as needed
-        // after the ensuing boot. Currently you end up stuck on the eSIM.
-        // wipeEuiccData(context, wipeEuicc);
+        wipeEuiccData(context, wipeEuicc);
 
         String shutdownArg = null;
         if (shutdown) {
@@ -770,6 +768,14 @@
     }
 
     private static void wipeEuiccData(Context context, final boolean isWipeEuicc) {
+        ContentResolver cr = context.getContentResolver();
+        if (Settings.Global.getInt(cr, Settings.Global.EUICC_PROVISIONED, 0) == 0) {
+            // If the eUICC isn't provisioned, there's no reason to either wipe or retain profiles,
+            // as there's nothing to wipe nor retain.
+            Log.d(TAG, "Skipping eUICC wipe/retain as it is not provisioned");
+            return;
+        }
+
         EuiccManager euiccManager = (EuiccManager) context.getSystemService(
                 Context.EUICC_SERVICE);
         if (euiccManager != null && euiccManager.isEnabled()) {
diff --git a/core/java/android/os/UserManager.java b/core/java/android/os/UserManager.java
index 3337def..12013fc 100644
--- a/core/java/android/os/UserManager.java
+++ b/core/java/android/os/UserManager.java
@@ -389,10 +389,13 @@
     public static final String DISALLOW_ADD_MANAGED_PROFILE = "no_add_managed_profile";
 
     /**
-     * Specifies if a user is disallowed from disabling application verification.
-     * Starting from {@link android.os.Build.VERSION_CODES#O}, application verification
-     * is enforced across all users on the device if a profile owner or device owner sets
-     * this restriction to <code>true</code>. The default value is <code>false</code>.
+     * Specifies if a user is disallowed from disabling application verification. The default
+     * value is <code>false</code>.
+     *
+     * <p>In Android 8.0 ({@linkplain android.os.Build.VERSION_CODES#O API level 26}) and higher,
+     * this is a global user restriction. If a device owner or profile owner sets this restriction,
+     * the system enforces app verification across all users on the device. Running in earlier
+     * Android versions, this restriction affects only the profile that sets it.
      *
      * <p>Key for user restrictions.
      * <p>Type: Boolean
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index e84a041..2d8ed7a 100755
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1437,10 +1437,10 @@
      * to the caller package.
      *
      * <p>
-     * <b>NOTE: </b> applications should call
+     * <b>NOTE: </b> Applications should call
      * {@link android.view.autofill.AutofillManager#hasEnabledAutofillServices()} and
-     * {@link android.view.autofill.AutofillManager#isAutofillSupported()} first, and only
-     * broadcast this intent if they return {@code false} and {@code true} respectively.
+     * {@link android.view.autofill.AutofillManager#isAutofillSupported()}, and only use this action
+     * to start an activity if they return {@code false} and {@code true} respectively.
      */
     @SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
     public static final String ACTION_REQUEST_SET_AUTOFILL_SERVICE =
@@ -10080,22 +10080,6 @@
         public static final String DEVICE_DEMO_MODE = "device_demo_mode";
 
         /**
-         * Retail mode specific settings. This is encoded as a key=value list, separated by commas.
-         * Ex: "user_inactivity_timeout_ms=30000,warning_dialog_timeout_ms=10000". The following
-         * keys are supported:
-         *
-         * <pre>
-         * user_inactivity_timeout_ms  (long)
-         * warning_dialog_timeout_ms   (long)
-         * </pre>
-         * <p>
-         * Type: string
-         *
-         * @hide
-         */
-        public static final String RETAIL_DEMO_MODE_CONSTANTS = "retail_demo_mode_constants";
-
-        /**
          * Indicates the maximum time that an app is blocked for the network rules to get updated.
          *
          * Type: long
diff --git a/core/java/android/service/vr/IVrListener.aidl b/core/java/android/service/vr/IVrListener.aidl
index afb13d3..acca3fa 100644
--- a/core/java/android/service/vr/IVrListener.aidl
+++ b/core/java/android/service/vr/IVrListener.aidl
@@ -20,5 +20,5 @@
 
 /** @hide */
 oneway interface IVrListener {
-    void focusedActivityChanged(in ComponentName component);
+    void focusedActivityChanged(in ComponentName component, boolean running2dInVr, int pid);
 }
diff --git a/core/java/android/service/vr/VrListenerService.java b/core/java/android/service/vr/VrListenerService.java
index 5da4560..fa3d065 100644
--- a/core/java/android/service/vr/VrListenerService.java
+++ b/core/java/android/service/vr/VrListenerService.java
@@ -70,8 +70,10 @@
 
     private final IVrListener.Stub mBinder = new IVrListener.Stub() {
         @Override
-        public void focusedActivityChanged(ComponentName component) {
-            mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, component).sendToTarget();
+        public void focusedActivityChanged(
+                ComponentName component, boolean running2dInVr, int pid) {
+            mHandler.obtainMessage(MSG_ON_CURRENT_VR_ACTIVITY_CHANGED, running2dInVr ? 1 : 0,
+                    pid, component).sendToTarget();
         }
     };
 
@@ -84,7 +86,8 @@
         public void handleMessage(Message msg) {
             switch (msg.what) {
                 case MSG_ON_CURRENT_VR_ACTIVITY_CHANGED: {
-                    VrListenerService.this.onCurrentVrActivityChanged((ComponentName) msg.obj);
+                    VrListenerService.this.onCurrentVrActivityChanged(
+                            (ComponentName) msg.obj, msg.arg1 == 1, msg.arg2);
                 } break;
             }
         }
@@ -120,6 +123,29 @@
     }
 
     /**
+     * An extended version of onCurrentVrActivityChanged
+     *
+     * <p>This will be called when this service is initially bound, but is not
+     * guaranteed to be called before onUnbind.  In general, this is intended to be used to
+     * determine when user focus has transitioned between two VR activities, or between a
+     * VR activity and a 2D activity. This should be overridden instead of the above
+     * onCurrentVrActivityChanged as that version is deprecated.</p>
+     *
+     * @param component the {@link ComponentName} of the VR activity or the 2D intent.
+     * @param running2dInVr true if the component is a 2D component.
+     * @param pid the process the component is running in.
+     *
+     * @see android.app.Activity#setVrModeEnabled
+     * @see android.R.attr#enableVrMode
+     * @hide
+     */
+    public void onCurrentVrActivityChanged(
+            ComponentName component, boolean running2dInVr, int pid) {
+        // Override to implement. Default to old behaviour of sending null for 2D.
+        onCurrentVrActivityChanged(running2dInVr ? null : component);
+    }
+
+    /**
      * Checks if the given component is enabled in user settings.
      *
      * <p>If this component is not enabled in the user's settings, it will not be started when
diff --git a/core/java/android/util/AtomicFile.java b/core/java/android/util/AtomicFile.java
index 2f1abe9..0122e49 100644
--- a/core/java/android/util/AtomicFile.java
+++ b/core/java/android/util/AtomicFile.java
@@ -202,6 +202,15 @@
     }
 
     /**
+     * @hide
+     * Checks if the original or backup file exists.
+     * @return whether the original or backup file exists.
+     */
+    public boolean exists() {
+        return mBaseName.exists() || mBackupName.exists();
+    }
+
+    /**
      * Gets the last modified time of the atomic file.
      * {@hide}
      *
diff --git a/core/java/android/view/Display.java b/core/java/android/view/Display.java
index 7346a21..263d3ff 100644
--- a/core/java/android/view/Display.java
+++ b/core/java/android/view/Display.java
@@ -1133,6 +1133,15 @@
     }
 
     /**
+     * Returns true if the display may be in a reduced operating mode while in the
+     * specified display power state.
+     * @hide
+     */
+    public static boolean isDozeState(int state) {
+        return state == STATE_DOZE || state == STATE_DOZE_SUSPEND;
+    }
+
+    /**
      * A mode supported by a given display.
      *
      * @see Display#getSupportedModes()
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index 71a3f7e..c431323 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -69,12 +69,7 @@
     public static final int TEXT_HANDLE_MOVE = 8;
 
     /**
-     * This is a private constant.  Feel free to renumber as desired.
-     * @hide
-     */
-    public static final int SAFE_MODE_DISABLED = 10000;
-
-    /**
+     * The phone has booted with safe mode enabled.
      * This is a private constant.  Feel free to renumber as desired.
      * @hide
      */
diff --git a/core/java/android/view/NotificationHeaderView.java b/core/java/android/view/NotificationHeaderView.java
index 568c40a..5804560 100644
--- a/core/java/android/view/NotificationHeaderView.java
+++ b/core/java/android/view/NotificationHeaderView.java
@@ -59,6 +59,7 @@
     private Drawable mBackground;
     private int mHeaderBackgroundHeight;
     private boolean mEntireHeaderClickable;
+    private boolean mExpandOnlyOnButton;
     private boolean mAcceptAllTouches;
 
     ViewOutlineProvider mProvider = new ViewOutlineProvider() {
@@ -315,6 +316,7 @@
     public class HeaderTouchListener implements View.OnTouchListener {
 
         private final ArrayList<Rect> mTouchRects = new ArrayList<>();
+        private Rect mExpandButtonRect;
         private int mTouchSlop;
         private boolean mTrackGesture;
         private float mDownX;
@@ -326,7 +328,7 @@
         public void bindTouchRects() {
             mTouchRects.clear();
             addRectAroundView(mIcon);
-            addRectAroundView(mExpandButton);
+            mExpandButtonRect = addRectAroundView(mExpandButton);
             addWidthRect();
             mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
         }
@@ -340,9 +342,10 @@
             mTouchRects.add(r);
         }
 
-        private void addRectAroundView(View view) {
+        private Rect addRectAroundView(View view) {
             final Rect r = getRectAroundView(view);
             mTouchRects.add(r);
+            return r;
         }
 
         private Rect getRectAroundView(View view) {
@@ -395,6 +398,9 @@
             if (mAcceptAllTouches) {
                 return true;
             }
+            if (mExpandOnlyOnButton) {
+                return mExpandButtonRect.contains((int) x, (int) y);
+            }
             for (int i = 0; i < mTouchRects.size(); i++) {
                 Rect r = mTouchRects.get(i);
                 if (r.contains((int) x, (int) y)) {
@@ -440,4 +446,12 @@
     public void setAcceptAllTouches(boolean acceptAllTouches) {
         mAcceptAllTouches = mEntireHeaderClickable || acceptAllTouches;
     }
+
+    /**
+     * Sets whether only the expand icon itself should serve as the expand target.
+     */
+    @RemotableViewMethod
+    public void setExpandOnlyOnButton(boolean expandOnlyOnButton) {
+        mExpandOnlyOnButton = expandOnlyOnButton;
+    }
 }
diff --git a/core/java/android/view/SurfaceView.java b/core/java/android/view/SurfaceView.java
index a19f05c..cac27af 100644
--- a/core/java/android/view/SurfaceView.java
+++ b/core/java/android/view/SurfaceView.java
@@ -729,7 +729,7 @@
                 mLocation[1] = getHeight();
 
                 mScreenRect.set(mWindowSpaceLeft, mWindowSpaceTop,
-                        mLocation[0], mLocation[1]);
+                        mWindowSpaceLeft + mLocation[0], mWindowSpaceTop + mLocation[1]);
 
                 if (mTranslator != null) {
                     mTranslator.translateRectInAppWindowToScreen(mScreenRect);
diff --git a/core/java/android/view/WindowManager.java b/core/java/android/view/WindowManager.java
index 48f3973..faf3e125 100644
--- a/core/java/android/view/WindowManager.java
+++ b/core/java/android/view/WindowManager.java
@@ -1743,6 +1743,13 @@
         public float buttonBrightness = BRIGHTNESS_OVERRIDE_NONE;
 
         /**
+         * Unspecified value for {@link #rotationAnimation} indicating
+         * a lack of preference.
+         * @hide
+         */
+        public static final int ROTATION_ANIMATION_UNSPECIFIED = -1;
+
+        /**
          * Value for {@link #rotationAnimation} which specifies that this
          * window will visually rotate in or out following a rotation.
          */
@@ -2584,5 +2591,16 @@
             encoder.addProperty("type", type);
             encoder.addProperty("flags", flags);
         }
+
+        /**
+         * @hide
+         * @return True if the layout parameters will cause the window to cover the full screen;
+         *         false otherwise.
+         */
+        public boolean isFullscreen() {
+            return x == 0 && y == 0
+                    && width == WindowManager.LayoutParams.MATCH_PARENT
+                    && height == WindowManager.LayoutParams.MATCH_PARENT;
+        }
     }
 }
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index ba9e05c..668d25e 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -74,7 +74,6 @@
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Looper;
-import android.os.PowerManager;
 import android.os.RemoteException;
 import android.util.Slog;
 import android.view.animation.Animation;
@@ -1317,12 +1316,12 @@
     public boolean isScreenOn();
 
     /**
-     * @return whether the device is currently {@link PowerManager#isInteractive() interactive}.
+     * @return whether the device is currently allowed to animate.
      *
-     * Note: the screen can be on while the device is not interactive, e.g. when the device is
-     * showing Ambient Display.
+     * Note: this can be true even if it is not appropriate to animate for reasons that are outside
+     *       of the policy's authority.
      */
-    boolean isInteractive();
+    boolean okToAnimate();
 
     /**
      * Tell the policy that the lid switch has changed state.
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 7761dca..6e62351 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -199,6 +199,22 @@
     }
 
     /**
+     * Reduces all images and ensures that they are all below the given sizes.
+     *
+     * @param maxWidth the maximum width allowed
+     * @param maxHeight the maximum height allowed
+     *
+     * @hide
+     */
+    public void reduceImageSizes(int maxWidth, int maxHeight) {
+        ArrayList<Bitmap> cache = mBitmapCache.mBitmaps;
+        for (int i = 0; i < cache.size(); i++) {
+            Bitmap bitmap = cache.get(i);
+            cache.set(i, Icon.scaleDownIfNecessary(bitmap, maxWidth, maxHeight));
+        }
+    }
+
+    /**
      * Handle with care!
      */
     static class MutablePair<F, S> {
diff --git a/core/java/com/android/internal/app/MediaRouteControllerDialog.java b/core/java/com/android/internal/app/MediaRouteControllerDialog.java
index 5ce3e54..635a868 100644
--- a/core/java/com/android/internal/app/MediaRouteControllerDialog.java
+++ b/core/java/com/android/internal/app/MediaRouteControllerDialog.java
@@ -142,7 +142,11 @@
                     @Override
                     public void onClick(DialogInterface dialogInterface, int id) {
                         if (mRoute.isSelected()) {
-                            mRouter.getDefaultRoute().select();
+                            if (mRoute.isBluetooth()) {
+                                mRouter.getDefaultRoute().select();
+                            } else {
+                                mRouter.getFallbackRoute().select();
+                            }
                         }
                         dismiss();
                     }
diff --git a/core/java/com/android/internal/colorextraction/ColorExtractor.java b/core/java/com/android/internal/colorextraction/ColorExtractor.java
index 2648604..68cf5cd 100644
--- a/core/java/com/android/internal/colorextraction/ColorExtractor.java
+++ b/core/java/com/android/internal/colorextraction/ColorExtractor.java
@@ -97,14 +97,14 @@
     }
 
     /**
-     * Retrieve TYPE_NORMAL gradient colors considering wallpaper visibility.
+     * Retrieve gradient colors for a specific wallpaper.
      *
      * @param which FLAG_LOCK or FLAG_SYSTEM
      * @return colors
      */
     @NonNull
     public GradientColors getColors(int which) {
-        return getColors(which, TYPE_NORMAL);
+        return getColors(which, TYPE_DARK);
     }
 
     /**
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 2363f68..dd7d43d 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -6553,9 +6553,12 @@
          * inactive so can be dropped.
          */
         @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
-        public boolean reset() {
+        public boolean reset(long uptime, long realtime) {
             boolean active = false;
 
+            mOnBatteryBackgroundTimeBase.init(uptime, realtime);
+            mOnBatteryScreenOffBackgroundTimeBase.init(uptime, realtime);
+
             if (mWifiRunningTimer != null) {
                 active |= !mWifiRunningTimer.reset(false);
                 active |= mWifiRunning;
@@ -6741,11 +6744,6 @@
             mLastStepUserTime = mLastStepSystemTime = 0;
             mCurStepUserTime = mCurStepSystemTime = 0;
 
-            mOnBatteryBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
-                    mBsi.mClocks.uptimeMillis() * 1000);
-            mOnBatteryScreenOffBackgroundTimeBase.reset(mBsi.mClocks.elapsedRealtime() * 1000,
-                    mBsi.mClocks.uptimeMillis() * 1000);
-
             if (!active) {
                 if (mWifiRunningTimer != null) {
                     mWifiRunningTimer.detach();
@@ -9337,7 +9335,7 @@
         mNumConnectivityChange = mLoadedNumConnectivityChange = mUnpluggedNumConnectivityChange = 0;
 
         for (int i=0; i<mUidStats.size(); i++) {
-            if (mUidStats.valueAt(i).reset()) {
+            if (mUidStats.valueAt(i).reset(uptimeMillis * 1000, elapsedRealtimeMillis * 1000)) {
                 mUidStats.remove(mUidStats.keyAt(i));
                 i--;
             }
diff --git a/core/java/com/android/internal/policy/IKeyguardService.aidl b/core/java/com/android/internal/policy/IKeyguardService.aidl
index 3f35c91..69184c3 100644
--- a/core/java/com/android/internal/policy/IKeyguardService.aidl
+++ b/core/java/com/android/internal/policy/IKeyguardService.aidl
@@ -64,6 +64,11 @@
     void onStartedWakingUp();
 
     /**
+     * Called when the device has finished waking up.
+     */
+    void onFinishedWakingUp();
+
+    /**
      * Called when the device screen is turning on.
      */
     void onScreenTurningOn(IKeyguardDrawnCallback callback);
@@ -74,6 +79,11 @@
     void onScreenTurnedOn();
 
     /**
+     * Called when the screen starts turning off.
+     */
+    void onScreenTurningOff();
+
+    /**
      * Called when the screen has turned off.
      */
     void onScreenTurnedOff();
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 7d9538f..40ecc8c 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -114,5 +114,5 @@
     void addQsTile(in ComponentName tile);
     void remQsTile(in ComponentName tile);
     void clickQsTile(in ComponentName tile);
-    void handleSystemNavigationKey(in int key);
+    void handleSystemKey(in int key);
 }
diff --git a/core/java/com/android/internal/statusbar/IStatusBarService.aidl b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
index 20db499..22eef07 100644
--- a/core/java/com/android/internal/statusbar/IStatusBarService.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBarService.aidl
@@ -75,5 +75,5 @@
     void addTile(in ComponentName tile);
     void remTile(in ComponentName tile);
     void clickTile(in ComponentName tile);
-    void handleSystemNavigationKey(in int key);
+    void handleSystemKey(in int key);
 }
diff --git a/core/java/com/android/internal/widget/LockPatternUtils.java b/core/java/com/android/internal/widget/LockPatternUtils.java
index e3b9178..53a9654 100644
--- a/core/java/com/android/internal/widget/LockPatternUtils.java
+++ b/core/java/com/android/internal/widget/LockPatternUtils.java
@@ -648,8 +648,12 @@
         boolean disabledByDefault = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_disableLockscreenByDefault);
         boolean isSystemUser = UserManager.isSplitSystemUser() && userId == UserHandle.USER_SYSTEM;
+        UserInfo userInfo = getUserManager().getUserInfo(userId);
+        boolean isDemoUser = UserManager.isDeviceInDemoMode(mContext) && userInfo != null
+                && userInfo.isDemo();
         return getBoolean(DISABLE_LOCKSCREEN_KEY, false, userId)
-                || (disabledByDefault && !isSystemUser);
+                || (disabledByDefault && !isSystemUser)
+                || isDemoUser;
     }
 
     /**
diff --git a/core/proto/android/providers/settings.proto b/core/proto/android/providers/settings.proto
index e212c43..fa645f4 100644
--- a/core/proto/android/providers/settings.proto
+++ b/core/proto/android/providers/settings.proto
@@ -315,7 +315,6 @@
     SettingProto boot_count = 270;
     SettingProto safe_boot_disallowed = 271;
     SettingProto device_demo_mode = 272;
-    SettingProto retail_demo_mode_constants = 273;
     SettingProto database_downgrade_reason = 274;
     SettingProto contacts_database_wal_enabled = 275;
     SettingProto multi_sim_voice_call_subscription = 276;
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 1aca99f..0cfe689 100644
--- a/core/res/res/layout/notification_template_material_big_text.xml
+++ b/core/res/res/layout/notification_template_material_big_text.xml
@@ -55,6 +55,7 @@
                 android:singleLine="false"
                 android:gravity="top"
                 android:visibility="gone"
+                android:textAlignment="viewStart"
                 />
         </LinearLayout>
 
diff --git a/core/res/res/layout/notification_template_part_line1.xml b/core/res/res/layout/notification_template_part_line1.xml
index 308b30f..ca35de3 100644
--- a/core/res/res/layout/notification_template_part_line1.xml
+++ b/core/res/res/layout/notification_template_part_line1.xml
@@ -28,6 +28,7 @@
         android:singleLine="true"
         android:ellipsize="marquee"
         android:fadingEdge="horizontal"
+        android:textAlignment="viewStart"
         />
     <TextView android:id="@+id/text_line_1"
         android:textAppearance="@style/TextAppearance.Material.Notification"
diff --git a/core/res/res/layout/notification_template_right_icon.xml b/core/res/res/layout/notification_template_right_icon.xml
index fbf7538..d379256 100644
--- a/core/res/res/layout/notification_template_right_icon.xml
+++ b/core/res/res/layout/notification_template_right_icon.xml
@@ -21,8 +21,8 @@
              android:layout_height="wrap_content"
              android:layout_gravity="top|end">
     <ImageView android:id="@+id/right_icon"
-               android:layout_width="40dp"
-               android:layout_height="40dp"
+               android:layout_width="@dimen/notification_right_icon_size"
+               android:layout_height="@dimen/notification_right_icon_size"
                android:layout_gravity="top|end"
                android:layout_marginTop="36dp"
                android:layout_marginEnd="@dimen/notification_content_margin_end"
diff --git a/core/res/res/layout/notification_template_text.xml b/core/res/res/layout/notification_template_text.xml
index 20c2896..68f34c8 100644
--- a/core/res/res/layout/notification_template_text.xml
+++ b/core/res/res/layout/notification_template_text.xml
@@ -24,5 +24,6 @@
     android:fadingEdge="horizontal"
     android:gravity="top"
     android:singleLine="true"
+    android:textAlignment="viewStart"
     android:textAppearance="@style/TextAppearance.Material.Notification"
     />
diff --git a/core/res/res/values-fa/strings.xml b/core/res/res/values-fa/strings.xml
index 279d382..97da53d 100644
--- a/core/res/res/values-fa/strings.xml
+++ b/core/res/res/values-fa/strings.xml
@@ -245,7 +245,7 @@
     <string name="global_action_assist" msgid="3892832961594295030">"دستیار"</string>
     <string name="global_action_voice_assist" msgid="7751191495200504480">"دستیار صوتی"</string>
     <string name="global_action_lockdown" msgid="8751542514724332873">"اکنون قفل شود"</string>
-    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"بیشتر از 999"</string>
+    <string name="status_bar_notification_info_overflow" msgid="5301981741705354993">"۹۹۹+"</string>
     <string name="notification_hidden_text" msgid="1135169301897151909">"محتواها پنهان هستند"</string>
     <string name="notification_hidden_by_policy_text" msgid="9004631276932584600">"محتوا بر اساس خط‌مشی پنهان شده است"</string>
     <string name="notification_channel_virtual_keyboard" msgid="6969925135507955575">"صفحه‌‌کلید مجازی"</string>
diff --git a/core/res/res/values-gl/strings.xml b/core/res/res/values-gl/strings.xml
index fe12e7f..ba35592 100644
--- a/core/res/res/values-gl/strings.xml
+++ b/core/res/res/values-gl/strings.xml
@@ -471,7 +471,7 @@
     <string name="permlab_nfc" msgid="4423351274757876953">"controlar Near Field Communication"</string>
     <string name="permdesc_nfc" msgid="7120611819401789907">"Permite á aplicación comunicarse con etiquetas, tarxetas e lectores Near Field Communication (NFC)."</string>
     <string name="permlab_disableKeyguard" msgid="3598496301486439258">"desactivar o bloqueo da pantalla"</string>
-    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite á aplicación desactivar o bloqueo do teclado e calquera seguridade dos contrasinais asociada. Por exemplo, o teléfono desactiva o bloqueo do teclado ao recibir unha chamada telefónica entrante e, a continuación, volve activar o bloqueo do teclado unha vez finalizada a chamada."</string>
+    <string name="permdesc_disableKeyguard" msgid="6034203065077122992">"Permite á aplicación desactivar o bloqueo do teclado e calquera seguranza dos contrasinais asociada. Por exemplo, o teléfono desactiva o bloqueo do teclado ao recibir unha chamada telefónica entrante e, a continuación, volve activar o bloqueo do teclado unha vez finalizada a chamada."</string>
     <string name="permlab_manageFingerprint" msgid="5640858826254575638">"xestionar hardware de impresión dixital"</string>
     <string name="permdesc_manageFingerprint" msgid="178208705828055464">"Permite que a aplicación invoque métodos para engadir e eliminar modelos de uso de impresión dixital."</string>
     <string name="permlab_useFingerprint" msgid="3150478619915124905">"usar hardware de impresión dixital"</string>
diff --git a/core/res/res/values-hi/strings.xml b/core/res/res/values-hi/strings.xml
index a36903a..ddc9dd8 100644
--- a/core/res/res/values-hi/strings.xml
+++ b/core/res/res/values-hi/strings.xml
@@ -528,10 +528,10 @@
     <string name="permdesc_manageNetworkPolicy" msgid="7537586771559370668">"ऐप्स को नेटवर्क नीतियां प्रबंधित करने और ऐप्स-विशिष्‍ट नियमों को परिभाषित करने देता है."</string>
     <string name="permlab_modifyNetworkAccounting" msgid="5088217309088729650">"नेटवर्क उपयोग हिसाब बदलें"</string>
     <string name="permdesc_modifyNetworkAccounting" msgid="5443412866746198123">"ऐप्स  को यह संशोधित करने देता है कि ऐप्स की तुलना में नेटवर्क उपयोग का मूल्यांकन कैसे किया जाता है. सामान्‍य ऐप्स द्वारा उपयोग करने के लिए नहीं."</string>
-    <string name="permlab_accessNotifications" msgid="7673416487873432268">"नोटिफिकेशन तक पहुंचें"</string>
-    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को नोटिफिकेशन को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
-    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"नोटिफिकेशन श्रवणकर्ता सेवा से जुड़ें"</string>
-    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को नोटिफिकेशन श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
+    <string name="permlab_accessNotifications" msgid="7673416487873432268">"नोटिफ़िकेशन तक पहुंचें"</string>
+    <string name="permdesc_accessNotifications" msgid="458457742683431387">"ऐप्स  को नोटिफ़िकेशन को प्राप्त करने, जांच करने, और साफ़ करने देता है, जिनमें अन्य ऐप्स  के द्वारा पोस्ट की गई सूचनाएं भी शामिल हैं."</string>
+    <string name="permlab_bindNotificationListenerService" msgid="7057764742211656654">"नोटिफ़िकेशन श्रवणकर्ता सेवा से जुड़ें"</string>
+    <string name="permdesc_bindNotificationListenerService" msgid="985697918576902986">"धारक को नोटिफ़िकेशन श्रवणकर्ता सेवा के शीर्ष स्तरीय इंटरफ़ेस से जुड़ने देती है. सामान्य ऐप्स  के लिए कभी भी आवश्यक नहीं होनी चाहिए."</string>
     <string name="permlab_bindConditionProviderService" msgid="1180107672332704641">"किसी स्थिति प्रदाता सेवा से आबद्ध हों"</string>
     <string name="permdesc_bindConditionProviderService" msgid="1680513931165058425">"धारक को किसी स्थिति प्रदाता सेवा के शीर्ष-स्तर के इंटरफ़ेस से आबद्ध होने देती है. सामान्य ऐप्स के लिए कभी भी आवश्यक नहीं होना चाहिए."</string>
     <string name="permlab_bindDreamService" msgid="4153646965978563462">"भावी सेवा से आबद्ध करें"</string>
@@ -1084,13 +1084,13 @@
     <string name="volume_call" msgid="3941680041282788711">"कॉल के दौरान वॉल्‍यूम"</string>
     <string name="volume_bluetooth_call" msgid="2002891926351151534">"ब्लूटूथ कॉल के दौरान वॉल्‍यूम"</string>
     <string name="volume_alarm" msgid="1985191616042689100">"अलार्म वॉल्‍यूम"</string>
-    <string name="volume_notification" msgid="2422265656744276715">"नोटिफिकेशन वॉल्‍यूम"</string>
+    <string name="volume_notification" msgid="2422265656744276715">"नोटिफ़िकेशन वॉल्‍यूम"</string>
     <string name="volume_unknown" msgid="1400219669770445902">"आवाज़"</string>
     <string name="volume_icon_description_bluetooth" msgid="6538894177255964340">"ब्लूटूथ वॉल्‍यूम"</string>
     <string name="volume_icon_description_ringer" msgid="3326003847006162496">"रिंगटोन वॉल्‍यूम"</string>
     <string name="volume_icon_description_incall" msgid="8890073218154543397">"कॉल वॉल्‍यूम"</string>
     <string name="volume_icon_description_media" msgid="4217311719665194215">"मीडिया वॉल्‍यूम"</string>
-    <string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफिकेशन वॉल्‍यूम"</string>
+    <string name="volume_icon_description_notification" msgid="7044986546477282274">"नोटिफ़िकेशन वॉल्‍यूम"</string>
     <string name="ringtone_default" msgid="3789758980357696936">"डिफ़ॉल्‍ट रिंगटोन"</string>
     <string name="ringtone_default_with_actual" msgid="1767304850491060581">"डिफ़ॉल्ट (<xliff:g id="ACTUAL_RINGTONE">%1$s</xliff:g>)"</string>
     <string name="ringtone_silent" msgid="7937634392408977062">"कोई नहीं"</string>
@@ -1289,7 +1289,7 @@
     <string name="accessibility_binding_label" msgid="4148120742096474641">"सरल उपयोग"</string>
     <string name="wallpaper_binding_label" msgid="1240087844304687662">"वॉलपेपर"</string>
     <string name="chooser_wallpaper" msgid="7873476199295190279">"वॉलपेपर बदलें"</string>
-    <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफिकेशन श्रवणकर्ता"</string>
+    <string name="notification_listener_binding_label" msgid="2014162835481906429">"नोटिफ़िकेशन श्रवणकर्ता"</string>
     <string name="vr_listener_binding_label" msgid="4316591939343607306">"VR श्रोता"</string>
     <string name="condition_provider_service_binding_label" msgid="1321343352906524564">"स्थिति प्रदाता"</string>
     <string name="notification_ranker_binding_label" msgid="774540592299064747">"नोटिफ़िकेशन रैंकर सेवा"</string>
@@ -1703,7 +1703,7 @@
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> चयनित</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="5929663562028088222">"अवर्गीकृत"</string>
-    <string name="importance_from_user" msgid="7318955817386549931">"आपने इन नोटिफिकेशन का महत्व सेट किया है."</string>
+    <string name="importance_from_user" msgid="7318955817386549931">"आपने इन नोटिफ़िकेशन का महत्व सेट किया है."</string>
     <string name="importance_from_person" msgid="9160133597262938296">"यह मौजूद व्यक्तियों के कारण महत्वपूर्ण है."</string>
     <string name="user_creation_account_exists" msgid="1942606193570143289">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें?"</string>
     <string name="user_creation_adding" msgid="4482658054622099197">"<xliff:g id="APP">%1$s</xliff:g> को <xliff:g id="ACCOUNT">%2$s</xliff:g> के द्वारा एक नया उपयोगकर्ता बनाने दें (इस खाते वाला एक उपयोगकर्ता पहले से मौजूद है) ?"</string>
diff --git a/core/res/res/values-kn/strings.xml b/core/res/res/values-kn/strings.xml
index 0cabce8..8c8fe6c 100644
--- a/core/res/res/values-kn/strings.xml
+++ b/core/res/res/values-kn/strings.xml
@@ -1106,7 +1106,7 @@
       <item quantity="one">ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ</item>
       <item quantity="other">ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳು ಲಭ್ಯವಿವೆ</item>
     </plurals>
-    <string name="wifi_available_title" msgid="3817100557900599505">"ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಿ"</string>
+    <string name="wifi_available_title" msgid="3817100557900599505">"ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಿ"</string>
     <string name="wifi_available_title_connecting" msgid="1557292688310330032">"ಮುಕ್ತ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗುತ್ತಿದೆ"</string>
     <string name="wifi_available_title_connected" msgid="7542672851522241548">"ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಪಡಿಸಲಾಗಿದೆ"</string>
     <string name="wifi_available_title_failed_to_connect" msgid="6861772233582618132">"ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗೆ ಸಂಪರ್ಕಿಸಲು ಸಾಧ್ಯವಾಗಲಿಲ್ಲ"</string>
@@ -1431,7 +1431,7 @@
     <string name="bluetooth_a2dp_audio_route_name" msgid="8575624030406771015">"ಬ್ಲೂಟೂತ್‌ ಆಡಿಯೊ"</string>
     <string name="wireless_display_route_description" msgid="9070346425023979651">"ವಯರ್‌ಲೆಸ್ ಪ್ರದರ್ಶನ"</string>
     <string name="media_route_button_content_description" msgid="591703006349356016">"ಪಾತ್ರ"</string>
-    <string name="media_route_chooser_title" msgid="1751618554539087622">"ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಪಡಿಸಿ"</string>
+    <string name="media_route_chooser_title" msgid="1751618554539087622">"ಸಾಧನಕ್ಕೆ ಸಂಪರ್ಕಿಸಿ"</string>
     <string name="media_route_chooser_title_for_remote_display" msgid="3395541745872017583">"ಸಾಧನಕ್ಕೆ ಬಿತ್ತರಿಸುವ ಪರದೆ"</string>
     <string name="media_route_chooser_searching" msgid="4776236202610828706">"ಸಾಧನಗಳನ್ನು ಹುಡುಕಲಾಗುತ್ತಿದೆ…"</string>
     <string name="media_route_chooser_extended_settings" msgid="87015534236701604">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
diff --git a/core/res/res/values-mr/strings.xml b/core/res/res/values-mr/strings.xml
index 5f6631e..ff75939 100644
--- a/core/res/res/values-mr/strings.xml
+++ b/core/res/res/values-mr/strings.xml
@@ -203,7 +203,7 @@
     <string name="silent_mode_vibrate" msgid="7072043388581551395">"रिंगर कंपन"</string>
     <string name="silent_mode_ring" msgid="8592241816194074353">"रिंगर चालू"</string>
     <string name="reboot_to_update_title" msgid="6212636802536823850">"Android सिस्टीम अद्यतन"</string>
-    <string name="reboot_to_update_prepare" msgid="6305853831955310890">"अद्यतनित करण्यासाठी तयार करीत आहे…"</string>
+    <string name="reboot_to_update_prepare" msgid="6305853831955310890">"अपडेट करण्याची तयारी करत आहे…"</string>
     <string name="reboot_to_update_package" msgid="3871302324500927291">"अद्यतन पॅकेजची प्रक्रिया करीत आहे…"</string>
     <string name="reboot_to_update_reboot" msgid="6428441000951565185">"रीस्टार्ट करीत आहे..."</string>
     <string name="reboot_to_reset_title" msgid="4142355915340627490">"फॅक्‍टरी डेटा रीसेट"</string>
diff --git a/core/res/res/values-pt-rPT/strings.xml b/core/res/res/values-pt-rPT/strings.xml
index e90fec3..db9bc0b 100644
--- a/core/res/res/values-pt-rPT/strings.xml
+++ b/core/res/res/values-pt-rPT/strings.xml
@@ -63,7 +63,7 @@
     <string name="needPuk2" msgid="4526033371987193070">"Introduza o PUK2 para desbloquear o cartão SIM."</string>
     <string name="enablePin" msgid="209412020907207950">"Ação sem êxito. Ative o bloqueio do SIM/RUIM."</string>
     <plurals name="pinpuk_attempts" formatted="false" msgid="1251012001539225582">
-      <item quantity="one">You have <xliff:g id="NUMBER_1">%d</xliff:g> remaining attempts before SIM is locked.</item>
+      <item quantity="one">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativa antes de o cartão SIM ficar bloqueado.</item>
       <item quantity="other">Tem mais <xliff:g id="NUMBER_1">%d</xliff:g> tentativas antes de o cartão SIM ficar bloqueado.</item>
     </plurals>
     <string name="imei" msgid="2625429890869005782">"IMEI"</string>
@@ -176,7 +176,7 @@
     <string name="low_memory" product="tv" msgid="516619861191025923">"O armazenamento da TV está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <string name="low_memory" product="default" msgid="3475999286680000541">"O armazenamento do telemóvel está cheio. Elimine alguns ficheiros para libertar espaço."</string>
     <plurals name="ssl_ca_cert_warning" formatted="false" msgid="5106721205300213569">
-      <item quantity="one">Certificate authorities installed</item>
+      <item quantity="one">Autoridade de certificação instalada</item>
       <item quantity="other">Autoridades de certificação instaladas</item>
     </plurals>
     <string name="ssl_ca_cert_noti_by_unknown" msgid="4475437862189850602">"Por um terceiro desconhecido"</string>
@@ -232,7 +232,7 @@
     <string name="bugreport_option_full_title" msgid="6354382025840076439">"Relatório completo"</string>
     <string name="bugreport_option_full_summary" msgid="7210859858969115745">"Utilize esta opção para uma interferência mínima do sistema quando o dispositivo não responder ou estiver demasiado lento, ou quando precisar de todas as secções de relatório. Não permite introduzir mais detalhes ou tirar capturas de ecrã adicionais."</string>
     <plurals name="bugreport_countdown" formatted="false" msgid="6878900193900090368">
-      <item quantity="one">Taking screenshot for bug report in <xliff:g id="NUMBER_1">%d</xliff:g> seconds.</item>
+      <item quantity="one">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundo…</item>
       <item quantity="other">A tirar uma captura de ecrã do relatório de erro dentro de <xliff:g id="NUMBER_1">%d</xliff:g> segundos.</item>
     </plurals>
     <string name="global_action_toggle_silent_mode" msgid="8219525344246810925">"Modo silencioso"</string>
@@ -868,7 +868,7 @@
     <string name="oneMonthDurationPast" msgid="7396384508953779925">"Há 1 mês"</string>
     <string name="beforeOneMonthDurationPast" msgid="909134546836499826">"Há mais de 1 mês"</string>
     <plurals name="last_num_days" formatted="false" msgid="5104533550723932025">
-      <item quantity="one">Last <xliff:g id="COUNT_1">%d</xliff:g> days</item>
+      <item quantity="one">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dia</item>
       <item quantity="other">Últimos <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <string name="last_month" msgid="3959346739979055432">"Último mês"</string>
@@ -890,67 +890,67 @@
     <string name="years" msgid="6881577717993213522">"anos"</string>
     <string name="now_string_shortest" msgid="8912796667087856402">"agora"</string>
     <plurals name="duration_minutes_shortest" formatted="false" msgid="3957499975064245495">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>m</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> m</item>
     </plurals>
     <plurals name="duration_hours_shortest" formatted="false" msgid="3552182110578602356">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>h</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest" formatted="false" msgid="5213655532597081640">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>d</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> d</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> d</item>
     </plurals>
     <plurals name="duration_years_shortest" formatted="false" msgid="7848711145196397042">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g>y</item>
-      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g>a</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
+      <item quantity="other"><xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_shortest_future" formatted="false" msgid="3277614521231489951">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>m</item>
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>m</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> min</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> min</item>
     </plurals>
     <plurals name="duration_hours_shortest_future" formatted="false" msgid="2152452368397489370">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>h</item>
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>h</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> h</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> h</item>
     </plurals>
     <plurals name="duration_days_shortest_future" formatted="false" msgid="8088331502820295701">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>d</item>
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>d</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> d</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> d</item>
     </plurals>
     <plurals name="duration_years_shortest_future" formatted="false" msgid="2317006667145250301">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g>y</item>
-      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g>a</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item>
+      <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> a</item>
     </plurals>
     <plurals name="duration_minutes_relative" formatted="false" msgid="3178131706192980192">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> minutes ago</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> minuto</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
     </plurals>
     <plurals name="duration_hours_relative" formatted="false" msgid="676894109982008411">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> hours ago</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> hora</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
     </plurals>
     <plurals name="duration_days_relative" formatted="false" msgid="2203515825765397130">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> days ago</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> dia</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <plurals name="duration_years_relative" formatted="false" msgid="4820062134188885734">
-      <item quantity="one"><xliff:g id="COUNT_1">%d</xliff:g> years ago</item>
+      <item quantity="one">há <xliff:g id="COUNT_1">%d</xliff:g> ano</item>
       <item quantity="other">há <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
     </plurals>
     <plurals name="duration_minutes_relative_future" formatted="false" msgid="4655043589817680966">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> minutes</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minuto</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> minutos</item>
     </plurals>
     <plurals name="duration_hours_relative_future" formatted="false" msgid="8084579714205223891">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> hours</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> hora</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> horas</item>
     </plurals>
     <plurals name="duration_days_relative_future" formatted="false" msgid="333215369363433992">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> days</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dia</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> dias</item>
     </plurals>
     <plurals name="duration_years_relative_future" formatted="false" msgid="8644862986413104011">
-      <item quantity="one">in <xliff:g id="COUNT_1">%d</xliff:g> years</item>
+      <item quantity="one">dentro de <xliff:g id="COUNT_1">%d</xliff:g> ano</item>
       <item quantity="other">dentro de <xliff:g id="COUNT_1">%d</xliff:g> anos</item>
     </plurals>
     <string name="VideoView_error_title" msgid="3534509135438353077">"Problema com o vídeo"</string>
@@ -1099,11 +1099,11 @@
     <string name="ringtone_picker_title_notification" msgid="4837740874822788802">"Sons de notificação"</string>
     <string name="ringtone_unknown" msgid="3914515995813061520">"Desconhecido"</string>
     <plurals name="wifi_available" formatted="false" msgid="7900333017752027322">
-      <item quantity="one">Wi-Fi networks available</item>
+      <item quantity="one">Rede Wi-Fi disponível</item>
       <item quantity="other">Redes Wi-Fi disponíveis</item>
     </plurals>
     <plurals name="wifi_available_detailed" formatted="false" msgid="1140699367193975606">
-      <item quantity="one">Open Wi-Fi networks available</item>
+      <item quantity="one">Rede Wi-Fi aberta disponível</item>
       <item quantity="other">Redes Wi-Fi abertas disponíveis</item>
     </plurals>
     <string name="wifi_available_title" msgid="3817100557900599505">"Ligar à rede Wi-Fi aberta"</string>
@@ -1316,7 +1316,7 @@
     <string name="no_matches" msgid="8129421908915840737">"Sem correspondências"</string>
     <string name="find_on_page" msgid="1946799233822820384">"Localizar na página"</string>
     <plurals name="matches_found" formatted="false" msgid="1210884353962081884">
-      <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> of <xliff:g id="TOTAL">%d</xliff:g></item>
+      <item quantity="one"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
       <item quantity="other"><xliff:g id="INDEX">%d</xliff:g> de <xliff:g id="TOTAL">%d</xliff:g></item>
     </plurals>
     <string name="action_mode_done" msgid="7217581640461922289">"Concluído"</string>
@@ -1602,7 +1602,7 @@
     <string name="restr_pin_error_doesnt_match" msgid="2224214190906994548">"Os PINs não correspondem. Tente novamente."</string>
     <string name="restr_pin_error_too_short" msgid="8173982756265777792">"O PIN é demasiado pequeno. Deve ter, no mínimo, 4 dígitos."</string>
     <plurals name="restr_pin_countdown" formatted="false" msgid="9061246974881224688">
-      <item quantity="one">Try again in <xliff:g id="COUNT">%d</xliff:g> seconds</item>
+      <item quantity="one">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundo</item>
       <item quantity="other">Tente novamente dentro de <xliff:g id="COUNT">%d</xliff:g> segundos</item>
     </plurals>
     <string name="restr_pin_try_later" msgid="973144472490532377">"Tente novamente mais tarde"</string>
@@ -1635,35 +1635,35 @@
     <string name="data_saver_enable_title" msgid="4674073932722787417">"Ativar a Poupança de dados?"</string>
     <string name="data_saver_enable_button" msgid="7147735965247211818">"Ativar"</string>
     <plurals name="zen_mode_duration_minutes_summary" formatted="false" msgid="4367877408072000848">
-      <item quantity="one">For %1$d minutes (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="other">Durante %1$d minutos (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="one">Durante %1$d minuto (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d minutos (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_summary_short" formatted="false" msgid="6830154222366042597">
-      <item quantity="one">For %1$d min (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="other">Durante %1$d min (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="one">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d min (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary" formatted="false" msgid="8152974162096743862">
-      <item quantity="one">For %1$d hours (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="other">Durante %1$d horas (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="one">Durante %1$d hora (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d horas (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_summary_short" formatted="false" msgid="4787552595253082371">
-      <item quantity="one">For %1$d hr (until <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
-      <item quantity="other">Durante %1$d h (até às <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="one">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
+      <item quantity="other">Durante %1$d h (até à(s) <xliff:g id="FORMATTEDTIME_1">%2$s</xliff:g>)</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes" formatted="false" msgid="5127407202506485571">
-      <item quantity="one">For %d minutes</item>
+      <item quantity="one">Durante %d minuto</item>
       <item quantity="other">Durante %d minutos</item>
     </plurals>
     <plurals name="zen_mode_duration_minutes_short" formatted="false" msgid="2199350154433426128">
-      <item quantity="one">For %d min</item>
+      <item quantity="one">Durante %d min</item>
       <item quantity="other">Durante %d min</item>
     </plurals>
     <plurals name="zen_mode_duration_hours" formatted="false" msgid="3938821308277433854">
-      <item quantity="one">For %d hours</item>
+      <item quantity="one">Durante %d hora</item>
       <item quantity="other">Durante %d horas</item>
     </plurals>
     <plurals name="zen_mode_duration_hours_short" formatted="false" msgid="6748277774662434217">
-      <item quantity="one">For %d hr</item>
+      <item quantity="one">Durante %d h</item>
       <item quantity="other">Durante %d h</item>
     </plurals>
     <string name="zen_mode_until" msgid="7336308492289875088">"Até às <xliff:g id="FORMATTEDTIME">%1$s</xliff:g>"</string>
@@ -1699,7 +1699,7 @@
     <string name="close_button_text" msgid="3937902162644062866">"Fechar"</string>
     <string name="notification_messaging_title_template" msgid="3452480118762691020">"<xliff:g id="CONVERSATION_TITLE">%1$s</xliff:g>: <xliff:g id="SENDER_NAME">%2$s</xliff:g>"</string>
     <plurals name="selected_count" formatted="false" msgid="7187339492915744615">
-      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selected</item>
+      <item quantity="one"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionado</item>
       <item quantity="other"><xliff:g id="COUNT_1">%1$d</xliff:g> selecionados</item>
     </plurals>
     <string name="default_notification_channel_label" msgid="5929663562028088222">"Sem categoria"</string>
@@ -1763,7 +1763,7 @@
     <string name="autofill_error_cannot_autofill" msgid="7402758580060110371">"Não é possível preencher automaticamente o conteúdo"</string>
     <string name="autofill_picker_no_suggestions" msgid="3908514303773350735">"Sem sugestões do preenchimento automático"</string>
     <plurals name="autofill_picker_some_suggestions" formatted="false" msgid="5506565809835815274">
-      <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> autofill suggestions</item>
+      <item quantity="one"><xliff:g id="COUNT">%1$s</xliff:g> sugestão do preenchimento automático</item>
       <item quantity="other"><xliff:g id="COUNT">%1$s</xliff:g> sugestões do preenchimento automático</item>
     </plurals>
     <string name="autofill_save_title" msgid="3345527308992082601">"Pretende guardar no &lt;b&gt;<xliff:g id="LABEL">%1$s</xliff:g>&lt;/b&gt;?"</string>
diff --git a/core/res/res/values-uk/strings.xml b/core/res/res/values-uk/strings.xml
index 7d1871f..7b54518 100644
--- a/core/res/res/values-uk/strings.xml
+++ b/core/res/res/values-uk/strings.xml
@@ -21,10 +21,10 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
     <string name="byteShort" msgid="8340973892742019101">"б"</string>
-    <string name="kilobyteShort" msgid="7542884022844556968">"Кб"</string>
-    <string name="megabyteShort" msgid="6355851576770428922">"Мб"</string>
-    <string name="gigabyteShort" msgid="3259882455212193214">"Гб"</string>
-    <string name="terabyteShort" msgid="231613018159186962">"Тб"</string>
+    <string name="kilobyteShort" msgid="7542884022844556968">"КБ"</string>
+    <string name="megabyteShort" msgid="6355851576770428922">"МБ"</string>
+    <string name="gigabyteShort" msgid="3259882455212193214">"ГБ"</string>
+    <string name="terabyteShort" msgid="231613018159186962">"ТБ"</string>
     <string name="petabyteShort" msgid="5637816680144990219">"Пб"</string>
     <string name="fileSizeSuffix" msgid="8897567456150907538">"<xliff:g id="NUMBER">%1$s</xliff:g> <xliff:g id="UNIT">%2$s</xliff:g>"</string>
     <string name="durationDays" msgid="6652371460511178259">"<xliff:g id="DAYS">%1$d</xliff:g> дн."</string>
@@ -1027,7 +1027,7 @@
     <string name="browse" msgid="6993590095938149861">"Веб-переглядач"</string>
     <string name="low_internal_storage_view_title" msgid="5576272496365684834">"Закінчується пам’ять"</string>
     <string name="low_internal_storage_view_text" msgid="6640505817617414371">"Деякі системні функції можуть не працювати"</string>
-    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Недостатньо місця для системи. Переконайтесь, що на пристрої є 250 Мб вільного місця, і повторіть спробу."</string>
+    <string name="low_internal_storage_view_text_no_boot" msgid="6935190099204693424">"Недостатньо місця для системи. Переконайтесь, що на пристрої є 250 МБ вільного місця, і повторіть спробу."</string>
     <string name="app_running_notification_title" msgid="8718335121060787914">"<xliff:g id="APP_NAME">%1$s</xliff:g> працює"</string>
     <string name="app_running_notification_text" msgid="1197581823314971177">"Торкніться, щоб дізнатися більше або зупинити додаток."</string>
     <string name="ok" msgid="5970060430562524910">"OK"</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 7b437fa..f56abc3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -291,6 +291,11 @@
     <!-- Mask to use when checking skb mark defined in config_networkWakeupPacketMark above. -->
     <integer name="config_networkWakeupPacketMask">0</integer>
 
+    <!-- Whether the APF Filter in the device should filter out IEEE 802.3 Frames
+         Those frames are identified by the field Eth-type having values
+         less than 0x600 -->
+    <bool translatable="false" name="config_apfDrop802_3Frames">true</bool>
+
     <!-- Default value for ConnectivityManager.getMultipathPreference() on metered networks. Actual
          device behaviour is controlled by Settings.Global.NETWORK_METERED_MULTIPATH_PREFERENCE.
          This is the default value of that setting. -->
@@ -954,15 +959,7 @@
         <item>30</item>
     </integer-array>
 
-    <!-- Vibrator pattern for feedback about booting with safe mode disabled -->
-    <integer-array name="config_safeModeDisabledVibePattern">
-        <item>0</item>
-        <item>1</item>
-        <item>20</item>
-        <item>21</item>
-    </integer-array>
-
-    <!-- Vibrator pattern for feedback about booting with safe mode disabled -->
+    <!-- Vibrator pattern for feedback about booting with safe mode enabled -->
     <integer-array name="config_safeModeEnabledVibePattern">
         <item>0</item>
         <item>1</item>
@@ -1857,6 +1854,11 @@
          states. -->
     <bool name="config_dozeAlwaysOnDisplayAvailable">false</bool>
 
+    <!-- Whether the display hardware requires we go to the off state before transitioning
+         out of any doze states. -->
+    <bool name="config_displayTransitionOffAfterDoze">false</bool>
+
+
     <!-- Power Management: Specifies whether to decouple the auto-suspend state of the
          device from the display on/off state.
 
@@ -2775,6 +2777,9 @@
     <!-- True if camera app should be pinned via Pinner Service -->
     <bool name="config_pinnerCameraApp">false</bool>
 
+    <!-- Component that runs demo mode when it is enabled. -->
+    <string name="config_demoModePackage" translatable="false"></string>
+
     <!-- Component that is the default launcher when demo mode is enabled. -->
     <string name="config_demoModeLauncherComponent">com.android.retaildemo/.DemoPlayer</string>
 
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index 9f9c883..743f4ad 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -580,6 +580,21 @@
     <dimen name="item_touch_helper_swipe_escape_velocity">120dp</dimen>
     <dimen name="item_touch_helper_swipe_escape_max_velocity">800dp</dimen>
 
+    <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined by the maximum notification height -->
+    <dimen name="notification_custom_view_max_image_height">284dp</dimen>
+    <!-- The maximum height of any image in a remote view. This is applied to all images in custom remoteviews. This value is determined a maximum notification width -->
+    <dimen name="notification_custom_view_max_image_width">450dp</dimen>
+    <!-- The maximum height of a big picture in a notification. The images will be reduced to that height in case they are bigger. This value is determined by the maximum notification height -->
+    <dimen name="notification_big_picture_max_height">284dp</dimen>
+    <!-- The maximum width of a big picture in a notification. The images will be reduced to that width in case they are bigger. This value is determined by the standard panel size -->
+    <dimen name="notification_big_picture_max_width">416dp</dimen>
+    <!-- The maximum height of a image in a media notification. The images will be reduced to that height in case they are bigger. This value is determined by the expanded media template-->
+    <dimen name="notification_media_image_max_height">140dp</dimen>
+    <!-- The maximum width of a image in a media notification. The images will be reduced to that width in case they are bigger.-->
+    <dimen name="notification_media_image_max_width">280dp</dimen>
+    <!-- The size of the right icon -->
+    <dimen name="notification_right_icon_size">40dp</dimen>
+
     <!-- Max width/height of the autofill data set picker as a fraction of the screen width/height -->
     <dimen name="autofill_dataset_picker_max_size">90%</dimen>
 
diff --git a/core/res/res/values/locale_config.xml b/core/res/res/values/locale_config.xml
index ba14843..0ba8b57 100644
--- a/core/res/res/values/locale_config.xml
+++ b/core/res/res/values/locale_config.xml
@@ -463,8 +463,6 @@
         <item>teo-KE</item> <!-- Teso (Kenya) -->
         <item>teo-UG</item> <!-- Teso (Uganda) -->
         <item>th-TH</item> <!-- Thai (Thailand) -->
-        <item>ti-ER</item> <!-- Tigrinya (Eritrea) -->
-        <item>ti-ET</item> <!-- Tigrinya (Ethiopia) -->
         <item>to-TO</item> <!-- Tongan (Tonga) -->
         <item>tr-CY</item> <!-- Turkish (Cyprus) -->
         <item>tr-TR</item> <!-- Turkish (Turkey) -->
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index bd8e14ea..ab26ae1 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -591,10 +591,7 @@
     <string name="notification_header_divider_symbol_with_spaces" translatable="false">" • "</string>
 
     <!-- Text shown in place of notification contents when the notification is hidden on a secure lockscreen -->
-    <string name="notification_hidden_text">Contents hidden</string>
-
-    <!-- Text shown in place of notification contents when the notification is hidden by policy on a secure lockscreen -->
-    <string name="notification_hidden_by_policy_text">Contents hidden by policy</string>
+    <string name="notification_hidden_text">New notification</string>
 
     <!-- Text shown when viewing channel settings for notifications related to the virtual keyboard -->
     <string name="notification_channel_virtual_keyboard">Virtual keyboard</string>
@@ -4590,22 +4587,10 @@
     <!-- The representation of a time duration when negative. An example is -1:14. This can be used with a countdown timer for example.-->
     <string name="negative_duration">\u2212<xliff:g id="time" example="1:14">%1$s</xliff:g></string>
 
-    <!-- Title of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
-    <string name="reset_retail_demo_mode_title">Reset device?</string>
-    <!-- Text of notification to start a new demo session when device is in retail mode [CHAR LIMIT=NONE] -->
-    <string name="reset_retail_demo_mode_text">Tap to reset device</string>
     <!-- Text of dialog shown when starting a demo user for the first time [CHAR LIMIT=40] -->
     <string name="demo_starting_message">Starting demo\u2026</string>
     <!-- Text of dialog shown when starting a new demo user in retail demo mode [CHAR LIMIT=40] -->
     <string name="demo_restarting_message">Resetting device\u2026</string>
-    <!-- Title of the dialog shown when user inactivity times out in retail demo mode [CHAR LIMIT=40] -->
-    <string name="demo_user_inactivity_timeout_title">Reset device?</string>
-    <!-- Warning message shown when user inactivity times out in retail demo mode [CHAR LIMIT=none] -->
-    <string name="demo_user_inactivity_timeout_countdown">You\u2019ll lose any changes and the demo will start again in <xliff:g id="timeout" example="9">%1$s</xliff:g> seconds\u2026</string>
-    <!-- Text of button to allow user to abort countdown and continue current session in retail demo mode [CHAR LIMIT=40] -->
-    <string name="demo_user_inactivity_timeout_left_button">Cancel</string>
-    <!-- Text of button to allow user to abort countdown and immediately start another session in retail demo mode [CHAR LIMIT=40] -->
-    <string name="demo_user_inactivity_timeout_right_button">Reset now</string>
 
     <!-- Accessibilty string added to a widget that has been suspended [CHAR LIMIT=20] -->
     <string name="suspended_widget_accessibility">Disabled <xliff:g id="label" example="Calendar">%1$s</xliff:g></string>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 2f81f43..a3b7ee8 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1166,6 +1166,7 @@
   <java-symbol type="string" name="lockscreen_transport_pause_description" />
   <java-symbol type="string" name="config_ethernet_tcp_buffers" />
   <java-symbol type="string" name="config_wifi_tcp_buffers" />
+  <java-symbol type="string" name="config_demoModePackage" />
   <java-symbol type="string" name="config_demoModeLauncherComponent" />
   <java-symbol type="string" name="config_carrierDemoModePassword" />
   <java-symbol type="string" name="config_carrierDemoModeSetting" />
@@ -1556,7 +1557,6 @@
   <java-symbol type="array" name="config_autoRotationTiltTolerance" />
   <java-symbol type="array" name="config_keyboardTapVibePattern" />
   <java-symbol type="array" name="config_longPressVibePattern" />
-  <java-symbol type="array" name="config_safeModeDisabledVibePattern" />
   <java-symbol type="array" name="config_safeModeEnabledVibePattern" />
   <java-symbol type="array" name="config_virtualKeyVibePattern" />
   <java-symbol type="attr" name="actionModePopupWindowStyle" />
@@ -1843,6 +1843,7 @@
   <java-symbol type="integer" name="config_networkAvoidBadWifi" />
   <java-symbol type="integer" name="config_networkWakeupPacketMark" />
   <java-symbol type="integer" name="config_networkWakeupPacketMask" />
+  <java-symbol type="bool" name="config_apfDrop802_3Frames" />
   <java-symbol type="integer" name="config_networkMeteredMultipathPreference" />
   <java-symbol type="integer" name="config_notificationsBatteryFullARGB" />
   <java-symbol type="integer" name="config_notificationsBatteryLedOff" />
@@ -2559,7 +2560,6 @@
   <java-symbol type="id" name="notification_material_reply_text_3" />
 
   <java-symbol type="string" name="notification_hidden_text" />
-  <java-symbol type="string" name="notification_hidden_by_policy_text" />
   <java-symbol type="id" name="app_name_text" />
   <java-symbol type="id" name="header_text" />
   <java-symbol type="id" name="expand_button" />
@@ -2945,6 +2945,14 @@
   <java-symbol type="style" name="AutofillDatasetPicker" />
   <java-symbol type="dimen" name="autofill_dataset_picker_max_size"/>
 
+  <java-symbol type="dimen" name="notification_big_picture_max_height"/>
+  <java-symbol type="dimen" name="notification_big_picture_max_width"/>
+  <java-symbol type="dimen" name="notification_media_image_max_width"/>
+  <java-symbol type="dimen" name="notification_media_image_max_height"/>
+  <java-symbol type="dimen" name="notification_right_icon_size"/>
+  <java-symbol type="dimen" name="notification_custom_view_max_image_height"/>
+  <java-symbol type="dimen" name="notification_custom_view_max_image_width"/>
+
   <!-- Accessibility fingerprint gestures -->
   <java-symbol type="string" name="capability_title_canCaptureFingerprintGestures" />
   <java-symbol type="string" name="capability_desc_canCaptureFingerprintGestures" />
@@ -3054,6 +3062,7 @@
   <java-symbol type="bool" name="config_handleVolumeKeysInWindowManager" />
   <java-symbol type="integer" name="config_inCallNotificationVolumeRelative" />
   <java-symbol type="bool" name="config_dozeAlwaysOnDisplayAvailable" />
+  <java-symbol type="bool" name="config_displayTransitionOffAfterDoze" />
   <java-symbol type="integer" name="config_storageManagerDaystoRetainDefault" />
   <java-symbol type="string" name="config_headlineFontFamily" />
   <java-symbol type="string" name="config_headlineFontFamilyLight" />
diff --git a/core/tests/coretests/src/android/provider/SettingsBackupTest.java b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
index ca53885..a979ac8 100644
--- a/core/tests/coretests/src/android/provider/SettingsBackupTest.java
+++ b/core/tests/coretests/src/android/provider/SettingsBackupTest.java
@@ -298,7 +298,6 @@
                     Settings.Global.RECOMMENDED_NETWORK_EVALUATOR_CACHE_EXPIRY_MS,
                     Settings.Global.READ_EXTERNAL_STORAGE_ENFORCED_DEFAULT,
                     Settings.Global.REQUIRE_PASSWORD_TO_DECRYPT,
-                    Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
                     Settings.Global.SAFE_BOOT_DISALLOWED,
                     Settings.Global.SAMPLING_PROFILER_MS,
                     Settings.Global.SELINUX_STATUS,
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
index af4a6d9..8fd4e31 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsSensorTest.java
@@ -400,7 +400,7 @@
         assertNotNull(sensor.getSensorBackgroundTime());
 
         // Reset the stats. Since the sensor is still running, we should still see the timer
-        bi.getUidStatsLocked(UID).reset();
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
 
         sensor = uid.getSensorStats().get(SENSOR_ID);
         assertNotNull(sensor);
@@ -410,9 +410,111 @@
         bi.noteStopSensorLocked(UID, SENSOR_ID);
 
         // Now the sensor timer has stopped so this reset should also take out the sensor.
-        bi.getUidStatsLocked(UID).reset();
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
 
         sensor = uid.getSensorStats().get(SENSOR_ID);
         assertNull(sensor);
     }
+
+    @SmallTest
+    public void testSensorResetTimes() throws Exception {
+        final MockClocks clocks = new MockClocks();
+        MockBatteryStatsImpl bi = new MockBatteryStatsImpl(clocks);
+        final int which = BatteryStats.STATS_SINCE_CHARGED;
+        bi.mForceOnBattery = true;
+        clocks.realtime = 100; // in ms
+        clocks.uptime = 100; // in ms
+
+        // TimeBases are on for some time.
+        BatteryStatsImpl.TimeBase timeBase = bi.getOnBatteryTimeBase();
+        BatteryStatsImpl.TimeBase bgTimeBase = bi.getOnBatteryBackgroundTimeBase(UID);
+        timeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        bgTimeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        bi.noteUidProcessStateLocked(UID, ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // TimeBases are turned off
+        timeBase.setRunning(false, clocks.uptime * 1000, clocks.realtime * 1000);
+        bgTimeBase.setRunning(false, clocks.uptime * 1000, clocks.realtime * 1000);
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Timer is turned on
+        bi.noteStartSensorLocked(UID, SENSOR_ID);
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Timebase was off so times are all 0.
+        BatteryStats.Uid.Sensor sensor = bi.getUidStats().get(UID).getSensorStats().get(SENSOR_ID);
+        BatteryStats.Timer timer = sensor.getSensorTime();
+        BatteryStats.Timer bgTimer = sensor.getSensorBackgroundTime();
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Reset the stats. Since the sensor is still running, we should still see the timer
+        // but still with 0 times.
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Now stop the timer. The times should still be 0.
+        bi.noteStopSensorLocked(UID, SENSOR_ID);
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        // Now repeat with the TimeBases turned on the entire time.
+        timeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        bgTimeBase.setRunning(true, clocks.uptime * 1000, clocks.realtime * 1000);
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Timer is turned on
+        bi.noteStartSensorLocked(UID, SENSOR_ID);
+
+        clocks.realtime += 111;
+        clocks.uptime += 1111;
+
+        // Timebase and timer was on so times have increased.
+        assertEquals(111_000, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(111, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(111_000, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(111, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 100;
+        clocks.uptime += 100;
+
+        // Reset the stats. Since the sensor is still running, we should still see the timer
+        // but with 0 times.
+        bi.getUidStatsLocked(UID).reset(clocks.uptime * 1000, clocks.realtime * 1000);
+        assertEquals(0, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(0, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(0, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+
+        clocks.realtime += 112;
+        clocks.uptime += 112;
+
+        // Now stop the timer. The times should have increased since the timebase was on.
+        bi.noteStopSensorLocked(UID, SENSOR_ID);
+        assertEquals(112_000, timer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(112, timer.getTotalDurationMsLocked(clocks.realtime));
+        assertEquals(112_000, bgTimer.getTotalTimeLocked(1000*clocks.realtime, which));
+        assertEquals(112, bgTimer.getTotalDurationMsLocked(clocks.realtime));
+    }
 }
diff --git a/core/tests/utiltests/AndroidManifest.xml b/core/tests/utiltests/AndroidManifest.xml
index da09894..d6384e7 100644
--- a/core/tests/utiltests/AndroidManifest.xml
+++ b/core/tests/utiltests/AndroidManifest.xml
@@ -40,6 +40,7 @@
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
     <uses-permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD" />
+    <uses-permission android:name="android.permission.ACCESS_KEYGUARD_SECURE_STORAGE" />
 
     <application>
         <uses-library android:name="android.test.runner" />
diff --git a/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
new file mode 100644
index 0000000..b18ee17
--- /dev/null
+++ b/core/tests/utiltests/src/com/android/internal/util/LockPatternUtilsTest.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2017 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.internal.util;
+
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_MANAGED;
+import static android.app.admin.DevicePolicyManager.PASSWORD_QUALITY_UNSPECIFIED;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.content.ContextWrapper;
+import android.content.pm.UserInfo;
+import android.os.UserManager;
+import android.provider.Settings;
+import android.support.test.InstrumentationRegistry;
+import android.support.test.filters.SmallTest;
+import android.support.test.runner.AndroidJUnit4;
+
+import android.test.mock.MockContentResolver;
+import com.android.internal.util.test.FakeSettingsProvider;
+import com.android.internal.widget.ILockSettings;
+import com.android.internal.widget.LockPatternUtils;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mockito;
+
+@RunWith(AndroidJUnit4.class)
+@SmallTest
+public class LockPatternUtilsTest {
+
+    private static final int DEMO_USER_ID = 5;
+
+    private LockPatternUtils mLockPatternUtils;
+
+    private void configureTest(boolean isSecure, boolean isDemoUser, int deviceDemoMode)
+            throws Exception {
+        final Context context = spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
+
+        final MockContentResolver cr = new MockContentResolver(context);
+        cr.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
+        when(context.getContentResolver()).thenReturn(cr);
+        Settings.Global.putInt(cr, Settings.Global.DEVICE_DEMO_MODE, deviceDemoMode);
+
+        final ILockSettings ils = Mockito.mock(ILockSettings.class);
+        when(ils.havePassword(DEMO_USER_ID)).thenReturn(isSecure);
+        when(ils.getLong("lockscreen.password_type", PASSWORD_QUALITY_UNSPECIFIED, DEMO_USER_ID))
+                .thenReturn((long) PASSWORD_QUALITY_MANAGED);
+        // TODO(b/63758238): stop spying the class under test
+        mLockPatternUtils = spy(new LockPatternUtils(context));
+        when(mLockPatternUtils.getLockSettings()).thenReturn(ils);
+
+        final UserInfo userInfo = Mockito.mock(UserInfo.class);
+        when(userInfo.isDemo()).thenReturn(isDemoUser);
+        final UserManager um = Mockito.mock(UserManager.class);
+        when(um.getUserInfo(DEMO_USER_ID)).thenReturn(userInfo);
+        when(context.getSystemService(Context.USER_SERVICE)).thenReturn(um);
+    }
+
+    @Test
+    public void isLockScreenDisabled_isDemoUser_true() throws Exception {
+        configureTest(false, true, 2);
+        assertTrue(mLockPatternUtils.isLockScreenDisabled(DEMO_USER_ID));
+    }
+
+    @Test
+    public void isLockScreenDisabled_isSecureAndDemoUser_false() throws Exception {
+        configureTest(true, true, 2);
+        assertFalse(mLockPatternUtils.isLockScreenDisabled(DEMO_USER_ID));
+    }
+
+    @Test
+    public void isLockScreenDisabled_isNotDemoUser_false() throws Exception {
+        configureTest(false, false, 2);
+        assertFalse(mLockPatternUtils.isLockScreenDisabled(DEMO_USER_ID));
+    }
+
+    @Test
+    public void isLockScreenDisabled_isNotInDemoMode_false() throws Exception {
+        configureTest(false, true, 0);
+        assertFalse(mLockPatternUtils.isLockScreenDisabled(DEMO_USER_ID));
+    }
+}
diff --git a/graphics/java/android/graphics/drawable/Icon.java b/graphics/java/android/graphics/drawable/Icon.java
index aa38f31..c329918 100644
--- a/graphics/java/android/graphics/drawable/Icon.java
+++ b/graphics/java/android/graphics/drawable/Icon.java
@@ -805,6 +805,43 @@
     };
 
     /**
+     * Scale down a bitmap to a given max width and max height. The scaling will be done in a uniform way
+     * @param bitmap the bitmap to scale down
+     * @param maxWidth the maximum width allowed
+     * @param maxHeight the maximum height allowed
+     *
+     * @return the scaled bitmap if necessary or the original bitmap if no scaling was needed
+     * @hide
+     */
+    public static Bitmap scaleDownIfNecessary(Bitmap bitmap, int maxWidth, int maxHeight) {
+        int bitmapWidth = bitmap.getWidth();
+        int bitmapHeight = bitmap.getHeight();
+        if (bitmapWidth > maxWidth || bitmapHeight > maxHeight) {
+            float scale = Math.min((float) maxWidth / bitmapWidth,
+                    (float) maxHeight / bitmapHeight);
+            bitmap = Bitmap.createScaledBitmap(bitmap, (int) (scale * bitmapWidth),
+                    (int) (scale * bitmapHeight), true /* filter */);
+        }
+        return bitmap;
+    }
+
+    /**
+     * Scale down this icon to a given max width and max height.
+     * The scaling will be done in a uniform way and currently only bitmaps are supported.
+     * @param maxWidth the maximum width allowed
+     * @param maxHeight the maximum height allowed
+     *
+     * @hide
+     */
+    public void scaleDownIfNecessary(int maxWidth, int maxHeight) {
+        if (mType != TYPE_BITMAP && mType != TYPE_ADAPTIVE_BITMAP) {
+            return;
+        }
+        Bitmap bitmap = getBitmap();
+        setBitmap(scaleDownIfNecessary(bitmap, maxWidth, maxHeight));
+    }
+
+    /**
      * Implement this interface to receive a callback when
      * {@link #loadDrawableAsync(Context, OnDrawableLoadedListener, Handler) loadDrawableAsync}
      * is finished and your Drawable is ready.
diff --git a/media/java/android/media/MediaHTTPConnection.java b/media/java/android/media/MediaHTTPConnection.java
index dd731df..aae1f51 100644
--- a/media/java/android/media/MediaHTTPConnection.java
+++ b/media/java/android/media/MediaHTTPConnection.java
@@ -61,9 +61,9 @@
     private final static int MAX_REDIRECTS = 20;
 
     public MediaHTTPConnection() {
-        CookieManager cookieManager = (CookieManager)CookieHandler.getDefault();
-        if (cookieManager == null) {
-            Log.w(TAG, "MediaHTTPConnection: Unexpected. No CookieManager found.");
+        CookieHandler cookieHandler = CookieHandler.getDefault();
+        if (cookieHandler == null) {
+            Log.w(TAG, "MediaHTTPConnection: Unexpected. No CookieHandler found.");
         }
 
         native_setup();
diff --git a/media/java/android/media/MediaHTTPService.java b/media/java/android/media/MediaHTTPService.java
index b678630..3a0e58a 100644
--- a/media/java/android/media/MediaHTTPService.java
+++ b/media/java/android/media/MediaHTTPService.java
@@ -41,34 +41,40 @@
         synchronized (mCookieStoreInitialized) {
             // Only need to do it once for all connections
             if ( !mCookieStoreInitialized )  {
-                CookieManager cookieManager = (CookieManager)CookieHandler.getDefault();
-                if (cookieManager == null) {
-                    cookieManager = new CookieManager();
-                    CookieHandler.setDefault(cookieManager);
-                    Log.v(TAG, "makeHTTPConnection: CookieManager created: " + cookieManager);
-                }
-                else {
-                    Log.v(TAG, "makeHTTPConnection: CookieManager(" + cookieManager + ") exists.");
+                CookieHandler cookieHandler = CookieHandler.getDefault();
+                if (cookieHandler == null) {
+                    cookieHandler = new CookieManager();
+                    CookieHandler.setDefault(cookieHandler);
+                    Log.v(TAG, "makeHTTPConnection: CookieManager created: " + cookieHandler);
+                } else {
+                    Log.v(TAG, "makeHTTPConnection: CookieHandler (" + cookieHandler + ") exists.");
                 }
 
                 // Applying the bootstrapping cookies
                 if ( mCookies != null ) {
-                    CookieStore store = cookieManager.getCookieStore();
-                    for ( HttpCookie cookie : mCookies ) {
-                        try {
-                            store.add(null, cookie);
-                        } catch ( Exception e ) {
-                            Log.v(TAG, "makeHTTPConnection: CookieStore.add" + e);
+                    if ( cookieHandler instanceof CookieManager ) {
+                        CookieManager cookieManager = (CookieManager)cookieHandler;
+                        CookieStore store = cookieManager.getCookieStore();
+                        for ( HttpCookie cookie : mCookies ) {
+                            try {
+                                store.add(null, cookie);
+                            } catch ( Exception e ) {
+                                Log.v(TAG, "makeHTTPConnection: CookieStore.add" + e);
+                            }
+                            //for extended debugging when needed
+                            //Log.v(TAG, "MediaHTTPConnection adding Cookie[" + cookie.getName() +
+                            //        "]: " + cookie);
                         }
-                        //for extended debugging when needed
-                        //Log.v(TAG, "MediaHTTPConnection adding Cookie[" + cookie.getName() +
-                        //        "]: " + cookie);
+                    } else {
+                        Log.w(TAG, "makeHTTPConnection: The installed CookieHandler is not a "
+                                + "CookieManager. Can’t add the provided cookies to the cookie "
+                                + "store.");
                     }
                 }   // mCookies
 
                 mCookieStoreInitialized = true;
 
-                Log.v(TAG, "makeHTTPConnection(" + this + "): cookieManager: " + cookieManager +
+                Log.v(TAG, "makeHTTPConnection(" + this + "): cookieHandler: " + cookieHandler +
                         " Cookies: " + mCookies);
             }   // mCookieStoreInitialized
         }   // synchronized
@@ -92,5 +98,4 @@
 
         return null;
     }
-
 }
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index d5509c1..8caba81 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -732,6 +732,15 @@
     }
 
     /**
+     * Returns a Bluetooth route if available, otherwise the default route.
+     * @hide
+     */
+    public RouteInfo getFallbackRoute() {
+        return (sStatic.mBluetoothA2dpRoute != null)
+                ? sStatic.mBluetoothA2dpRoute : sStatic.mDefaultAudioVideo;
+    }
+
+    /**
      * @hide for use by framework routing UI
      */
     public RouteCategory getSystemCategory() {
@@ -913,6 +922,19 @@
                 (route == btRoute || route == sStatic.mDefaultAudioVideo)) {
             try {
                 sStatic.mAudioService.setBluetoothA2dpOn(route == btRoute);
+                // TODO: Remove the following logging when no longer needed.
+                if (route != btRoute) {
+                    StackTraceElement[] callStack = Thread.currentThread().getStackTrace();
+                    StringBuffer sb = new StringBuffer();
+                    // callStack[3] is the caller of this method.
+                    for (int i = 3; i < callStack.length; i++) {
+                        StackTraceElement caller = callStack[i];
+                        sb.append(caller.getClassName() + "." + caller.getMethodName()
+                                + ":" + caller.getLineNumber()).append("  ");
+                    }
+                    Log.w(TAG, "Default route is selected while a BT route is available: pkgName="
+                            + sStatic.mPackageName + ", callers=" + sb.toString());
+                }
             } catch (RemoteException e) {
                 Log.e(TAG, "Error changing Bluetooth A2DP state", e);
             }
@@ -1999,6 +2021,11 @@
         }
 
         /** @hide */
+        public boolean isBluetooth() {
+            return this == sStatic.mBluetoothA2dpRoute;
+        }
+
+        /** @hide */
         public void select() {
             selectRouteStatic(mSupportedTypes, this, true);
         }
diff --git a/packages/SystemUI/res/drawable/ic_qs_night_display_on.xml b/packages/SettingsLib/res/drawable/ic_qs_night_display_on.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_qs_night_display_on.xml
rename to packages/SettingsLib/res/drawable/ic_qs_night_display_on.xml
diff --git a/packages/SystemUI/res/drawable/ic_signal_location.xml b/packages/SettingsLib/res/drawable/ic_signal_location.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_signal_location.xml
rename to packages/SettingsLib/res/drawable/ic_signal_location.xml
diff --git a/packages/SettingsLib/res/values-gl/strings.xml b/packages/SettingsLib/res/values-gl/strings.xml
index 1a6fd39..fe91f40 100644
--- a/packages/SettingsLib/res/values-gl/strings.xml
+++ b/packages/SettingsLib/res/values-gl/strings.xml
@@ -296,7 +296,7 @@
     <string name="enable_freeform_support" msgid="1461893351278940416">"Activar ventás de forma libre"</string>
     <string name="enable_freeform_support_summary" msgid="8247310463288834487">"Activa a compatibilidade con ventás de forma libre experimentais."</string>
     <string name="local_backup_password_title" msgid="3860471654439418822">"Contrasinal para copias"</string>
-    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguridade de ordenador completas non están protexidas"</string>
+    <string name="local_backup_password_summary_none" msgid="6951095485537767956">"As copias de seguranza de ordenador completas non están protexidas"</string>
     <string name="local_backup_password_summary_change" msgid="5376206246809190364">"Toca para cambiar ou eliminar o contrasinal para as copias de seguranza completas do escritorio"</string>
     <string name="local_backup_password_toast_success" msgid="582016086228434290">"Novo contrasinal da copia de seguranza definido"</string>
     <string name="local_backup_password_toast_confirmation_mismatch" msgid="7805892532752708288">"O contrasinal novo e a confirmación non coinciden"</string>
diff --git a/packages/SettingsLib/res/values-hi/strings.xml b/packages/SettingsLib/res/values-hi/strings.xml
index dd9ad33..12564b5 100644
--- a/packages/SettingsLib/res/values-hi/strings.xml
+++ b/packages/SettingsLib/res/values-hi/strings.xml
@@ -220,7 +220,7 @@
     <string name="mobile_data_always_on_summary" msgid="8149773901431697910">"वाई-फ़ाई के सक्रिय रहने पर भी, हमेशा मोबाइल डेटा सक्रिय रखें (तेज़ी से नेटवर्क स्विच करने के लिए)."</string>
     <string name="tethering_hardware_offload_summary" msgid="7726082075333346982">"हार्डवेयर त्‍वरण को टेदर करना उपलब्ध होने पर उसका उपयोग करें"</string>
     <string name="adb_warning_title" msgid="6234463310896563253">"USB डीबग करने की अनुमति दें?"</string>
-    <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग डीबग करने का उद्देश्‍य केवल विकास है. इसका उपयोग आपके कंप्‍यूटर और आपके डिवाइस के बीच डेटा की प्रतिलिपि बनाने, बिना नोटिफिकेशन के आपके डिवाइस पर ऐप्स इंस्‍टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string>
+    <string name="adb_warning_message" msgid="7316799925425402244">"USB डीबग करने का उद्देश्‍य केवल विकास है. इसका इस्तेमाल आपके कंप्‍यूटर और आपके डिवाइस के बीच डेटा को कॉपी करने, बिना नोटिफ़िकेशन के आपके डिवाइस पर ऐप इंस्‍टॉल करने और लॉग डेटा पढ़ने के लिए करें."</string>
     <string name="adb_keys_warning_message" msgid="5659849457135841625">"आपके द्वारा पूर्व में प्राधिकृत सभी कंप्यूटर से USB डीबगिंग की पहुंच निरस्त करें?"</string>
     <string name="dev_settings_warning_title" msgid="7244607768088540165">"विकास सेटिंग की अनुमति दें?"</string>
     <string name="dev_settings_warning_message" msgid="2298337781139097964">"ये सेटिंग केवल विकास संबंधी उपयोग के प्रयोजन से हैं. वे आपके डिवाइस और उस पर स्‍थित ऐप्स  को खराब कर सकती हैं या उनके दुर्व्यवहार का कारण हो सकती हैं."</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java
index caa7929..6c79a61 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapper.java
@@ -123,4 +123,9 @@
      * @return the label as a CharSequence
      */
     CharSequence loadLabel(ApplicationInfo app);
+
+    /**
+     * Retrieve all activities that can be performed for the given intent.
+     */
+    List<ResolveInfo> queryIntentActivities(Intent intent, int flags);
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java
index 9b2cd7c..dcb40b2 100644
--- a/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java
+++ b/packages/SettingsLib/src/com/android/settingslib/applications/PackageManagerWrapperImpl.java
@@ -113,4 +113,9 @@
     public CharSequence loadLabel(ApplicationInfo app) {
         return app.loadLabel(mPm);
     }
+
+    @Override
+    public List<ResolveInfo> queryIntentActivities(Intent intent, int flags) {
+        return mPm.queryIntentActivities(intent, flags);
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
index 167ffe6..7f82a1ca 100644
--- a/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
+++ b/packages/SettingsLib/src/com/android/settingslib/suggestions/SuggestionParser.java
@@ -91,7 +91,8 @@
 
     // Shared prefs keys for storing dismissed state.
     // Index into current dismissed state.
-    private static final String DISMISS_INDEX = "_dismiss_index";
+    @VisibleForTesting
+    static final String DISMISS_INDEX = "_dismiss_index";
     private static final String SETUP_TIME = "_setup_time";
     private static final String IS_DISMISSED = "_is_dismissed";
 
@@ -355,7 +356,8 @@
         return elapsedTime > category.exclusiveExpireDaysInMillis;
     }
 
-    private boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
+    @VisibleForTesting
+    boolean isDismissed(Tile suggestion, boolean isSmartSuggestionEnabled) {
         String dismissControl = getDismissControl(suggestion, isSmartSuggestionEnabled);
         if (dismissControl == null) {
             return false;
@@ -372,7 +374,11 @@
             return false;
         }
         int index = mSharedPrefs.getInt(keyBase + DISMISS_INDEX, 0);
-        int currentDismiss = parseDismissString(dismissControl)[index];
+        int[] dismissRules = parseDismissString(dismissControl);
+        if (dismissRules.length <= index) {
+            return true;
+        }
+        int currentDismiss = dismissRules[index];
         long time = getEndTime(mSharedPrefs.getLong(keyBase + SETUP_TIME, 0), currentDismiss);
         if (System.currentTimeMillis() >= time) {
             // Dismiss timeout has passed, undismiss it.
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
index ec3b520..0400e24 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/AccessPoint.java
@@ -1065,7 +1065,7 @@
                 // are still seen, we will investigate further.
                 update(config); // Notifies the AccessPointListener of the change
             }
-            if (mRssi != info.getRssi()) {
+            if (mRssi != info.getRssi() && info.getRssi() != WifiInfo.INVALID_RSSI) {
                 mRssi = info.getRssi();
                 updated = true;
             } else if (mNetworkInfo != null && networkInfo != null
diff --git a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
index 9ccd332..5a35da9 100644
--- a/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
+++ b/packages/SettingsLib/src/com/android/settingslib/wifi/WifiTracker.java
@@ -365,7 +365,7 @@
                 mConnectivityManager.unregisterNetworkCallback(mNetworkCallback);
                 mRegistered = false;
             }
-            unregisterAndClearScoreCache();
+            unregisterScoreCache();
             pauseScanning();
             mContext.getContentResolver().unregisterContentObserver(mObserver);
 
@@ -375,11 +375,14 @@
         mStaleScanResults = true;
     }
 
-    private void unregisterAndClearScoreCache() {
+    private void unregisterScoreCache() {
         mNetworkScoreManager.unregisterNetworkScoreCache(NetworkKey.TYPE_WIFI, mScoreCache);
-        mScoreCache.clearScores();
 
-        // Synchronize on mLock to avoid concurrent modification during updateAccessPoints
+        // We do not want to clear the existing scores in the cache, as this method is called during
+        // stop tracking on activity pause. Hence, on resumption we want the ability to show the
+        // last known, potentially stale, scores. However, by clearing requested scores, the scores
+        // will be requested again upon resumption of tracking, and if any changes have occurred
+        // the listeners (UI) will be updated accordingly.
         synchronized (mLock) {
             mRequestedScores.clear();
         }
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
index c08dd6e..2f02b9b 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/AccessPointTest.java
@@ -626,6 +626,57 @@
     }
 
     @Test
+    public void testUpdateWithDifferentRssi_returnsTrue() {
+        int networkId = 123;
+        int rssi = -55;
+        WifiConfiguration config = new WifiConfiguration();
+        config.networkId = networkId;
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setNetworkId(networkId);
+        wifiInfo.setRssi(rssi);
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+        AccessPoint ap = new TestAccessPointBuilder(mContext)
+                .setNetworkInfo(networkInfo)
+                .setNetworkId(networkId)
+                .setRssi(rssi)
+                .setWifiInfo(wifiInfo)
+                .build();
+
+        NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+        wifiInfo.setRssi(rssi + 1);
+        assertThat(ap.update(config, wifiInfo, newInfo)).isTrue();
+    }
+
+    @Test
+    public void testUpdateWithInvalidRssi_returnsFalse() {
+        int networkId = 123;
+        int rssi = -55;
+        WifiConfiguration config = new WifiConfiguration();
+        config.networkId = networkId;
+        WifiInfo wifiInfo = new WifiInfo();
+        wifiInfo.setNetworkId(networkId);
+        wifiInfo.setRssi(rssi);
+
+        NetworkInfo networkInfo =
+                new NetworkInfo(ConnectivityManager.TYPE_WIFI, 0 /* subtype */, "WIFI", "");
+        networkInfo.setDetailedState(NetworkInfo.DetailedState.CONNECTING, "", "");
+
+        AccessPoint ap = new TestAccessPointBuilder(mContext)
+                .setNetworkInfo(networkInfo)
+                .setNetworkId(networkId)
+                .setRssi(rssi)
+                .setWifiInfo(wifiInfo)
+                .build();
+
+        NetworkInfo newInfo = new NetworkInfo(networkInfo); // same values
+        wifiInfo.setRssi(WifiInfo.INVALID_RSSI);
+        assertThat(ap.update(config, wifiInfo, newInfo)).isFalse();
+    }
+    @Test
     public void testUpdateWithConfigChangeOnly_returnsFalseButInvokesListener() {
         int networkId = 123;
         int rssi = -55;
diff --git a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
index b6d0c45..c87d01a 100644
--- a/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
+++ b/packages/SettingsLib/tests/integ/src/com/android/settingslib/wifi/WifiTrackerTest.java
@@ -473,6 +473,17 @@
     }
 
     @Test
+    public void stopTracking_shouldNotClearExistingScores()
+            throws InterruptedException {
+        // Start the tracker and inject the initial scan results and then stop tracking
+        WifiTracker tracker =  createTrackerWithImmediateBroadcastsAndInjectInitialScanResults();
+        updateScoresAndWaitForAccessPointsChangedCallback(tracker);
+        tracker.stopTracking();
+
+        assertThat(mScoreCacheCaptor.getValue().getScoredNetwork(NETWORK_KEY_1)).isNotNull();
+    }
+
+    @Test
     public void scoreCacheUpdateScoresShouldTriggerOnAccessPointsChanged()
             throws InterruptedException {
         WifiTracker tracker = createMockedWifiTracker();
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
index 60933cf..8391136 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/suggestions/SuggestionParserTest.java
@@ -16,6 +16,8 @@
 
 package com.android.settingslib.suggestions;
 
+import static com.google.common.truth.Truth.assertThat;
+
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
@@ -42,8 +44,6 @@
 import java.util.Arrays;
 import java.util.List;
 
-import static com.google.common.truth.Truth.assertThat;
-
 @RunWith(SettingLibRobolectricTestRunner.class)
 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION)
 public class SuggestionParserTest {
@@ -190,6 +190,24 @@
         assertThat(sl.getSuggestionForCategory("category2")).hasSize(1);
     }
 
+    @Test
+    public void isSuggestionDismissed_mismatchRule_shouldDismiss() {
+        final Tile suggestion = new Tile();
+        suggestion.metaData = new Bundle();
+        suggestion.metaData.putString(SuggestionParser.META_DATA_DISMISS_CONTROL, "1,2,3");
+        suggestion.intent = new Intent().setComponent(new ComponentName("pkg", "cls"));
+
+        // Dismiss suggestion when smart suggestion is not enabled.
+        mSuggestionParser.dismissSuggestion(suggestion, false /* isSmartSuggestionEnabled */);
+        final String suggestionKey = suggestion.intent.getComponent().flattenToShortString();
+        // And point to last rule in dismiss control
+        mPrefs.edit().putInt(suggestionKey + SuggestionParser.DISMISS_INDEX, 2).apply();
+
+        // Turn on smart suggestion, and check if suggestion is enabled.
+        assertThat(mSuggestionParser.isDismissed(suggestion, true /* isSmartSuggestionEnabled */))
+                .isTrue();
+    }
+
     private void readAndDismissSuggestion(boolean isSmartSuggestionEnabled) {
         mSuggestionsBeforeDismiss = new ArrayList<>();
         mSuggestionsAfterDismiss = new ArrayList<>();
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
index b328933..819ee3e 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProtoDumpUtil.java
@@ -915,9 +915,6 @@
                 Settings.Global.DEVICE_DEMO_MODE,
                 GlobalSettingsProto.DEVICE_DEMO_MODE);
         dumpSetting(s, p,
-                Settings.Global.RETAIL_DEMO_MODE_CONSTANTS,
-                GlobalSettingsProto.RETAIL_DEMO_MODE_CONSTANTS);
-        dumpSetting(s, p,
                 Settings.Global.DATABASE_DOWNGRADE_REASON,
                 GlobalSettingsProto.DATABASE_DOWNGRADE_REASON);
         dumpSetting(s, p,
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
index f5d7dd8..ad2ec0b 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsProvider.java
@@ -2597,7 +2597,7 @@
             synchronized (mLock) {
                 final int key = makeKey(SETTINGS_TYPE_GLOBAL, UserHandle.USER_SYSTEM);
                 File globalFile = getSettingsFile(key);
-                if (globalFile.exists()) {
+                if (SettingsState.stateFileExists(globalFile)) {
                     return;
                 }
 
@@ -2634,7 +2634,7 @@
             // Every user has secure settings and if no file we need to migrate.
             final int secureKey = makeKey(SETTINGS_TYPE_SECURE, userId);
             File secureFile = getSettingsFile(secureKey);
-            if (secureFile.exists()) {
+            if (SettingsState.stateFileExists(secureFile)) {
                 return;
             }
 
diff --git a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
index 5f4b239..d3ac11a 100644
--- a/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
+++ b/packages/SettingsProvider/src/com/android/providers/settings/SettingsState.java
@@ -689,17 +689,11 @@
 
     private void readStateSyncLocked() {
         FileInputStream in;
-        if (!mStatePersistFile.exists()) {
-            Slog.i(LOG_TAG, "No settings state " + mStatePersistFile);
-            addHistoricalOperationLocked(HISTORICAL_OPERATION_INITIALIZE, null);
-            return;
-        }
         try {
             in = new AtomicFile(mStatePersistFile).openRead();
         } catch (FileNotFoundException fnfe) {
-            String message = "No settings state " + mStatePersistFile;
-            Slog.wtf(LOG_TAG, message);
-            Slog.i(LOG_TAG, message);
+            Slog.i(LOG_TAG, "No settings state " + mStatePersistFile);
+            addHistoricalOperationLocked(HISTORICAL_OPERATION_INITIALIZE, null);
             return;
         }
         try {
@@ -715,6 +709,16 @@
         }
     }
 
+    /**
+     * Uses AtomicFile to check if the file or its backup exists.
+     * @param file The file to check for existence
+     * @return whether the original or backup exist
+     */
+    public static boolean stateFileExists(File file) {
+        AtomicFile stateFile = new AtomicFile(file);
+        return stateFile.exists();
+    }
+
     private void parseStateLocked(XmlPullParser parser)
             throws IOException, XmlPullParserException {
         final int outerDepth = parser.getDepth();
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
index 26a179a..b821e7e 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_password_view.xml
@@ -54,7 +54,7 @@
              android:textStyle="normal"
              android:inputType="textPassword"
              android:textSize="16sp"
-             android:textColor="?attr/bgProtectTextColor"
+             android:textColor="?attr/wallpaperTextColor"
              android:textAppearance="?android:attr/textAppearanceMedium"
              android:imeOptions="flagForceAscii|actionDone"
              android:maxLength="500"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
index 501d0a5..3283e04 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_pin_view.xml
@@ -54,7 +54,7 @@
                     android:layout_centerHorizontal="true"
                     android:layout_marginRight="72dp"
                     androidprv:scaledTextSize="@integer/scaled_password_text_size"
-                    android:textColor="?attr/bgProtectTextColor"
+                    android:textColor="?attr/wallpaperTextColor"
                     android:contentDescription="@string/keyguard_accessibility_pin_area"
                     />
             <ImageButton
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
index 87b1ee7..6dea493 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_presentation.xml
@@ -41,7 +41,7 @@
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
                 android:layout_gravity="center_horizontal|top"
-                android:textColor="?attr/bgProtectTextColor"
+                android:textColor="?attr/wallpaperTextColor"
                 android:singleLine="true"
                 style="@style/widget_big_thin"
                 android:format12Hour="@string/keyguard_widget_12_hours_format"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
index c4732e4..cf87f90 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_pin_view.xml
@@ -67,7 +67,7 @@
                     android:layout_centerHorizontal="true"
                     android:layout_marginRight="72dp"
                     androidprv:scaledTextSize="@integer/scaled_password_text_size"
-                    android:textColor="?attr/bgProtectTextColor"
+                    android:textColor="?attr/wallpaperTextColor"
                     android:contentDescription="@string/keyguard_accessibility_sim_pin_area"
                     />
             <ImageButton
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
index 1c7defd..3cae493 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_sim_puk_view.xml
@@ -68,7 +68,7 @@
                     android:layout_centerHorizontal="true"
                     android:layout_marginRight="72dp"
                     androidprv:scaledTextSize="@integer/scaled_password_text_size"
-                    android:textColor="?attr/bgProtectTextColor"
+                    android:textColor="?attr/wallpaperTextColor"
                     android:contentDescription="@string/keyguard_accessibility_sim_puk_area"
                     />
             <ImageButton
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
index 7d125046..56fb73f 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_area.xml
@@ -29,9 +29,9 @@
         android:id="@+id/date_view"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:textColor="?attr/bgProtectTextColor"
+        android:textColor="?attr/wallpaperTextColor"
         style="@style/widget_label"
-        android:letterSpacing="0.15"
+        android:letterSpacing="0.05"
         android:gravity="center"
         />
     <TextView android:id="@+id/alarm_status"
@@ -39,10 +39,10 @@
         android:layout_height="wrap_content"
         android:drawablePadding="6dp"
         android:drawableStart="@drawable/ic_access_alarms_big"
-        android:drawableTint="?attr/bgProtectSecondaryTextColor"
+        android:drawableTint="?attr/wallpaperTextColorSecondary"
         android:drawableTintMode="src_in"
-        android:textColor="?attr/bgProtectSecondaryTextColor"
-        android:letterSpacing="0.15"
+        android:textColor="?attr/wallpaperTextColorSecondary"
+        android:letterSpacing="0.05"
         style="@style/widget_label"
         android:layout_marginStart="6dp"
         android:gravity="center"
diff --git a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
index ee14f3d..138733e 100644
--- a/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
+++ b/packages/SystemUI/res-keyguard/layout/keyguard_status_view.xml
@@ -44,7 +44,7 @@
                 android:layout_gravity="center_horizontal"
                 android:layout_centerHorizontal="true"
                 android:layout_alignParentTop="true"
-                android:textColor="?attr/bgProtectTextColor"
+                android:textColor="?attr/wallpaperTextColor"
                 android:singleLine="true"
                 style="@style/widget_big_thin"
                 android:format12Hour="@string/keyguard_widget_12_hours_format"
@@ -76,8 +76,9 @@
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
             android:layout_marginTop="@dimen/date_owner_info_margin"
+            android:layout_gravity="center_horizontal"
             android:layout_centerHorizontal="true"
-            android:textColor="?attr/bgProtectSecondaryTextColor"
+            android:textColor="?attr/wallpaperTextColorSecondary"
             android:textSize="@dimen/widget_label_font_size"
             android:letterSpacing="0.05"
             android:ellipsize="marquee"
diff --git a/packages/SystemUI/res-keyguard/values/styles.xml b/packages/SystemUI/res-keyguard/values/styles.xml
index 9eceeb4..ea867ee 100644
--- a/packages/SystemUI/res-keyguard/values/styles.xml
+++ b/packages/SystemUI/res-keyguard/values/styles.xml
@@ -20,11 +20,11 @@
 <resources>
     <!-- Keyguard PIN pad styles -->
     <style name="Keyguard.TextView" parent="@android:style/Widget.DeviceDefault.TextView">
-        <item name="android:textColor">?attr/bgProtectSecondaryTextColor</item>
+        <item name="android:textColor">?attr/wallpaperTextColorSecondary</item>
         <item name="android:textSize">@dimen/kg_status_line_font_size</item>
     </style>
     <style name="Keyguard.TextView.EmergencyButton" parent="@android:style/DeviceDefault.ButtonBar">
-        <item name="android:textColor">?attr/bgProtectSecondaryTextColor</item>
+        <item name="android:textColor">?attr/wallpaperTextColorSecondary</item>
         <item name="android:textSize">@dimen/kg_status_line_font_size</item>
         <item name="android:background">@null</item>
     </style>
@@ -34,7 +34,7 @@
         <item name="android:background">@null</item>
         <item name="android:textSize">32sp</item>
         <item name="android:fontFamily">@*android:string/config_headlineFontFamilyLight</item>
-        <item name="android:textColor">?attr/bgProtectTextColor</item>
+        <item name="android:textColor">?attr/wallpaperTextColor</item>
         <item name="android:paddingBottom">-16dp</item>
     </style>
     <style name="Keyguard.ImageButton.NumPadEnter" parent="@android:style/Widget.ImageButton">
@@ -43,7 +43,7 @@
     <style name="Widget.TextView.NumPadKey.Klondike" parent="Widget.TextView.NumPadKey">
         <item name="android:textSize">12sp</item>
         <item name="android:fontFamily">sans-serif</item>
-        <item name="android:textColor">?attr/bgProtectSecondaryTextColor</item>
+        <item name="android:textColor">?attr/wallpaperTextColorSecondary</item>
         <item name="android:paddingBottom">0dp</item>
     </style>
 
@@ -61,9 +61,9 @@
     </style>
 
     <style name="PasswordTheme" parent="systemui_theme">
-        <item name="android:textColor">?attr/bgProtectTextColor</item>
-        <item name="android:colorControlNormal">?attr/bgProtectTextColor</item>
-        <item name="android:colorControlActivated">?attr/bgProtectTextColor</item>
+        <item name="android:textColor">?attr/wallpaperTextColor</item>
+        <item name="android:colorControlNormal">?attr/wallpaperTextColor</item>
+        <item name="android:colorControlActivated">?attr/wallpaperTextColor</item>
     </style>
 
     <style name="keyguard_presentation_theme" parent="@android:style/Theme.Material.NoActionBar.Fullscreen">
diff --git a/packages/SystemUI/res/color/background_protect_secondary.xml b/packages/SystemUI/res/color/background_protect_secondary.xml
index 26dc151..97744db 100644
--- a/packages/SystemUI/res/color/background_protect_secondary.xml
+++ b/packages/SystemUI/res/color/background_protect_secondary.xml
@@ -16,5 +16,5 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?attr/bgProtectSecondaryTextColor" />
+    <item android:color="?attr/wallpaperTextColorSecondary" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/background_protected.xml b/packages/SystemUI/res/color/background_protected.xml
index ab8ed87..ff2009d 100644
--- a/packages/SystemUI/res/color/background_protected.xml
+++ b/packages/SystemUI/res/color/background_protected.xml
@@ -16,5 +16,5 @@
   -->
 
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:color="?attr/bgProtectTextColor" />
+    <item android:color="?attr/wallpaperTextColor" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/pin_delete_color.xml b/packages/SystemUI/res/color/pin_delete_color.xml
index bb8b8e3..7d4f132 100644
--- a/packages/SystemUI/res/color/pin_delete_color.xml
+++ b/packages/SystemUI/res/color/pin_delete_color.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.61" android:color="?attr/bgProtectTextColor" />
+    <item android:alpha="0.61" android:color="?attr/wallpaperTextColor" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/color/pin_divider_color.xml b/packages/SystemUI/res/color/pin_divider_color.xml
index ca5f431..aff2317 100644
--- a/packages/SystemUI/res/color/pin_divider_color.xml
+++ b/packages/SystemUI/res/color/pin_divider_color.xml
@@ -15,5 +15,5 @@
   ~ limitations under the License
   -->
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
-    <item android:alpha="0.45" android:color="?attr/bgProtectSecondaryTextColor" />
+    <item android:alpha="0.45" android:color="?attr/wallpaperTextColorSecondary" />
 </selector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/ic_dnd.xml b/packages/SystemUI/res/drawable/ic_dnd.xml
index e658e68..9a1d502 100644
--- a/packages/SystemUI/res/drawable/ic_dnd.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -15,13 +15,13 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24dp"
     android:tint="?android:attr/colorControlNormal">
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M24.0,4.0C12.95,4.0 4.0,12.95 4.0,24.0s8.95,20.0 20.0,20.0 20.0,-8.95 20.0,-20.0S35.05,4.0 24.0,4.0zm10.0,22.0L14.0,26.0l0.0,-4.0l20.0,0.0l0.0,4.0z" />
+        android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM16,13L8,13c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h8c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
index 0515b35..e7b9fa7 100644
--- a/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
+++ b/packages/SystemUI/res/drawable/ic_dnd_total_silence.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -22,9 +22,6 @@
 
     <path
         android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,2.0C6.5,2.0 2.0,6.5 2.0,12.0s4.5,10.0 10.0,10.0s10.0,-4.5 10.0,-10.0S17.5,2.0 12.0,2.0zM12.0,20.5c-4.7,0.0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12.0,3.5s8.5,3.8 8.5,8.5S16.7,20.5 12.0,20.5z"/>
-    <path
-        android:fillColor="#FFFFFFFF"
-        android:pathData="M12.0,6.0c-3.3,0.0 -6.0,2.7 -6.0,6.0c0.0,3.3 2.7,6.0 6.0,6.0s6.0,-2.7 6.0,-6.0C18.0,8.7 15.4,6.0 12.0,6.0zM15.0,13.0L9.0,13.0l0.0,-2.0l6.0,0.0L15.0,13.0z"/>
+        android:pathData="M12,2C6.5,2 2,6.5 2,12s4.5,10 10,10 10,-4.5 10,-10S17.5,2 12,2zM12,20.5c-4.7,0 -8.5,-3.8 -8.5,-8.5S7.3,3.5 12,3.5s8.5,3.8 8.5,8.5 -3.8,8.5 -8.5,8.5zM12,6c-3.3,0 -6,2.7 -6,6s2.7,6 6,6 6,-2.7 6,-6 -2.6,-6 -6,-6zM14,13h-4c-0.55,0 -1,-0.45 -1,-1s0.45,-1 1,-1h4c0.55,0 1,0.45 1,1s-0.45,1 -1,1z"/>
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm.xml b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
index e64f445..996e488 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -15,13 +15,13 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24.0dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24.0dp"
     android:tint="?android:attr/colorControlNormal">
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M44.0,11.44l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-28.24,-4.66l-2.57,-3.06 -9.19,7.71 2.57,3.06 9.19,-7.71zm9.24,9.22l-3.0,0.0l0.0,12.0l9.49,5.71 1.51,-2.47 -8.0,-4.74l0.0,-10.5zm-1.01,-8.0c-9.95,0.0 -17.99,8.06 -17.99,18.0s8.04,18.0 17.99,18.0 18.01,-8.06 18.01,-18.0 -8.06,-18.0 -18.01,-18.0zm0.01,32.0c-7.73,0.0 -14.0,-6.27 -14.0,-14.0s6.27,-14.0 14.0,-14.0 14.0,6.27 14.0,14.0 -6.26,14.0 -14.0,14.0z" />
+        android:pathData="M2.7,6.5c-0.4,-0.4 -0.3,-1 0.1,-1.4l3,-2.6c0.4,-0.4 1,-0.3 1.4,0.1C7.6,3 7.5,3.7 7.1,4l-3,2.6C3.6,7 3,6.9 2.7,6.5zM21.3,5.1l-3.1,-2.6c-0.4,-0.4 -0.99,-0.31 -1.4,0.1c-0.4,0.4 -0.3,1 0.1,1.4L20,6.6c0.41,0.37 1,0.3 1.4,-0.1C21.73,6.12 21.7,5.4 21.3,5.1zM21,13c0,5 -4,9 -9,9s-9,-4 -9,-9s4,-9 9,-9S21,8 21,13zM19.1,13c0,-3.9 -3.2,-7.1 -7.1,-7.1S4.9,9.1 4.9,13s3.2,7.1 7.1,7.1S19.1,16.9 19.1,13zM11.75,8C11.34,8 11,8.34 11,8.75V14l4.14,2.48c0.34,0.21 0.77,0.1 0.98,-0.24s0.09,-0.79 -0.25,-0.99l-3.37,-2v-4.5C12.5,8.34 12.16,8 11.75,8z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
index 37d7690..02fb1e7 100644
--- a/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_alarm_mute.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -15,13 +15,13 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24.0dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24.0dp"
     android:tint="?android:attr/colorControlNormal" >
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M24.0,12.0c7.73,0.0 14.0,6.27 14.0,14.0 0.0,1.69 -0.31,3.3 -0.86,4.8l3.04,3.04c1.16,-2.37 1.82,-5.03 1.82,-7.84 0.0,-9.94 -8.06,-18.0 -18.01,-18.0 -2.81,0.0 -5.46,0.66 -7.84,1.81l3.05,3.05c1.5,-0.55 3.11,-0.86 4.8,-0.86zm20.0,-0.56l-9.19,-7.71 -2.57,3.06 9.19,7.71 2.57,-3.06zm-38.16,-6.85l-2.55,2.54 2.66,2.66 -2.22,1.86 2.84,2.84 2.22,-1.86 1.6,1.6c-2.73,3.16 -4.39,7.27 -4.39,11.77 0.0,9.94 8.04,18.0 17.99,18.0 4.51,0.0 8.62,-1.67 11.77,-4.4l4.4,4.4 2.54,-2.55 -34.91,-34.91 -1.95,-1.95zm27.1,32.19c-2.43,2.01 -5.54,3.22 -8.94,3.22 -7.73,0.0 -14.0,-6.27 -14.0,-14.0 0.0,-3.4 1.21,-6.51 3.22,-8.94l19.72,19.72zm-16.91,-30.23l-2.84,-2.84 -1.7,1.43 2.84,2.84 1.7,-1.43z" />
+        android:pathData="M21.35,6.49c-0.35,0.42 -0.98,0.47 -1.4,0.12l-3.07,-2.57a1,1 0,1 1,1.29 -1.53l3.07,2.57c0.42,0.35 0.47,0.98 0.11,1.41zM20.72,20.09a0.9,0.9 0,0 1,0 1.27,0.9 0.9,0 0,1 -1.27,0l-1.57,-1.57A8.875,8.875 0,0 1,12 22c-4.98,0 -9,-4.03 -9,-9 0,-2.25 0.83,-4.31 2.2,-5.89l-0.8,-0.8 -0.41,0.35a1,1 0,0 1,-1.35 -0.06,1 1,0 0,1 0.07,-1.47l0.27,-0.23 -0.7,-0.7a0.9,0.9 0,0 1,0 -1.27c0.35,-0.35 0.93,-0.35 1.28,0l17.16,17.16zM16.54,18.45L6.55,8.46A7.041,7.041 0,0 0,4.9 13c0,3.91 3.19,7.1 7.1,7.1 1.73,0 3.31,-0.62 4.54,-1.65zM7.17,3.98A0.997,0.997 0,1 0,5.9 2.44l-0.16,0.13 1.42,1.42 0.01,-0.01zM12,4c-1.41,0 -2.73,0.33 -3.92,0.91l1.45,1.45c0.77,-0.29 1.6,-0.46 2.47,-0.46 3.91,0 7.1,3.18 7.1,7.1 0,0.87 -0.17,1.7 -0.45,2.47l1.44,1.44c0.58,-1.18 0.91,-2.5 0.91,-3.91a9,9 0,0 0,-9 -9z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
index 5c3c650..b0b9404 100644
--- a/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_bt_sco.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -15,13 +15,16 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24.0dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="24.0"
+    android:viewportWidth="24.0"
     android:width="24.0dp"
     android:tint="?android:attr/colorControlNormal" >
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M29.41,19.0L34.0,14.41L34.0,22.0l1.0,0.0l5.71,-5.71 -4.3,-4.29 4.29,-4.29L35.0,2.0l-1.0,0.0l0.0,7.59L29.41,5.0 28.0,6.41 33.59,12.0 28.0,17.59 29.41,19.0zM36.0,5.83l1.88,1.88L36.0,9.59L36.0,5.83zm0.0,8.58l1.88,1.88L36.0,18.17l0.0,-3.76zM40.0,31.0c-2.49,0.0 -4.89,-0.4 -7.14,-1.14 -0.69,-0.22 -1.48,-0.06 -2.0,0.49l-4.4,4.41c-5.67,-2.88 -10.29,-7.51 -13.18,-13.17l4.4,-4.41c0.55,-0.5 0.71,-1.3 0.49,-2.03C17.4,12.9 17.0,10.49 17.0,8.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0L8.0,6.0c-1.11,0.0 -2.0,0.89 -2.0,2.0 0.0,18.78 15.22,34.0 34.0,34.0 1.11,0.0 2.0,-0.89 2.0,-2.0l0.0,-7.0c0.0,-1.11 -0.89,-2.0 -2.0,-2.0z" />
+        android:pathData="M20,15.5c-1.25,0 -2.45,-0.2 -3.57,-0.57c-0.35,-0.11 -0.74,-0.03 -1.02,0.24l-2.2,2.2c-2.83,-1.44 -5.15,-3.75 -6.59,-6.59l2.2,-2.21c0.28,-0.26 0.36,-0.65 0.25,-1C8.7,6.45 8.5,5.25 8.5,4c0,-0.55 -0.45,-1 -1,-1H4C3.45,3 3,3.45 3,4c0,9.39 7.61,17 17,17c0.55,0 1,-0.45 1,-1v-3.5C21,15.95 20.55,15.5 20,15.5z"/>
+    <path
+        android:fillColor="#FFFFFF"
+        android:pathData="M17.97,6l1.88,-1.87c0.21,-0.21 0.21,-0.54 0,-0.74L17.6,1.16l-0.01,-0.01c-0.21,-0.2 -0.53,-0.2 -0.73,0.01c-0.09,0.1 -0.15,0.23 -0.15,0.36v3.23l-2.03,-2.03c-0.21,-0.21 -0.53,-0.21 -0.74,0c-0.21,0.21 -0.21,0.53 0,0.74L16.49,6l-2.55,2.55c-0.21,0.21 -0.21,0.53 0,0.74c0.21,0.21 0.53,0.21 0.74,0l2.03,-2.03v3.23c0,0.29 0.24,0.52 0.52,0.52c0.13,0 0.26,-0.05 0.35,-0.15l2.25,-2.25c0.21,-0.21 0.21,-0.54 0,-0.74L17.97,6zM17.75,2.78l0.99,0.99l-0.99,0.99V2.78zM17.75,9.23V7.27l0.99,0.99L17.75,9.23z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media.xml b/packages/SystemUI/res/drawable/ic_volume_media.xml
index d689207..53c0740 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -22,6 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M12.0,3.0l0.0,9.28c-0.47,-0.17 -0.97,-0.28 -1.5,-0.28C8.01,12.0 6.0,14.01 6.0,16.5S8.01,21.0 10.5,21.0c2.31,0.0 4.2,-1.75 4.45,-4.0L15.0,17.0L15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0z" />
+        android:pathData="M18,3h-5c-0.55,0 -1,0.45 -1,1v8.3a3.88,3.88 0,0 0,-2.9 -0.04c-1.79,0.67 -3.11,2.35 -3.1,4.26A4.483,4.483 0,0 0,10.5 21c2.5,0 4.5,-2.3 4.5,-4.5V6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
index 9b7b2da..60d0184 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -22,9 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M17.0,3.0l-7.0,0.0l0.0,9.3C9.5,12.1 9.0,12.0 8.5,12.0C6.0,12.0 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0s4.5,-2.3 4.5,-4.5C13.0,14.7 13.0,6.0 13.0,6.0l4.0,0.0L17.0,3.0z"/>
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
+        android:pathData="M16,3h-5c-0.55,0 -1,0.45 -1,1v8.3c-0.93,-0.39 -1.96,-0.4 -2.9,-0.04c-1.79,0.67 -3.11,2.35 -3.1,4.26C4,19 6.01,21 8.49,21c0,0 0.01,0 0.01,0c2.5,0 4.5,-2.3 4.5,-4.5V6h3c0.55,0 1,-0.45 1,-1V4C17,3.45 16.55,3 16,3zM20.97,12l1.88,-1.87c0.21,-0.21 0.21,-0.54 0,-0.74L20.6,7.16l-0.01,-0.01c-0.21,-0.2 -0.53,-0.2 -0.73,0.01c-0.09,0.1 -0.15,0.23 -0.15,0.36v3.23l-2.03,-2.03c-0.21,-0.21 -0.53,-0.21 -0.74,0c-0.21,0.21 -0.21,0.53 0,0.74L19.49,12l-2.55,2.55c-0.21,0.21 -0.21,0.53 0,0.74c0.21,0.21 0.53,0.21 0.74,0l2.03,-2.03v3.23c0,0.29 0.24,0.52 0.52,0.52c0.13,0 0.26,-0.05 0.35,-0.15l0.02,-0.02l2.23,-2.23c0.21,-0.21 0.21,-0.54 0,-0.74L20.97,12zM20.75,10.75V8.78l0.99,0.99L20.75,10.75zM20.75,15.23v-1.96l0.99,0.99C21.73,14.25 20.75,15.23 20.75,15.23z"/>
 
 </vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
index 17ac01d..49fcfc4 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_bt_mute.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -22,12 +22,12 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M13.0,6.0l4.0,0.0L17.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C13.0,8.8 13.0,6.0 13.0,6.0z"/>
+        android:pathData="M13,6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1h-5c-0.55,0 -1,0.45 -1,1v4.6l3,3V6z"/>
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M2.1,5.7L8.4,12.0C6.0,12.1 4.0,14.0 4.0,16.5S6.0,21.0 8.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3l0.0,-0.1l3.9,3.9l1.3,-1.3L3.4,4.5L2.1,5.7z"/>
+        android:pathData="M4,5.1C3.67,4.76 3.12,4.75 2.78,5.08C2.41,5.42 2.4,6 2.75,6.35L8.4,12C6,12.1 4,14 4,16.5c0,2.51 2.33,4.67 4.84,4.48C11.35,20.81 13,18.62 13,16.7v-0.1l3.27,3.27c0.35,0.35 0.91,0.35 1.25,0l0.05,-0.05c0.35,-0.35 0.35,-0.91 0,-1.25L4,5.1z"/>
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M23.4,9.9L20.5,7.0L20.0,7.0l0.0,3.8l-2.3,-2.3L17.0,9.2l2.8,2.8L17.0,14.8l0.7,0.7l2.3,-2.3L20.0,17.0l0.5,0.0l2.8,-2.8L21.2,12.0L23.4,9.9zM21.0,8.9l0.9,0.9l-0.9,1.0L21.0,8.9zM21.9,14.2L21.0,15.1l0.0,-1.9L21.9,14.2z"/>
+        android:pathData="M20.97,12l1.88,-1.87c0.21,-0.21 0.21,-0.54 0,-0.74L20.6,7.16l-0.01,-0.01c-0.21,-0.2 -0.53,-0.2 -0.73,0.01c-0.09,0.1 -0.15,0.23 -0.15,0.36v3.23l-2.03,-2.03c-0.21,-0.21 -0.53,-0.21 -0.74,0c-0.21,0.21 -0.21,0.53 0,0.74L19.49,12l-2.55,2.55c-0.21,0.21 -0.21,0.53 0,0.74c0.21,0.21 0.53,0.21 0.74,0l2.03,-2.03v3.23c0,0.29 0.24,0.52 0.52,0.52c0.13,0 0.26,-0.05 0.35,-0.15l2.25,-2.25c0.21,-0.21 0.21,-0.54 0,-0.74L20.97,12zM20.75,8.78l0.99,0.99l-0.99,0.98V8.78zM20.75,15.23v-1.96l0.99,0.99C21.73,14.25 20.75,15.23 20.75,15.23z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
index 267d09d..ebb86e8 100644
--- a/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_media_mute.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -22,9 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M15.0,6.0l4.0,0.0L19.0,3.0l-7.0,0.0l0.0,5.6l3.0,3.0C15.0,8.8 15.0,6.0 15.0,6.0z" />
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M4.8,3.9L3.5,5.1l6.9,6.9C8.0,12.1 6.0,14.0 6.0,16.5C6.0,19.0 8.0,21.0 10.5,21.0c2.7,0.0 4.5,-2.3 4.5,-4.3c0.0,0.0 0.0,-0.1 0.0,-0.1l4.0,4.0l1.3,-1.3L4.8,3.9z" />
+        android:pathData="M15,6h3c0.55,0 1,-0.45 1,-1V4c0,-0.55 -0.45,-1 -1,-1h-5c-0.55,0 -1,0.45 -1,1v4.6l3,3V6zM4.18,4.48c-0.37,0.34 -0.38,0.92 -0.03,1.27L10.4,12C8,12.1 6,14 6,16.5c0,2.51 2.33,4.67 4.84,4.48 2.51,-0.17 4.16,-2.36 4.16,-4.28v-0.1l3.37,3.37c0.35,0.35 0.91,0.35 1.25,0l0.05,-0.05c0.35,-0.35 0.35,-0.91 0,-1.25L5.4,4.5a0.866,0.866 0,0 0,-1.22 -0.02z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer.xml b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
index 18af711..f258856 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -15,13 +15,17 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24dp"
-    android:viewportHeight="24.0"
-    android:viewportWidth="24.0"
+    android:viewportHeight="23.4"
+    android:viewportWidth="23.4"
     android:width="24dp"
     android:tint="?android:attr/colorControlNormal" >
 
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M11.5,22.0c1.1,0.0 2.0,-0.9 2.0,-2.0l-4.0,0.0C9.5,21.1 10.4,22.0 11.5,22.0zM18.0,16.0l0.0,-5.5c0.0,-3.1 -2.1,-5.6 -5.0,-6.3L13.0,3.5C13.0,2.7 12.3,2.0 11.5,2.0C10.7,2.0 10.0,2.7 10.0,3.5l0.0,0.7c-2.9,0.7 -5.0,3.2 -5.0,6.3L5.0,16.0l-2.0,2.0l0.0,1.0l17.0,0.0l0.0,-1.0L18.0,16.0z" />
+    <group
+        android:translateX="-0.78"
+        android:translateY="-0.5" >
+        <path
+            android:fillColor="#FFFFFF"
+            android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22zM18,16v-5c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C7.63,5.36 6,7.92 6,11v5l-2.15,2.15c-0.19,0.2 -0.19,0.51 0.01,0.71C3.95,18.95 4.07,19 4.2,19h15.6c0.45,0 0.67,-0.54 0.35,-0.85L18,16z"/>
+    </group>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
index bc926c3..106d899 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_mute.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -15,13 +15,23 @@
 -->
 <vector xmlns:android="http://schemas.android.com/apk/res/android"
     android:height="24dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
+    android:viewportHeight="23.4"
+    android:viewportWidth="23.3"
     android:width="24dp"
     android:tint="?android:attr/colorControlNormal" >
 
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M23.000000,44.000000c2.200000,0.000000 4.000000,-1.800000 4.000000,-4.000000l-8.000000,0.000000C19.000000,42.200001 20.799999,44.000000 23.000000,44.000000zM36.000000,21.000000c0.000000,-6.100000 -4.300000,-11.300000 -10.000000,-12.600000L26.000000,7.000000c0.000000,-1.700000 -1.300000,-3.000000 -3.000000,-3.000000c-1.700000,0.000000 -3.000000,1.300000 -3.000000,3.000000l0.000000,1.400000c-1.000000,0.200000 -2.000000,0.600000 -2.900000,1.100000L36.000000,28.400000L36.000000,21.000000zM35.500000,38.000000l4.000000,4.000000l2.500000,-2.500000L8.500000,6.000000L6.000000,8.500000l5.800000,5.800000C10.700000,16.299999 10.000000,18.600000 10.000000,21.000000l0.000000,11.000000l-4.000000,4.000000l0.000000,2.000000L35.500000,38.000000z" />
+    <group
+        android:translateX="-0.85"
+        android:translateY="-0.5" >
+        <path
+            android:fillColor="#FF0"
+            android:pathData="M20.73,19.46l-0.6,-0.6c0,0 0,0 0,0L5.54,4.26c-0.35,-0.35 -0.92,-0.35 -1.27,0c-0.35,0.35 -0.35,0.92 0,1.27l2.4,2.4C6.25,8.85 6,9.88 6,11v5l-2.15,2.15c-0.19,0.2 -0.19,0.51 0.01,0.71C3.95,18.95 4.07,19 4.2,19h13.53l1.73,1.73c0.35,0.35 0.92,0.35 1.27,0C21.09,20.38 21.09,19.81 20.73,19.46z"/>
+        <path
+            android:fillColor="#FF0"
+            android:pathData="M18,11c0,-3.07 -1.64,-5.64 -4.5,-6.32V4c0,-0.83 -0.67,-1.5 -1.5,-1.5S10.5,3.17 10.5,4v0.68C9.87,4.83 9.31,5.08 8.8,5.4l9.2,9.2V11z"/>
+        <path
+            android:fillColor="#FF0"
+            android:pathData="M12,22c1.1,0 2,-0.9 2,-2h-4C10,21.1 10.9,22 12,22z"/>
+    </group>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
index ffbffad..9db8511 100644
--- a/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
+++ b/packages/SystemUI/res/drawable/ic_volume_ringer_vibrate.xml
@@ -1,5 +1,5 @@
 <!--
-     Copyright (C) 2015 The Android Open Source Project
+     Copyright (C) 2017 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.
@@ -22,6 +22,6 @@
 
     <path
         android:fillColor="#FFFFFF"
-        android:pathData="M0.0,15.0l2.0,0.0L2.0,9.0L0.0,9.0L0.0,15.0zM3.0,17.0l2.0,0.0L5.0,7.0L3.0,7.0L3.0,17.0zM22.0,9.0l0.0,6.0l2.0,0.0L24.0,9.0L22.0,9.0zM19.0,17.0l2.0,0.0L21.0,7.0l-2.0,0.0L19.0,17.0zM16.5,3.0l-9.0,0.0C6.7,3.0 6.0,3.7 6.0,4.5l0.0,15.0C6.0,20.3 6.7,21.0 7.5,21.0l9.0,0.0c0.8,0.0 1.5,-0.7 1.5,-1.5l0.0,-15.0C18.0,3.7 17.3,3.0 16.5,3.0zM16.0,19.0L8.0,19.0L8.0,5.0l8.0,0.0L16.0,19.0z" />
+        android:pathData="M1,15c0.55,0 1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v4c0,0.55 0.45,1 1,1zM4,17c0.55,0 1,-0.45 1,-1L5,8c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v8c0,0.55 0.45,1 1,1zM22,10v4c0,0.55 0.45,1 1,1s1,-0.45 1,-1v-4c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1zM20,17c0.55,0 1,-0.45 1,-1L21,8c0,-0.55 -0.45,-1 -1,-1s-1,0.45 -1,1v8c0,0.55 0.45,1 1,1zM16.5,3h-9C6.67,3 6,3.67 6,4.5v15c0,0.83 0.67,1.5 1.5,1.5h9c0.83,0 1.5,-0.67 1.5,-1.5v-15c0,-0.83 -0.67,-1.5 -1.5,-1.5zM16,19L8,19L8,5h8v14z"/>
 
-</vector>
\ No newline at end of file
+</vector>
diff --git a/packages/SystemUI/res/layout/keyguard_bottom_area.xml b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
index 5244122..ddd8ef8 100644
--- a/packages/SystemUI/res/layout/keyguard_bottom_area.xml
+++ b/packages/SystemUI/res/layout/keyguard_bottom_area.xml
@@ -39,7 +39,7 @@
             android:layout_height="wrap_content"
             android:gravity="center_horizontal"
             android:textStyle="italic"
-            android:textColor="?attr/bgProtectSecondaryTextColor"
+            android:textColor="?attr/wallpaperTextColorSecondary"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:visibility="gone" />
 
@@ -49,7 +49,7 @@
             android:layout_height="wrap_content"
             android:gravity="center_horizontal"
             android:textStyle="italic"
-            android:textColor="?attr/bgProtectSecondaryTextColor"
+            android:textColor="?attr/wallpaperTextColorSecondary"
             android:textAppearance="?android:attr/textAppearanceSmall"
             android:accessibilityLiveRegion="polite" />
 
@@ -69,7 +69,7 @@
         android:src="@drawable/ic_camera_alt_24dp"
         android:scaleType="center"
         android:contentDescription="@string/accessibility_camera_button"
-        android:tint="?attr/bgProtectTextColor" />
+        android:tint="?attr/wallpaperTextColor" />
 
     <com.android.systemui.statusbar.KeyguardAffordanceView
         android:id="@+id/left_button"
@@ -79,7 +79,7 @@
         android:src="@drawable/ic_phone_24dp"
         android:scaleType="center"
         android:contentDescription="@string/accessibility_phone_button"
-        android:tint="?attr/bgProtectTextColor" />
+        android:tint="?attr/wallpaperTextColor" />
 
     <com.android.systemui.statusbar.phone.LockIcon
         android:id="@+id/lock_icon"
@@ -89,7 +89,7 @@
         android:src="@drawable/ic_lock_24dp"
         android:contentDescription="@string/accessibility_unlock_button"
         android:scaleType="center"
-        android:tint="?attr/bgProtectTextColor" />
+        android:tint="?attr/wallpaperTextColor" />
 
     <FrameLayout
         android:id="@+id/overlay_container"
diff --git a/packages/SystemUI/res/layout/keyguard_status_bar.xml b/packages/SystemUI/res/layout/keyguard_status_bar.xml
index 71a681c..7b30d6a 100644
--- a/packages/SystemUI/res/layout/keyguard_status_bar.xml
+++ b/packages/SystemUI/res/layout/keyguard_status_bar.xml
@@ -63,7 +63,7 @@
         android:gravity="center_vertical"
         android:ellipsize="marquee"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="?attr/bgProtectSecondaryTextColor"
+        android:textColor="?attr/wallpaperTextColorSecondary"
         android:singleLine="true" />
 
 </com.android.systemui.statusbar.phone.KeyguardStatusBarView>
diff --git a/packages/SystemUI/res/layout/recents_empty.xml b/packages/SystemUI/res/layout/recents_empty.xml
index 8048c68..d7f058c 100644
--- a/packages/SystemUI/res/layout/recents_empty.xml
+++ b/packages/SystemUI/res/layout/recents_empty.xml
@@ -23,8 +23,8 @@
     android:drawableTop="@drawable/recents_empty"
     android:drawablePadding="25dp"
     android:textSize="16sp"
-    android:drawableTint="?attr/bgProtectTextColor"
-    android:textColor="?attr/bgProtectTextColor"
+    android:drawableTint="?attr/wallpaperTextColor"
+    android:textColor="?attr/wallpaperTextColor"
     android:text="@string/recents_empty_message"
     android:fontFamily="sans-serif"
     android:visibility="gone" />
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/recents_stack_action_button.xml b/packages/SystemUI/res/layout/recents_stack_action_button.xml
index 10b4316..4707a8c 100644
--- a/packages/SystemUI/res/layout/recents_stack_action_button.xml
+++ b/packages/SystemUI/res/layout/recents_stack_action_button.xml
@@ -24,7 +24,7 @@
     android:paddingBottom="12dp"
     android:text="@string/recents_stack_action_button_label"
     android:textSize="14sp"
-    android:textColor="?attr/bgProtectTextColor"
+    android:textColor="?attr/wallpaperTextColor"
     android:textAllCaps="true"
     android:shadowColor="#99000000"
     android:shadowDx="0"
diff --git a/packages/SystemUI/res/layout/status_bar_no_notifications.xml b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
index ed4bc67..0a25b69 100644
--- a/packages/SystemUI/res/layout/status_bar_no_notifications.xml
+++ b/packages/SystemUI/res/layout/status_bar_no_notifications.xml
@@ -27,7 +27,7 @@
             android:layout_height="64dp"
             android:paddingTop="28dp"
             android:gravity="top|center_horizontal"
-            android:textColor="?attr/bgProtectTextColor"
+            android:textColor="?attr/wallpaperTextColor"
             android:textSize="16sp"
             android:text="@string/empty_shade_text"/>
 </com.android.systemui.statusbar.EmptyShadeView>
diff --git a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
index eefa9bc..8dc4cb4 100644
--- a/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
+++ b/packages/SystemUI/res/layout/status_bar_notification_dismiss_all.xml
@@ -30,6 +30,6 @@
             android:focusable="true"
             android:contentDescription="@string/accessibility_clear_all"
             android:text="@string/clear_all_notifications_text"
-            android:textColor="?attr/bgProtectTextColor"
+            android:textColor="?attr/wallpaperTextColor"
             android:textAllCaps="true"/>
 </com.android.systemui.statusbar.DismissView>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 75ed110..4668b80 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -29,7 +29,7 @@
       <item quantity="one">अवलोकन में %d स्‍क्रीन</item>
       <item quantity="other">अवलोकन में %d स्‍क्रीन</item>
     </plurals>
-    <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कोई नोटिफिकेशन नहीं"</string>
+    <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"कोई नोटिफ़िकेशन नहीं"</string>
     <string name="status_bar_ongoing_events_title" msgid="1682504513316879202">"ऑनगोइंग"</string>
     <string name="status_bar_latest_events_title" msgid="6594767438577593172">"सूचनाएं"</string>
     <string name="battery_low_title" msgid="6456385927409742437">"बैटरी कम है"</string>
@@ -166,7 +166,7 @@
     <string name="accessibility_settings_button" msgid="799583911231893380">"सिस्टम सेटिंग."</string>
     <string name="accessibility_notifications_button" msgid="4498000369779421892">"सूचनाएं."</string>
     <string name="accessibility_overflow_action" msgid="5681882033274783311">"सभी नोटिफ़िकेशन देखें"</string>
-    <string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफिकेशन साफ़ करें"</string>
+    <string name="accessibility_remove_notification" msgid="3603099514902182350">"नोटिफ़िकेशन साफ़ करें"</string>
     <string name="accessibility_gps_enabled" msgid="3511469499240123019">"GPS सक्षम."</string>
     <string name="accessibility_gps_acquiring" msgid="8959333351058967158">"GPS प्राप्त करना."</string>
     <string name="accessibility_tty_enabled" msgid="4613200365379426561">"टेलीटाइपराइटर सक्षम."</string>
@@ -181,8 +181,8 @@
     <string name="accessibility_recents_item_open_app_info" msgid="5107479759905883540">"<xliff:g id="APP">%s</xliff:g> ऐप्लिकेशन जानकारी खोलें."</string>
     <string name="accessibility_recents_item_launched" msgid="7616039892382525203">"<xliff:g id="APP">%s</xliff:g> प्रारंभ हो रहा है."</string>
     <string name="accessibility_recents_task_header" msgid="1437183540924535457">"<xliff:g id="APP">%1$s</xliff:g> <xliff:g id="ACTIVITY_LABEL">%2$s</xliff:g>"</string>
-    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफिकेशन खारिज की गई."</string>
-    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफिकेशन शेड."</string>
+    <string name="accessibility_notification_dismissed" msgid="854211387186306927">"नोटिफ़िकेशन खारिज की गई."</string>
+    <string name="accessibility_desc_notification_shade" msgid="4690274844447504208">"नोटिफ़िकेशन शेड."</string>
     <string name="accessibility_desc_quick_settings" msgid="6186378411582437046">"त्वरित सेटिंग."</string>
     <string name="accessibility_desc_lock_screen" msgid="5625143713611759164">"लॉक स्क्रीन."</string>
     <string name="accessibility_desc_settings" msgid="3417884241751434521">"सेटिंग"</string>
@@ -255,7 +255,7 @@
       <item quantity="one">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और नोटिफ़िकेशन हैं.</item>
       <item quantity="other">इसमें <xliff:g id="NUMBER_1">%s</xliff:g> और नोटिफ़िकेशन हैं.</item>
     </plurals>
-    <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"नोटिफिकेशन सेटिंग"</string>
+    <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"नोटिफ़िकेशन सेटिंग"</string>
     <string name="status_bar_notification_app_settings_title" msgid="5525260160341558869">"<xliff:g id="APP_NAME">%s</xliff:g> सेटिंग"</string>
     <string name="accessibility_rotation_lock_off" msgid="4062780228931590069">"स्‍क्रीन स्‍वचालित रूप से घूमेगी."</string>
     <string name="accessibility_rotation_lock_on_landscape" msgid="6731197337665366273">"स्‍क्रीन लैंडस्केप अभिविन्यास में लॉक है."</string>
@@ -411,7 +411,7 @@
     <string name="media_projection_remember_text" msgid="3103510882172746752">"फिर से न दिखाएं"</string>
     <string name="clear_all_notifications_text" msgid="814192889771462828">"सभी साफ करें"</string>
     <string name="media_projection_action_text" msgid="8470872969457985954">"अब प्रारंभ करें"</string>
-    <string name="empty_shade_text" msgid="708135716272867002">"कोई नोटिफिकेशन नहीं"</string>
+    <string name="empty_shade_text" msgid="708135716272867002">"कोई नोटिफ़िकेशन नहीं"</string>
     <string name="profile_owned_footer" msgid="8021888108553696069">"प्रोफ़ाइल को मॉनीटर किया जा सकता है"</string>
     <string name="vpn_footer" msgid="2388611096129106812">"नेटवर्क को मॉनीटर किया जा सकता है"</string>
     <string name="branded_vpn_footer" msgid="2168111859226496230">"नेटवर्क को मॉनिटर किया जा सकता है"</string>
@@ -542,8 +542,8 @@
     <string name="enable_bluetooth_title" msgid="5027037706500635269">"ब्लूटूथ चालू करें?"</string>
     <string name="enable_bluetooth_message" msgid="9106595990708985385">"अपने कीबोर्ड को अपने टैबलेट से कनेक्ट करने के लिए, आपको पहले ब्लूटूथ चालू करना होगा."</string>
     <string name="enable_bluetooth_confirmation_ok" msgid="6258074250948309715">"चालू करें"</string>
-    <string name="show_silently" msgid="6841966539811264192">"नोटिफिकेशन मौन रूप से दिखाएं"</string>
-    <string name="block" msgid="2734508760962682611">"सभी नोटिफिकेशन अवरुद्ध करें"</string>
+    <string name="show_silently" msgid="6841966539811264192">"नोटिफ़िकेशन मौन रूप से दिखाएं"</string>
+    <string name="block" msgid="2734508760962682611">"सभी नोटिफ़िकेशन अवरुद्ध करें"</string>
     <string name="do_not_silence" msgid="6878060322594892441">"मौन ना करें"</string>
     <string name="do_not_silence_block" msgid="4070647971382232311">"मौन या अवरुद्ध ना करें"</string>
     <string name="tuner_full_importance_settings" msgid="3207312268609236827">"पावर नोटिफ़िकेशन नियंत्रण"</string>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index c35c30c..7667c5e 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -758,7 +758,7 @@
     <string name="notification_channel_alerts" msgid="4496839309318519037">"알림"</string>
     <string name="notification_channel_screenshot" msgid="6314080179230000938">"스크린샷"</string>
     <string name="notification_channel_general" msgid="4525309436693914482">"일반 메시지"</string>
-    <string name="notification_channel_storage" msgid="3077205683020695313">"저장소"</string>
+    <string name="notification_channel_storage" msgid="3077205683020695313">"저장공간"</string>
     <string name="instant_apps" msgid="6647570248119804907">"인스턴트 앱"</string>
     <string name="instant_apps_message" msgid="8116608994995104836">"인스턴트 앱은 설치가 필요하지 않습니다."</string>
     <string name="app_info" msgid="6856026610594615344">"앱 정보"</string>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 06325eb..7d7c9c6 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -214,10 +214,10 @@
     <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth conectado."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"O Bluetooth foi desativado."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"O Bluetooth foi ativado."</string>
-    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Relatório de Localização desativado."</string>
-    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Relatório de Localização ativado."</string>
-    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"O Relatório de Localização foi desativado."</string>
-    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"O Relatório de Localização foi ativado."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Relatório de localização desativado."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Relatório de localização ativado."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"O Relatório de localização foi desativado."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"O Relatório de localização foi ativado."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Fechar painel."</string>
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 53196cd..b40b6d4 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -26,7 +26,7 @@
     <string name="status_bar_no_recent_apps" msgid="7374907845131203189">"Os ecrãs recentes aparecem aqui"</string>
     <string name="status_bar_accessibility_dismiss_recents" msgid="4576076075226540105">"Ignorar aplicações recentes"</string>
     <plurals name="status_bar_accessibility_recent_apps" formatted="false" msgid="9138535907802238759">
-      <item quantity="one">%d screens in Overview</item>
+      <item quantity="one">%d ecrã na Vista geral</item>
       <item quantity="other">%d ecrãs na Vista geral</item>
     </plurals>
     <string name="status_bar_no_notifications_title" msgid="4755261167193833213">"Sem notificações"</string>
@@ -252,7 +252,7 @@
     <string name="accessibility_clear_all" msgid="5235938559247164925">"Limpar todas as notificações."</string>
     <string name="notification_group_overflow_indicator" msgid="1863231301642314183">"+ <xliff:g id="NUMBER">%s</xliff:g>"</string>
     <plurals name="notification_group_overflow_description" formatted="false" msgid="4579313201268495404">
-      <item quantity="one"><xliff:g id="NUMBER_1">%s</xliff:g> more notifications inside.</item>
+      <item quantity="one">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificação no grupo.</item>
       <item quantity="other">Mais <xliff:g id="NUMBER_1">%s</xliff:g> notificações no grupo.</item>
     </plurals>
     <string name="status_bar_notification_inspect_item_title" msgid="5668348142410115323">"Definições de notificação"</string>
@@ -556,12 +556,12 @@
     <string name="notification_default_channel_desc" msgid="2506053815870808359">"Esta aplicação não tem categorias de notificação"</string>
     <string name="notification_unblockable_desc" msgid="3561016061737896906">"Não é possível desativar as notificações desta aplicação"</string>
     <plurals name="notification_num_channels_desc" formatted="false" msgid="5492793452274077663">
-      <item quantity="one">1 out of <xliff:g id="NUMBER_1">%d</xliff:g> notification categories from this app</item>
+      <item quantity="one">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categoria de notificação desta aplicação</item>
       <item quantity="other">1 de <xliff:g id="NUMBER_1">%d</xliff:g> categorias de notificação desta aplicação</item>
     </plurals>
     <string name="notification_channels_list_desc_2" msgid="6214732715833946441">"<xliff:g id="CHANNEL_NAME_1">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2">%2$s</xliff:g>"</string>
     <plurals name="notification_channels_list_desc_2_and_others" formatted="false" msgid="2747813553355336157">
-      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g>, and <xliff:g id="NUMBER_5">%3$d</xliff:g> others</item>
+      <item quantity="one"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e mais <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
       <item quantity="other"><xliff:g id="CHANNEL_NAME_1_3">%1$s</xliff:g>, <xliff:g id="CHANNEL_NAME_2_4">%2$s</xliff:g> e mais <xliff:g id="NUMBER_5">%3$d</xliff:g></item>
     </plurals>
     <string name="notification_channel_controls_opened_accessibility" msgid="6553950422055908113">"Controlos de notificações da aplicação <xliff:g id="APP_NAME">%1$s</xliff:g> abertos"</string>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 06325eb..7d7c9c6 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -214,10 +214,10 @@
     <string name="accessibility_quick_settings_bluetooth_connected" msgid="4306637793614573659">"Bluetooth conectado."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_off" msgid="2730003763480934529">"O Bluetooth foi desativado."</string>
     <string name="accessibility_quick_settings_bluetooth_changed_on" msgid="8722351798763206577">"O Bluetooth foi ativado."</string>
-    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Relatório de Localização desativado."</string>
-    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Relatório de Localização ativado."</string>
-    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"O Relatório de Localização foi desativado."</string>
-    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"O Relatório de Localização foi ativado."</string>
+    <string name="accessibility_quick_settings_location_off" msgid="5119080556976115520">"Relatório de localização desativado."</string>
+    <string name="accessibility_quick_settings_location_on" msgid="5809937096590102036">"Relatório de localização ativado."</string>
+    <string name="accessibility_quick_settings_location_changed_off" msgid="8526845571503387376">"O Relatório de localização foi desativado."</string>
+    <string name="accessibility_quick_settings_location_changed_on" msgid="339403053079338468">"O Relatório de localização foi ativado."</string>
     <string name="accessibility_quick_settings_alarm" msgid="3959908972897295660">"Alarme definido para <xliff:g id="TIME">%s</xliff:g>."</string>
     <string name="accessibility_quick_settings_close" msgid="3115847794692516306">"Fechar painel."</string>
     <string name="accessibility_quick_settings_more_time" msgid="3659274935356197708">"Mais tempo."</string>
diff --git a/packages/SystemUI/res/values/attrs.xml b/packages/SystemUI/res/values/attrs.xml
index 81f0138..0560082 100644
--- a/packages/SystemUI/res/values/attrs.xml
+++ b/packages/SystemUI/res/values/attrs.xml
@@ -127,7 +127,7 @@
 
     <attr name="lightIconTheme" format="reference" />
     <attr name="darkIconTheme" format="reference" />
-    <attr name="bgProtectTextColor" format="color" />
-    <attr name="bgProtectSecondaryTextColor" format="color" />
+    <attr name="wallpaperTextColor" format="color" />
+    <attr name="wallpaperTextColorSecondary" format="color" />
 </resources>
 
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 1705f79..34aa6d0 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -268,11 +268,14 @@
     <integer name="doze_small_icon_alpha">222</integer><!-- 87% of 0xff -->
 
     <!-- Doze: the brightness value to use for the lower brightness AOD mode -->
-    <integer name="config_doze_aod_brightness_low">6</integer>
+    <integer name="config_doze_aod_brightness_low">5</integer>
 
     <!-- Doze: the brightness value to use for the higher brightness AOD mode -->
     <integer name="config_doze_aod_brightness_high">27</integer>
 
+    <!-- Doze: the brightness value to use for the sunlight AOD mode -->
+    <integer name="config_doze_aod_brightness_sunlight">28</integer>
+
     <!-- Doze: whether the double tap sensor reports 2D touch coordinates -->
     <bool name="doze_double_tap_reports_touch_coordinates">false</bool>
 
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 1ff7ae4..94687de 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -101,6 +101,9 @@
     <!-- Height of a the shelf with the notification icons -->
     <dimen name="notification_shelf_height">32dp</dimen>
 
+    <!-- Minimum height of a notification to be interactable -->
+    <dimen name="notification_min_interaction_height">40dp</dimen>
+
     <!-- the padding of the shelf icon container -->
     <dimen name="shelf_icon_container_padding">13dp</dimen>
 
@@ -781,6 +784,9 @@
     <!-- The shortest-edge size of the expanded PiP. -->
     <dimen name="pip_expanded_shortest_edge_size">160dp</dimen>
 
+    <!-- The additional offset to apply to the IME animation to account for the input field. -->
+    <dimen name="pip_ime_offset">48dp</dimen>
+
     <!-- The padding between actions in the PiP in landscape  Note that the PiP does not reflect
          the configuration of the device, so we can't use -land resources. -->
     <dimen name="pip_between_action_padding_land">8dp</dimen>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index b61c5b5..daed847 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -41,8 +41,8 @@
         <item name="android:windowShowWallpaper">true</item>
         <item name="android:windowDisablePreview">true</item>
         <item name="clearAllStyle">@style/ClearAllButtonDefaultMargins</item>
-        <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
-        <item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
+        <item name="wallpaperTextColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="wallpaperTextColorSecondary">?android:attr/textColorSecondaryInverse</item>
     </style>
 
     <style name="ClearAllButtonDefaultMargins">
@@ -55,8 +55,8 @@
     <!-- Performance optimized Recents theme (no wallpaper) -->
     <style name="RecentsTheme.NoWallpaper">
         <item name="android:windowBackground">@android:color/black</item>
-        <item name="bgProtectTextColor">@android:color/white</item>
-        <item name="bgProtectSecondaryTextColor">@android:color/white</item>
+        <item name="wallpaperTextColor">@android:color/white</item>
+        <item name="wallpaperTextColorSecondary">@android:color/white</item>
     </style>
 
     <!-- Theme used for the activity that shows when the system forced an app to be resizable -->
@@ -306,8 +306,8 @@
     <style name="systemui_theme" parent="systemui_base">
         <item name="lightIconTheme">@style/DualToneLightTheme</item>
         <item name="darkIconTheme">@style/DualToneDarkTheme</item>
-        <item name="bgProtectTextColor">?android:attr/textColorPrimaryInverse</item>
-        <item name="bgProtectSecondaryTextColor">?android:attr/textColorSecondaryInverse</item>
+        <item name="wallpaperTextColor">?android:attr/textColorPrimaryInverse</item>
+        <item name="wallpaperTextColorSecondary">?android:attr/textColorSecondaryInverse</item>
         <item name="android:colorControlHighlight">?android:attr/textColorSecondaryInverse</item>
         <item name="*android:lockPatternStyle">@style/LockPatternStyle</item>
     </style>
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
index 5005f9d..a9d583f 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusView.java
@@ -24,6 +24,8 @@
 import android.content.res.Resources;
 import android.graphics.Color;
 import android.graphics.PorterDuff;
+import android.os.Handler;
+import android.os.Looper;
 import android.os.UserHandle;
 import android.support.v4.graphics.ColorUtils;
 import android.text.TextUtils;
@@ -48,6 +50,7 @@
 public class KeyguardStatusView extends GridLayout {
     private static final boolean DEBUG = KeyguardConstants.DEBUG;
     private static final String TAG = "KeyguardStatusView";
+    private static final int MARQUEE_DELAY_MS = 2000;
 
     private final LockPatternUtils mLockPatternUtils;
     private final AlarmManager mAlarmManager;
@@ -59,6 +62,8 @@
     private ViewGroup mClockContainer;
     private ChargingView mBatteryDoze;
     private View mKeyguardStatusArea;
+    private Runnable mPendingMarqueeStart;
+    private Handler mHandler;
 
     private View[] mVisibleInDoze;
     private boolean mPulsing;
@@ -112,9 +117,29 @@
         super(context, attrs, defStyle);
         mAlarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
         mLockPatternUtils = new LockPatternUtils(getContext());
+        mHandler = new Handler(Looper.myLooper());
     }
 
     private void setEnableMarquee(boolean enabled) {
+        if (DEBUG) Log.v(TAG, "Schedule setEnableMarquee: " + (enabled ? "Enable" : "Disable"));
+        if (enabled) {
+            if (mPendingMarqueeStart == null) {
+                mPendingMarqueeStart = () -> {
+                    setEnableMarqueeImpl(true);
+                    mPendingMarqueeStart = null;
+                };
+                mHandler.postDelayed(mPendingMarqueeStart, MARQUEE_DELAY_MS);
+            }
+        } else {
+            if (mPendingMarqueeStart != null) {
+                mHandler.removeCallbacks(mPendingMarqueeStart);
+                mPendingMarqueeStart = null;
+            }
+            setEnableMarqueeImpl(false);
+        }
+    }
+
+    private void setEnableMarqueeImpl(boolean enabled) {
         if (DEBUG) Log.v(TAG, (enabled ? "Enable" : "Disable") + " transport text marquee");
         if (mAlarmStatusView != null) mAlarmStatusView.setSelected(enabled);
         if (mOwnerInfo != null) mOwnerInfo.setSelected(enabled);
@@ -308,6 +333,10 @@
             }
             child.setAlpha(dark ? 0 : 1);
         }
+        if (mOwnerInfo != null) {
+            mOwnerInfo.setAlpha(dark ? 0 : 1);
+        }
+
         updateDozeVisibleViews();
         mBatteryDoze.setDark(dark);
         mClockView.setTextColor(ColorUtils.blendARGB(mTextColor, Color.WHITE, darkAmount));
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
index 14d6b59..5a02178 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitorCallback.java
@@ -154,13 +154,19 @@
 
     /**
      * Called when the device has started waking up.
+     *
+     * @deprecated use {@link com.android.systemui.keyguard.WakefulnessLifecycle}.
      */
+    @Deprecated
     public void onStartedWakingUp() { }
 
     /**
      * Called when the device has started going to sleep.
      * @param why see {@link #onFinishedGoingToSleep(int)}
+     *
+     * @deprecated use {@link com.android.systemui.keyguard.WakefulnessLifecycle}.
      */
+    @Deprecated
     public void onStartedGoingToSleep(int why) { }
 
     /**
@@ -168,17 +174,26 @@
      * @param why either {@link WindowManagerPolicy#OFF_BECAUSE_OF_ADMIN},
      * {@link WindowManagerPolicy#OFF_BECAUSE_OF_USER}, or
      * {@link WindowManagerPolicy#OFF_BECAUSE_OF_TIMEOUT}.
+     *
+     * @deprecated use {@link com.android.systemui.keyguard.WakefulnessLifecycle}.
      */
+    @Deprecated
     public void onFinishedGoingToSleep(int why) { }
 
     /**
      * Called when the screen has been turned on.
+     *
+     * @deprecated use {@link com.android.systemui.keyguard.ScreenLifecycle}.
      */
+    @Deprecated
     public void onScreenTurnedOn() { }
 
     /**
      * Called when the screen has been turned off.
+     *
+     * @deprecated use {@link com.android.systemui.keyguard.ScreenLifecycle}.
      */
+    @Deprecated
     public void onScreenTurnedOff() { }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index 776d076..e5c729f 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -30,6 +30,8 @@
 import com.android.systemui.assist.AssistManager;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.fragments.FragmentService;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.PluginActivityManager;
 import com.android.systemui.plugins.PluginDependencyProvider;
@@ -248,6 +250,12 @@
         mProviders.put(StatusBarIconController.class, () ->
                 new StatusBarIconControllerImpl(mContext));
 
+        mProviders.put(ScreenLifecycle.class, () ->
+                new ScreenLifecycle());
+
+        mProviders.put(WakefulnessLifecycle.class, () ->
+                new WakefulnessLifecycle());
+
         mProviders.put(FragmentService.class, () ->
                 new FragmentService(mContext));
 
diff --git a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
index 44cf003..fe8373f 100644
--- a/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
+++ b/packages/SystemUI/src/com/android/systemui/colorextraction/SysuiColorExtractor.java
@@ -98,7 +98,7 @@
      */
     @Override
     public GradientColors getColors(int which) {
-        return getColors(which, TYPE_NORMAL);
+        return getColors(which, TYPE_DARK);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
index 0be4eda..a1dfeb3 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeMachine.java
@@ -91,6 +91,7 @@
                 case UNINITIALIZED:
                 case INITIALIZED:
                 case DOZE:
+                case DOZE_REQUEST_PULSE:
                 case DOZE_AOD_PAUSED:
                     return Display.STATE_OFF;
                 case DOZE_PULSING:
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
index 28a45aa..ed4b131 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeScreenBrightness.java
@@ -39,6 +39,7 @@
 
     private final int mHighBrightness;
     private final int mLowBrightness;
+    private final int mSunlightBrightness;
 
     public DozeScreenBrightness(Context context, DozeMachine.Service service,
             SensorManager sensorManager, Sensor lightSensor, Handler handler) {
@@ -52,6 +53,8 @@
                 R.integer.config_doze_aod_brightness_low);
         mHighBrightness = context.getResources().getInteger(
                 R.integer.config_doze_aod_brightness_high);
+        mSunlightBrightness = context.getResources().getInteger(
+                R.integer.config_doze_aod_brightness_sunlight);
     }
 
     @Override
@@ -83,9 +86,12 @@
     }
 
     private int computeBrightness(int sensorValue) {
-        // The sensor reports 0 for off, 1 for low brightness and 2 for high brightness.
-        // We currently use DozeScreenState for screen off, so we treat off as low brightness.
-        if (sensorValue >= 2) {
+        // The sensor reports 0 for off, 1 for low brightness, 2 for high brightness, and 3 for
+        // sunlight. We currently use DozeScreenState for screen off, so we treat off as low
+        // brightness.
+        if (sensorValue >= 3) {
+            return mSunlightBrightness;
+        } else if (sensorValue == 2) {
             return mHighBrightness;
         } else {
             return mLowBrightness;
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
index 9b113d8..ad177a7 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java
@@ -25,8 +25,10 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.HardwareUiLayout;
+import com.android.systemui.Interpolators;
 import com.android.systemui.colorextraction.SysuiColorExtractor;
 import com.android.systemui.plugins.GlobalActions.GlobalActionsManager;
+import com.android.systemui.statusbar.notification.NotificationUtils;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.volume.VolumeDialogMotion.LogAccelerateInterpolator;
 import com.android.systemui.volume.VolumeDialogMotion.LogDecelerateInterpolator;
@@ -65,6 +67,7 @@
 import android.text.TextUtils;
 import android.util.ArraySet;
 import android.util.Log;
+import android.util.MathUtils;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
@@ -112,6 +115,8 @@
     private static final String GLOBAL_ACTION_KEY_ASSIST = "assist";
     private static final String GLOBAL_ACTION_KEY_RESTART = "restart";
 
+    private static final float SHUTDOWN_SCRIM_ALPHA = 0.95f;
+
     private final Context mContext;
     private final GlobalActionsManager mWindowManagerFuncs;
     private final AudioManager mAudioManager;
@@ -1291,7 +1296,7 @@
                     .alpha(1)
                     .translationX(0)
                     .setDuration(300)
-                    .setInterpolator(new LogDecelerateInterpolator())
+                    .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                     .setUpdateListener(animation -> {
                         int alpha = (int) ((Float) animation.getAnimatedValue()
                                 * ScrimController.GRADIENT_SCRIM_ALPHA * 255);
@@ -1329,9 +1334,8 @@
                     .setInterpolator(new LogAccelerateInterpolator())
                     .setUpdateListener(animation -> {
                         float frac = animation.getAnimatedFraction();
-                        float alpha = frac *(ScrimController.GRADIENT_SCRIM_ALPHA_BUSY
-                                        - ScrimController.GRADIENT_SCRIM_ALPHA)
-                                + ScrimController.GRADIENT_SCRIM_ALPHA;
+                        float alpha = NotificationUtils.interpolate(
+                                ScrimController.GRADIENT_SCRIM_ALPHA, SHUTDOWN_SCRIM_ALPHA, frac);
                         mGradientDrawable.setAlpha((int) (alpha * 255));
                     })
                     .start();
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
new file mode 100644
index 0000000..4c98c08
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardLifecyclesDispatcher.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import android.os.Handler;
+import android.os.Message;
+
+import com.android.internal.policy.IKeyguardDrawnCallback;
+
+/**
+ * Dispatches the lifecycles keyguard gets from WindowManager on the main thread.
+ */
+public class KeyguardLifecyclesDispatcher {
+
+    static final int SCREEN_TURNING_ON = 0;
+    static final int SCREEN_TURNED_ON = 1;
+    static final int SCREEN_TURNING_OFF = 2;
+    static final int SCREEN_TURNED_OFF = 3;
+
+    static final int STARTED_WAKING_UP = 4;
+    static final int FINISHED_WAKING_UP = 5;
+    static final int STARTED_GOING_TO_SLEEP = 6;
+    static final int FINISHED_GOING_TO_SLEEP = 7;
+
+    private final ScreenLifecycle mScreenLifecycle;
+    private final WakefulnessLifecycle mWakefulnessLifecycle;
+
+    public KeyguardLifecyclesDispatcher(ScreenLifecycle screenLifecycle,
+            WakefulnessLifecycle wakefulnessLifecycle) {
+        mScreenLifecycle = screenLifecycle;
+        mWakefulnessLifecycle = wakefulnessLifecycle;
+    }
+
+    void dispatch(int what) {
+        mHandler.obtainMessage(what).sendToTarget();
+    }
+
+    private Handler mHandler = new Handler() {
+        @Override
+        public void handleMessage(Message msg) {
+            switch (msg.what) {
+                case SCREEN_TURNING_ON:
+                    mScreenLifecycle.dispatchScreenTurningOn();
+                    break;
+                case SCREEN_TURNED_ON:
+                    mScreenLifecycle.dispatchScreenTurnedOn();
+                    break;
+                case SCREEN_TURNING_OFF:
+                    mScreenLifecycle.dispatchScreenTurningOff();
+                    break;
+                case SCREEN_TURNED_OFF:
+                    mScreenLifecycle.dispatchScreenTurnedOff();
+                    break;
+                case STARTED_WAKING_UP:
+                    mWakefulnessLifecycle.dispatchStartedWakingUp();
+                    break;
+                case FINISHED_WAKING_UP:
+                    mWakefulnessLifecycle.dispatchFinishedWakingUp();
+                    break;
+                case STARTED_GOING_TO_SLEEP:
+                    mWakefulnessLifecycle.dispatchStartedGoingToSleep();
+                    break;
+                case FINISHED_GOING_TO_SLEEP:
+                    mWakefulnessLifecycle.dispatchFinishedGoingToSleep();
+                    break;
+                default:
+                    throw new IllegalArgumentException("Unknown message: " + msg);
+            }
+        }
+    };
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 2d5d198..2a5ae0d 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -31,6 +31,7 @@
 import com.android.internal.policy.IKeyguardExitCallback;
 import com.android.internal.policy.IKeyguardService;
 import com.android.internal.policy.IKeyguardStateCallback;
+import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIApplication;
 
 import static android.content.pm.PackageManager.PERMISSION_GRANTED;
@@ -40,12 +41,17 @@
     static final String PERMISSION = android.Manifest.permission.CONTROL_KEYGUARD;
 
     private KeyguardViewMediator mKeyguardViewMediator;
+    private KeyguardLifecyclesDispatcher mKeyguardLifecyclesDispatcher;
 
     @Override
     public void onCreate() {
         ((SystemUIApplication) getApplication()).startServicesIfNeeded();
         mKeyguardViewMediator =
                 ((SystemUIApplication) getApplication()).getComponent(KeyguardViewMediator.class);
+        mKeyguardLifecyclesDispatcher = new KeyguardLifecyclesDispatcher(
+                Dependency.get(ScreenLifecycle.class),
+                Dependency.get(WakefulnessLifecycle.class));
+
     }
 
     @Override
@@ -111,12 +117,16 @@
         public void onStartedGoingToSleep(int reason) {
             checkPermission();
             mKeyguardViewMediator.onStartedGoingToSleep(reason);
+            mKeyguardLifecyclesDispatcher.dispatch(
+                    KeyguardLifecyclesDispatcher.STARTED_GOING_TO_SLEEP);
         }
 
         @Override // Binder interface
         public void onFinishedGoingToSleep(int reason, boolean cameraGestureTriggered) {
             checkPermission();
             mKeyguardViewMediator.onFinishedGoingToSleep(reason, cameraGestureTriggered);
+            mKeyguardLifecyclesDispatcher.dispatch(
+                    KeyguardLifecyclesDispatcher.FINISHED_GOING_TO_SLEEP);
         }
 
         @Override // Binder interface
@@ -124,6 +134,15 @@
             Trace.beginSection("KeyguardService.mBinder#onStartedWakingUp");
             checkPermission();
             mKeyguardViewMediator.onStartedWakingUp();
+            mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.STARTED_WAKING_UP);
+            Trace.endSection();
+        }
+
+        @Override // Binder interface
+        public void onFinishedWakingUp() {
+            Trace.beginSection("KeyguardService.mBinder#onFinishedWakingUp");
+            checkPermission();
+            mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.FINISHED_WAKING_UP);
             Trace.endSection();
         }
 
@@ -132,6 +151,7 @@
             Trace.beginSection("KeyguardService.mBinder#onScreenTurningOn");
             checkPermission();
             mKeyguardViewMediator.onScreenTurningOn(callback);
+            mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_ON);
             Trace.endSection();
         }
 
@@ -140,13 +160,21 @@
             Trace.beginSection("KeyguardService.mBinder#onScreenTurnedOn");
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOn();
+            mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_ON);
             Trace.endSection();
         }
 
         @Override // Binder interface
+        public void onScreenTurningOff() {
+            checkPermission();
+            mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNING_OFF);
+        }
+
+        @Override // Binder interface
         public void onScreenTurnedOff() {
             checkPermission();
             mKeyguardViewMediator.onScreenTurnedOff();
+            mKeyguardLifecyclesDispatcher.dispatch(KeyguardLifecyclesDispatcher.SCREEN_TURNED_OFF);
         }
 
         @Override // Binder interface
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index 6d10d94..e23875f 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -811,6 +811,7 @@
         synchronized (this) {
             mDeviceInteractive = false;
             mGoingToSleep = false;
+            mWakeAndUnlocking = false;
 
             resetKeyguardDonePendingLocked();
             mHideAnimationRun = false;
@@ -1957,7 +1958,6 @@
             if (DEBUG) Log.d(TAG, "handleNotifyScreenTurnedOff");
             mStatusBarKeyguardViewManager.onScreenTurnedOff();
             mDrawnCallback = null;
-            mWakeAndUnlocking = false;
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java
new file mode 100644
index 0000000..1b20cfb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/Lifecycle.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import java.util.ArrayList;
+import java.util.function.Consumer;
+
+/**
+ * Base class for lifecycles with observers.
+ */
+public class Lifecycle<T> {
+
+    private ArrayList<T> mObservers = new ArrayList<>();
+
+    public void addObserver(T observer) {
+        mObservers.add(observer);
+    }
+
+    public void removeObserver(T observer) {
+        mObservers.remove(observer);
+    }
+
+    public void dispatch(Consumer<T> consumer) {
+        for (int i = 0; i < mObservers.size(); i++) {
+            consumer.accept(mObservers.get(i));
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
new file mode 100644
index 0000000..3f39dfe
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ScreenLifecycle.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import com.android.systemui.Dumpable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Tracks the screen lifecycle.
+ */
+public class ScreenLifecycle extends Lifecycle<ScreenLifecycle.Observer> implements Dumpable {
+
+    public static final int SCREEN_OFF = 0;
+    public static final int SCREEN_TURNING_ON = 1;
+    public static final int SCREEN_ON = 2;
+    public static final int SCREEN_TURNING_OFF = 3;
+
+    private int mScreenState = SCREEN_OFF;
+
+    public int getScreenState() {
+        return mScreenState;
+    }
+
+    public void dispatchScreenTurningOn() {
+        mScreenState = SCREEN_TURNING_ON;
+        dispatch(Observer::onScreenTurningOn);
+    }
+
+    public void dispatchScreenTurnedOn() {
+        mScreenState = SCREEN_ON;
+        dispatch(Observer::onScreenTurnedOn);
+    }
+
+    public void dispatchScreenTurningOff() {
+        mScreenState = SCREEN_TURNING_OFF;
+        dispatch(Observer::onScreenTurningOff);
+    }
+
+    public void dispatchScreenTurnedOff() {
+        mScreenState = SCREEN_OFF;
+        dispatch(Observer::onScreenTurnedOff);
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("ScreenLifecycle:");
+        pw.println("  mScreenState=" + mScreenState);
+    }
+
+    public interface Observer {
+        default void onScreenTurningOn() {}
+        default void onScreenTurnedOn() {}
+        default void onScreenTurningOff() {}
+        default void onScreenTurnedOff() {}
+    }
+
+}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
new file mode 100644
index 0000000..578e6fb
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/WakefulnessLifecycle.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import com.android.systemui.Dumpable;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+
+/**
+ * Tracks the wakefulness lifecycle.
+ */
+public class WakefulnessLifecycle extends Lifecycle<WakefulnessLifecycle.Observer> implements
+        Dumpable {
+
+    public static final int WAKEFULNESS_ASLEEP = 0;
+    public static final int WAKEFULNESS_WAKING = 1;
+    public static final int WAKEFULNESS_AWAKE = 2;
+    public static final int WAKEFULNESS_GOING_TO_SLEEP = 3;
+
+    private int mWakefulness = WAKEFULNESS_ASLEEP;
+
+    public int getWakefulness() {
+        return mWakefulness;
+    }
+
+    public void dispatchStartedWakingUp() {
+        mWakefulness = WAKEFULNESS_WAKING;
+        dispatch(Observer::onStartedWakingUp);
+    }
+
+    public void dispatchFinishedWakingUp() {
+        mWakefulness = WAKEFULNESS_AWAKE;
+        dispatch(Observer::onFinishedWakingUp);
+    }
+
+    public void dispatchStartedGoingToSleep() {
+        mWakefulness = WAKEFULNESS_GOING_TO_SLEEP;
+        dispatch(Observer::onStartedGoingToSleep);
+    }
+
+    public void dispatchFinishedGoingToSleep() {
+        mWakefulness = WAKEFULNESS_ASLEEP;
+        dispatch(Observer::onFinishedGoingToSleep);
+    }
+
+    @Override
+    public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
+        pw.println("WakefulnessLifecycle:");
+        pw.println("  mWakefulness=" + mWakefulness);
+    }
+
+    public interface Observer {
+        default void onStartedWakingUp() {}
+        default void onFinishedWakingUp() {}
+        default void onStartedGoingToSleep() {}
+        default void onFinishedGoingToSleep() {}
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 278fdc3..d3be19d 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -27,6 +27,7 @@
 import android.app.IActivityManager;
 import android.content.ComponentName;
 import android.content.Context;
+import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.PointF;
 import android.graphics.Rect;
@@ -122,6 +123,7 @@
     private boolean mIsMinimized;
     private boolean mIsImeShowing;
     private int mImeHeight;
+    private int mImeOffset;
     private float mSavedSnapFraction = -1f;
     private boolean mSendingHoverAccessibilityEvents;
     private boolean mMovementWithinMinimize;
@@ -192,8 +194,11 @@
         };
         mMotionHelper = new PipMotionHelper(mContext, mActivityManager, mMenuController,
                 mSnapAlgorithm, mFlingAnimationUtils);
-        mExpandedShortestEdgeSize = context.getResources().getDimensionPixelSize(
+
+        Resources res = context.getResources();
+        mExpandedShortestEdgeSize = res.getDimensionPixelSize(
                 R.dimen.pip_expanded_shortest_edge_size);
+        mImeOffset = res.getDimensionPixelSize(R.dimen.pip_ime_offset);
 
         // Register the listener for input consumer touch events
         inputConsumerController.setTouchListener(this::handleTouchEvent);
@@ -265,7 +270,6 @@
         mSnapAlgorithm.getMovementBounds(mExpandedBounds, insetBounds, expandedMovementBounds,
                 mIsImeShowing ? mImeHeight : 0);
 
-
         // If this is from an IME adjustment, then we should move the PiP so that it is not occluded
         // by the IME
         if (fromImeAdjustement) {
@@ -278,18 +282,22 @@
                         ? expandedMovementBounds
                         : normalMovementBounds;
                 if (mIsImeShowing) {
-                    // IME visible
+                    // IME visible, apply the IME offset if the space allows for it
+                    final int imeOffset = toMovementBounds.bottom - Math.max(toMovementBounds.top,
+                            toMovementBounds.bottom - mImeOffset);
                     if (bounds.top == mMovementBounds.bottom) {
                         // If the PIP is currently resting on top of the IME, then adjust it with
-                        // the hiding IME
-                        bounds.offsetTo(bounds.left, toMovementBounds.bottom);
+                        // the showing IME
+                        bounds.offsetTo(bounds.left, toMovementBounds.bottom - imeOffset);
                     } else {
-                        bounds.offset(0, Math.min(0, toMovementBounds.bottom - bounds.top));
+                        bounds.offset(0, Math.min(0, toMovementBounds.bottom - imeOffset
+                                - bounds.top));
                     }
                 } else {
                     // IME hidden
-                    if (bounds.top == mMovementBounds.bottom) {
-                        // If the PIP is resting on top of the IME, then adjust it with the hiding IME
+                    if (bounds.top >= (mMovementBounds.bottom - mImeOffset)) {
+                        // If the PIP is resting on top of the IME, then adjust it with the hiding
+                        // IME
                         bounds.offsetTo(bounds.left, toMovementBounds.bottom);
                     }
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index dd3361b..686b3bb 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -29,7 +29,7 @@
  */
 public class PipTouchState {
     private static final String TAG = "PipTouchHandler";
-    private static final boolean DEBUG = true;
+    private static final boolean DEBUG = false;
 
     private ViewConfiguration mViewConfig;
 
diff --git a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
index fa16f8e..f2ea6a6 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/RecentsActivity.java
@@ -337,7 +337,7 @@
         getWindow().getAttributes().privateFlags |=
                 WindowManager.LayoutParams.PRIVATE_FLAG_FORCE_DECOR_VIEW_VISIBILITY;
 
-        mLastConfig = Utilities.getAppConfiguration(this);
+        mLastConfig = new Configuration(Utilities.getAppConfiguration(this));
         mFocusTimerDuration = getResources().getInteger(R.integer.recents_auto_advance_duration);
         mIterateTrigger = new DozeTrigger(mFocusTimerDuration, new Runnable() {
             @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index bf89b01..f9407dd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -77,7 +77,7 @@
     private static final int MSG_TOGGLE_APP_SPLIT_SCREEN       = 30 << MSG_SHIFT;
     private static final int MSG_APP_TRANSITION_FINISHED       = 31 << MSG_SHIFT;
     private static final int MSG_DISMISS_KEYBOARD_SHORTCUTS    = 32 << MSG_SHIFT;
-    private static final int MSG_HANDLE_SYSNAV_KEY             = 33 << MSG_SHIFT;
+    private static final int MSG_HANDLE_SYSTEM_KEY             = 33 << MSG_SHIFT;
     private static final int MSG_SHOW_GLOBAL_ACTIONS           = 34 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
@@ -134,7 +134,7 @@
         default void remQsTile(ComponentName tile) { }
         default void clickTile(ComponentName tile) { }
 
-        default void handleSystemNavigationKey(int arg1) { }
+        default void handleSystemKey(int arg1) { }
         default void handleShowGlobalActionsMenu() { }
     }
 
@@ -415,9 +415,9 @@
     }
 
     @Override
-    public void handleSystemNavigationKey(int key) {
+    public void handleSystemKey(int key) {
         synchronized (mLock) {
-            mHandler.obtainMessage(MSG_HANDLE_SYSNAV_KEY, key, 0).sendToTarget();
+            mHandler.obtainMessage(MSG_HANDLE_SYSTEM_KEY, key, 0).sendToTarget();
         }
     }
 
@@ -600,9 +600,9 @@
                         mCallbacks.get(i).toggleSplitScreen();
                     }
                     break;
-                case MSG_HANDLE_SYSNAV_KEY:
+                case MSG_HANDLE_SYSTEM_KEY:
                     for (int i = 0; i < mCallbacks.size(); i++) {
-                        mCallbacks.get(i).handleSystemNavigationKey(msg.arg1);
+                        mCallbacks.get(i).handleSystemKey(msg.arg1);
                     }
                     break;
                 case MSG_SHOW_GLOBAL_ACTIONS:
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
index ed4f685..22c0b736 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ExpandableNotificationRow.java
@@ -1973,6 +1973,9 @@
         if (mGuts != null) {
             mGuts.setActualHeight(height);
         }
+        if (mMenuRow.getMenuView() != null) {
+            mMenuRow.onHeightUpdate();
+        }
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
index 23a67e2..54d622b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationGuts.java
@@ -329,4 +329,8 @@
     public boolean isExposed() {
         return mExposed;
     }
+
+    public boolean isLeavebehind() {
+        return mGutsContent != null && mGutsContent.isLeavebehind();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
index f859124..99b4b07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationMenuRow.java
@@ -100,6 +100,7 @@
     private boolean mShouldShowMenu;
 
     private NotificationSwipeActionHelper mSwipeHelper;
+    private boolean mIsUserTouching;
 
     public NotificationMenuRow(Context context) {
         mContext = context;
@@ -202,8 +203,11 @@
         } else {
             mIconsPlaced = false;
             setMenuLocation();
-            // If the # of items showing changed we need to update the snap position
-            showMenu(mParent, mOnLeft ? getSpaceForMenu() : -getSpaceForMenu(), 0 /* velocity */);
+            if (!mIsUserTouching) {
+                // If the # of items showing changed we need to update the snap position
+                showMenu(mParent, mOnLeft ? getSpaceForMenu() : -getSpaceForMenu(),
+                        0 /* velocity */);
+            }
         }
     }
 
@@ -233,6 +237,7 @@
                 mHandler.removeCallbacks(mCheckForDrag);
                 mCheckForDrag = null;
                 mPrevX = ev.getRawX();
+                mIsUserTouching = true;
                 break;
 
             case MotionEvent.ACTION_MOVE:
@@ -265,7 +270,12 @@
                 break;
 
             case MotionEvent.ACTION_UP:
+                mIsUserTouching = false;
                 return handleUpEvent(ev, view, velocity);
+            case MotionEvent.ACTION_CANCEL:
+                mIsUserTouching = false;
+                cancelDrag();
+                return false;
         }
         return false;
     }
@@ -354,23 +364,24 @@
     }
 
     private void snapBack(View animView, float velocity) {
-        if (mFadeAnimator != null) {
-            mFadeAnimator.cancel();
-        }
-        mHandler.removeCallbacks(mCheckForDrag);
+        cancelDrag();
         mMenuSnappedTo = false;
         mSnapping = true;
         mSwipeHelper.snap(animView, 0 /* leftTarget */, velocity);
     }
 
     private void dismiss(View animView, float velocity) {
+        cancelDrag();
+        mMenuSnappedTo = false;
+        mDismissing = true;
+        mSwipeHelper.dismiss(animView, velocity);
+    }
+
+    private void cancelDrag() {
         if (mFadeAnimator != null) {
             mFadeAnimator.cancel();
         }
         mHandler.removeCallbacks(mCheckForDrag);
-        mMenuSnappedTo = false;
-        mDismissing = true;
-        mSwipeHelper.dismiss(animView, velocity);
     }
 
     /**
@@ -420,7 +431,7 @@
         if (mParent == null || mMenuItems.size() == 0 || mMenuContainer == null) {
             return;
         }
-        int parentHeight = mParent.getCollapsedHeight();
+        int parentHeight = mParent.getActualHeight();
         float translationY;
         if (parentHeight < mVertSpaceForIcons) {
             translationY = (parentHeight / 2) - (mHorizSpaceForIcon / 2);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index e5f68ad..1889806 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -244,7 +244,7 @@
             boolean aboveShelf = ViewState.getFinalTranslationZ(row) > baseZHeight;
             boolean isLastChild = child == lastChild;
             float rowTranslationY = row.getTranslationY();
-            if (isLastChild || aboveShelf || backgroundForceHidden) {
+            if ((isLastChild && !child.isInShelf()) || aboveShelf || backgroundForceHidden) {
                 notificationClipEnd = shelfStart + getIntrinsicHeight();
             } else {
                 notificationClipEnd = shelfStart - mPaddingBetweenElements;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
index cb2aa94..a53e348 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/ScrimView.java
@@ -202,8 +202,7 @@
         return mDrawable;
     }
 
-    @VisibleForTesting
-    ColorExtractor.GradientColors getColors() {
+    public ColorExtractor.GradientColors getColors() {
         return mColors;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
index f591524..2dc467f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/DozeScrimController.java
@@ -114,6 +114,7 @@
         // be invoked when we're done so that the caller can drop the pulse wakelock.
         mPulseCallback = callback;
         mPulseReason = reason;
+        mScrimController.setDozeInFrontAlpha(1f);
         mHandler.post(mPulseIn);
     }
 
@@ -290,10 +291,6 @@
 
             // Signal that the pulse is ready to turn the screen on and draw.
             pulseStarted();
-
-            if (mDozeParameters.getAlwaysOn()) {
-                mHandler.post(DozeScrimController.this::onScreenTurnedOn);
-            }
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
index 5af80f5..df059e3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/FingerprintUnlockController.java
@@ -285,7 +285,7 @@
         if (!mUpdateMonitor.isDeviceInteractive()) {
             if (!mStatusBarKeyguardViewManager.isShowing()) {
                 return MODE_ONLY_WAKE;
-            } else if (pulsingOrAod() && unlockingAllowed) {
+            } else if (mDozeScrimController.isPulsing() && unlockingAllowed) {
                 return MODE_WAKE_AND_UNLOCK_PULSING;
             } else if (unlockingAllowed || !mUnlockMethodCache.isMethodSecure()) {
                 return MODE_WAKE_AND_UNLOCK;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
index f7c2fc8..881de67 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -333,17 +333,19 @@
     }
 
     public void onOverlayChanged() {
-        @ColorInt int textColor = Utils.getColorAttr(mContext, R.attr.bgProtectTextColor);
-        mCarrierLabel.setTextColor(textColor);
-        mBatteryView.setFillColor(textColor);
-        mIconManager.setTint(textColor);
-
+        @ColorInt int textColor = Utils.getColorAttr(mContext, R.attr.wallpaperTextColor);
+        @ColorInt int iconColor = Utils.getDefaultColor(mContext, Color.luminance(textColor) < 0.5 ?
+                R.color.dark_mode_icon_color_single_tone :
+                R.color.light_mode_icon_color_single_tone);
         float intensity = textColor == Color.WHITE ? 0 : 1;
+        mCarrierLabel.setTextColor(iconColor);
+        mBatteryView.setFillColor(iconColor);
+        mIconManager.setTint(iconColor);
         Rect tintArea = new Rect(0, 0, 0, 0);
 
-        applyDarkness(R.id.signal_cluster, tintArea, intensity, textColor);
-        applyDarkness(R.id.battery, tintArea, intensity, textColor);
-        applyDarkness(R.id.clock, tintArea, intensity, textColor);
+        applyDarkness(R.id.signal_cluster, tintArea, intensity, iconColor);
+        applyDarkness(R.id.battery, tintArea, intensity, iconColor);
+        applyDarkness(R.id.clock, tintArea, intensity, iconColor);
     }
 
     private void applyDarkness(int id, Rect tintArea, float intensity, int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
index 9d699cf..917a56f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarController.java
@@ -16,11 +16,16 @@
 
 package com.android.systemui.statusbar.phone;
 
+import android.app.WallpaperColors;
+import android.content.Context;
+import android.graphics.Color;
 import android.graphics.Rect;
 import android.view.View;
 
+import com.android.internal.colorextraction.ColorExtractor.GradientColors;
 import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
+import com.android.systemui.R;
 import com.android.systemui.statusbar.policy.BatteryController;
 import com.android.systemui.statusbar.policy.DarkIconDispatcher;
 
@@ -49,6 +54,7 @@
     private boolean mDockedLight;
     private int mLastStatusBarMode;
     private int mLastNavigationBarMode;
+    private final Color mDarkModeColor;
 
     /**
      * Whether the navigation bar should be light factoring in already how much alpha the scrim has
@@ -61,12 +67,14 @@
      */
     private boolean mHasLightNavigationBar;
     private boolean mScrimAlphaBelowThreshold;
+    private boolean mInvertLightNavBarWithScrim;
     private float mScrimAlpha;
 
     private final Rect mLastFullscreenBounds = new Rect();
     private final Rect mLastDockedBounds = new Rect();
 
-    public LightBarController() {
+    public LightBarController(Context ctx) {
+        mDarkModeColor = Color.valueOf(ctx.getColor(R.color.dark_mode_icon_color_single_tone));
         mStatusBarIconController = Dependency.get(DarkIconDispatcher.class);
         mBatteryController = Dependency.get(BatteryController.class);
         mBatteryController.addCallback(this);
@@ -74,6 +82,7 @@
 
     public void setNavigationBar(LightBarTransitionsController navigationBar) {
         mNavigationBarController = navigationBar;
+        updateNavigation();
     }
 
     public void setFingerprintUnlockController(
@@ -119,7 +128,8 @@
             boolean last = mNavigationLight;
             mHasLightNavigationBar = isLight(vis, navigationBarMode,
                     View.SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR);
-            mNavigationLight = mHasLightNavigationBar && mScrimAlphaBelowThreshold;
+            mNavigationLight = mHasLightNavigationBar
+                    && (mScrimAlphaBelowThreshold || !mInvertLightNavBarWithScrim);
             if (mNavigationLight != last) {
                 updateNavigation();
             }
@@ -145,6 +155,15 @@
         }
     }
 
+    public void setScrimColor(GradientColors colors) {
+        boolean invertLightNavBarWithScrimBefore = mInvertLightNavBarWithScrim;
+        mInvertLightNavBarWithScrim = !colors.supportsDarkText();
+        if (mHasLightNavigationBar
+                && invertLightNavBarWithScrimBefore != mInvertLightNavBarWithScrim) {
+            reevaluate();
+        }
+    }
+
     private boolean isLight(int vis, int barMode, int flag) {
         boolean isTransparentBar = (barMode == MODE_TRANSPARENT
                 || barMode == MODE_LIGHTS_OUT_TRANSPARENT);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
index 6bd959f..b0ac6ec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LightBarTransitionsController.java
@@ -23,8 +23,8 @@
 import android.os.SystemClock;
 import android.util.TimeUtils;
 
-import com.android.systemui.Dumpable;
 import com.android.systemui.Dependency;
+import com.android.systemui.Dumpable;
 import com.android.systemui.Interpolators;
 import com.android.systemui.SysUiServiceProvider;
 import com.android.systemui.statusbar.CommandQueue;
@@ -55,7 +55,6 @@
     private ValueAnimator mTintAnimator;
     private float mDarkIntensity;
     private float mNextDarkIntensity;
-
     private final Runnable mTransitionDeferringDoneRunnable = new Runnable() {
         @Override
         public void run() {
@@ -130,6 +129,7 @@
     public void setIconsDark(boolean dark, boolean animate) {
         if (!animate) {
             setIconTintInternal(dark ? 1.0f : 0.0f);
+            mNextDarkIntensity = dark ? 1.0f : 0.0f;
         } else if (mTransitionPending) {
             deferIconTintChange(dark ? 1.0f : 0.0f);
         } else if (mTransitionDeferring) {
@@ -155,19 +155,19 @@
 
     private void animateIconTint(float targetDarkIntensity, long delay,
             long duration) {
+        if (mNextDarkIntensity == targetDarkIntensity) {
+            return;
+        }
         if (mTintAnimator != null) {
             mTintAnimator.cancel();
         }
-        if (mDarkIntensity == targetDarkIntensity) {
-            return;
-        }
         mNextDarkIntensity = targetDarkIntensity;
         mTintAnimator = ValueAnimator.ofFloat(mDarkIntensity, targetDarkIntensity);
         mTintAnimator.addUpdateListener(
                 animation -> setIconTintInternal((Float) animation.getAnimatedValue()));
         mTintAnimator.setDuration(duration);
         mTintAnimator.setStartDelay(delay);
-        mTintAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
+        mTintAnimator.setInterpolator(Interpolators.LINEAR_OUT_SLOW_IN);
         mTintAnimator.start();
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
index 6d3fcff..62d4b73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/ScrimController.java
@@ -102,6 +102,7 @@
     protected long mDurationOverride = -1;
     private long mAnimationDelay;
     private Runnable mOnAnimationFinished;
+    private boolean mDeferFinishedListener;
     private final Interpolator mInterpolator = new DecelerateInterpolator();
     private boolean mDozing;
     private float mDozeInFrontAlpha;
@@ -118,6 +119,12 @@
     private boolean mKeyguardFadingOutInProgress;
     private boolean mAnimatingDozeUnlock;
     private ValueAnimator mKeyguardFadeoutAnimation;
+    /** Wake up from AOD transition is starting; need fully opaque front scrim */
+    private boolean mWakingUpFromAodStarting;
+    /** Wake up from AOD transition is in progress; need black tint */
+    private boolean mWakingUpFromAodInProgress;
+    /** Wake up from AOD transition is animating; need to reset when animation finishes */
+    private boolean mWakingUpFromAodAnimationRunning;
 
     public ScrimController(LightBarController lightBarController, ScrimView scrimBehind,
             ScrimView scrimInFront, View headsUpScrim) {
@@ -185,9 +192,32 @@
         scheduleUpdate();
     }
 
+    public void prepareWakeUpFromAod() {
+        mWakingUpFromAodInProgress = true;
+        mWakingUpFromAodStarting = true;
+        mAnimateChange = false;
+        scheduleUpdate();
+        onPreDraw();
+    }
+
+    public void wakeUpFromAod() {
+        if (mWakeAndUnlocking || mAnimateKeyguardFadingOut) {
+            // Wake and unlocking has a separate transition that must not be interfered with.
+            mWakingUpFromAodStarting = false;
+            return;
+        }
+        if (mWakingUpFromAodStarting) {
+            mWakingUpFromAodInProgress = true;
+            mWakingUpFromAodStarting = false;
+            mAnimateChange = true;
+            scheduleUpdate();
+        }
+    }
+
     public void setWakeAndUnlocking() {
         mWakeAndUnlocking = true;
         mAnimatingDozeUnlock = true;
+        mWakingUpFromAodStarting = false;
         scheduleUpdate();
     }
 
@@ -313,6 +343,7 @@
                 mScrimInFront.setColors(mSystemColors, animateScrimInFront);
                 mScrimBehind.setColors(mSystemColors, animateScrimBehind);
             }
+            mLightBarController.setScrimColor(mScrimInFront.getColors());
         }
 
         if (mAnimateKeyguardFadingOut || mForceHideScrims) {
@@ -353,7 +384,11 @@
             setScrimBehindAlpha(mScrimBehindAlpha);
         } else {
             float fraction = Math.max(0, Math.min(mFraction, 1));
-            setScrimInFrontAlpha(0f);
+            if (mWakingUpFromAodStarting) {
+                setScrimInFrontAlpha(1f);
+            } else {
+                setScrimInFrontAlpha(0f);
+            }
             setScrimBehindAlpha(fraction
                     * (mScrimBehindAlphaKeyguard - mScrimBehindAlphaUnlocking)
                     + mScrimBehindAlphaUnlocking);
@@ -423,7 +458,10 @@
             scrimView.setViewAlpha(alpha);
 
             int dozeTint = Color.TRANSPARENT;
-            if (mAnimatingDozeUnlock || mDozing) {
+
+            boolean dozing = mAnimatingDozeUnlock || mDozing;
+            boolean frontScrimDozing = mWakingUpFromAodInProgress;
+            if (dozing || frontScrimDozing && scrim == mScrimInFront) {
                 dozeTint = Color.BLACK;
             }
             scrimView.setTint(dozeTint);
@@ -446,7 +484,7 @@
         anim.addListener(new AnimatorListenerAdapter() {
             @Override
             public void onAnimationEnd(Animator animation) {
-                if (mOnAnimationFinished != null) {
+                if (!mDeferFinishedListener && mOnAnimationFinished != null) {
                     mOnAnimationFinished.run();
                     mOnAnimationFinished = null;
                 }
@@ -455,6 +493,10 @@
                     mKeyguardFadingOutInProgress = false;
                     mAnimatingDozeUnlock = false;
                 }
+                if (mWakingUpFromAodAnimationRunning) {
+                    mWakingUpFromAodAnimationRunning = false;
+                    mWakingUpFromAodInProgress = false;
+                }
                 scrim.setTag(TAG_KEY_ANIM, null);
                 scrim.setTag(TAG_KEY_ANIM_TARGET, null);
             }
@@ -464,6 +506,9 @@
             mKeyguardFadingOutInProgress = true;
             mKeyguardFadeoutAnimation = anim;
         }
+        if (mWakingUpFromAodInProgress) {
+            mWakingUpFromAodAnimationRunning = true;
+        }
         if (mSkipFirstFrame) {
             anim.setCurrentPlayTime(16);
         }
@@ -557,7 +602,12 @@
         float animEndValue = -1;
         if (previousAnimator != null) {
             if (animate || alpha == currentAlpha) {
+                // We are not done yet! Defer calling the finished listener.
+                if (animate) {
+                    mDeferFinishedListener = true;
+                }
                 previousAnimator.cancel();
+                mDeferFinishedListener = false;
             } else {
                 animEndValue = ViewState.getChildTag(scrim, TAG_END_ALPHA);
             }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index a11af51..75a2768 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -21,6 +21,9 @@
 import static android.app.StatusBarManager.windowStateToString;
 import static android.content.res.Configuration.UI_MODE_TYPE_CAR;
 
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_ASLEEP;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_AWAKE;
+import static com.android.systemui.keyguard.WakefulnessLifecycle.WAKEFULNESS_WAKING;
 import static com.android.systemui.statusbar.notification.NotificationInflater.InflationCallback;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT;
 import static com.android.systemui.statusbar.phone.BarTransitions.MODE_LIGHTS_OUT_TRANSPARENT;
@@ -102,6 +105,7 @@
 import android.os.UserManager;
 import android.os.Vibrator;
 import android.provider.Settings;
+import android.service.notification.NotificationListenerService;
 import android.service.notification.NotificationListenerService.RankingMap;
 import android.service.notification.StatusBarNotification;
 import android.service.vr.IVrManager;
@@ -174,6 +178,8 @@
 import com.android.systemui.fragments.ExtensionFragmentListener;
 import com.android.systemui.fragments.FragmentHostManager;
 import com.android.systemui.keyguard.KeyguardViewMediator;
+import com.android.systemui.keyguard.ScreenLifecycle;
+import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.qs.QS;
 import com.android.systemui.plugins.statusbar.NotificationMenuRowPlugin.MenuItem;
@@ -421,8 +427,6 @@
     private DozeServiceHost mDozeServiceHost;
     private boolean mWakeUpComingFromTouch;
     private PointF mWakeUpTouchLocation;
-    private boolean mScreenTurningOn;
-    private boolean mScreenFullyOff;
 
     int mPixelFormat;
     Object mQueueLock = new Object();
@@ -562,7 +566,7 @@
         }};
 
     private boolean mWaitingForKeyguardExit;
-    private boolean mDozing;
+    protected boolean mDozing;
     private boolean mDozingRequested;
     protected boolean mScrimSrcModeEnabled;
 
@@ -633,11 +637,6 @@
     // Fingerprint (as computed by getLoggingFingerprint() of the last logged state.
     private int mLastLoggedStateFingerprint;
 
-    /**
-     * If set, the device has started going to sleep but isn't fully non-interactive yet.
-     */
-    protected boolean mStartedGoingToSleep;
-
     private final OnChildLocationsChangedListener mNotificationLocationsChangedListener =
             new OnChildLocationsChangedListener() {
                 @Override
@@ -736,6 +735,8 @@
     private String mKeyToRemoveOnGutsClosed;
     private SysuiColorExtractor mColorExtractor;
     private ForegroundServiceController mForegroundServiceController;
+    private ScreenLifecycle mScreenLifecycle;
+    private WakefulnessLifecycle mWakefulnessLifecycle;
 
     private void recycleAllVisibilityObjects(ArraySet<NotificationVisibility> array) {
         final int N = array.size();
@@ -774,6 +775,10 @@
         mNetworkController = Dependency.get(NetworkController.class);
         mUserSwitcherController = Dependency.get(UserSwitcherController.class);
         mKeyguardMonitor = (KeyguardMonitorImpl) Dependency.get(KeyguardMonitor.class);
+        mScreenLifecycle = Dependency.get(ScreenLifecycle.class);
+        mScreenLifecycle.addObserver(mScreenObserver);
+        mWakefulnessLifecycle = Dependency.get(WakefulnessLifecycle.class);
+        mWakefulnessLifecycle.addObserver(mWakefulnessObserver);
         mBatteryController = Dependency.get(BatteryController.class);
         mAssistManager = Dependency.get(AssistManager.class);
         mDeviceProvisionedController = Dependency.get(DeviceProvisionedController.class);
@@ -1108,7 +1113,7 @@
             }
         });
 
-        mLightBarController = new LightBarController();
+        mLightBarController = new LightBarController(context);
         if (mNavigationBar != null) {
             mNavigationBar.setLightBarController(mLightBarController);
         }
@@ -1789,7 +1794,8 @@
             return;
         }
         if (entry != null && mNotificationGutsExposed != null
-                && mNotificationGutsExposed == entry.row.getGuts()) {
+                && mNotificationGutsExposed == entry.row.getGuts() && entry.row.getGuts() != null
+                && !entry.row.getGuts().isLeavebehind()) {
             Log.w(TAG, "Keeping notification because it's showing guts. " + key);
             mLatestRankingMap = ranking;
             mKeyToRemoveOnGutsClosed = key;
@@ -1924,9 +1930,6 @@
             boolean sensitive = userPublic && needsRedaction;
             boolean deviceSensitive = devicePublic
                     && !userAllowsPrivateNotificationsInPublic(mCurrentUserId);
-            if (sensitive) {
-                updatePublicContentView(ent, ent.notification);
-            }
             ent.row.setSensitive(sensitive, deviceSensitive);
             ent.row.setNeedsRedaction(needsRedaction);
             if (mGroupManager.isChildInGroupWithSummary(ent.row.getStatusBarNotification())) {
@@ -2828,12 +2831,6 @@
         mRemoteInputEntriesToRemoveOnCollapse.clear();
     }
 
-    public void onScreenTurnedOff() {
-        mScreenFullyOff = true;
-        mFalsingManager.onScreenOff();
-        updateIsKeyguard();
-    }
-
     public NotificationStackScrollLayout getNotificationScrollLayout() {
         return mStackScroller;
     }
@@ -2943,8 +2940,8 @@
      * settings. Down action closes the entire panel.
      */
     @Override
-    public void handleSystemNavigationKey(int key) {
-        if (SPEW) Log.d(TAG, "handleSystemNavigationKey: " + key);
+    public void handleSystemKey(int key) {
+        if (SPEW) Log.d(TAG, "handleNavigationKey: " + key);
         if (!panelsEnabled() || !mKeyguardMonitor.isDeviceInteractive()
                 || mKeyguardMonitor.isShowing() && !mKeyguardMonitor.isOccluded()) {
             return;
@@ -4202,10 +4199,7 @@
 
     public void showKeyguard() {
         mKeyguardRequested = true;
-        // Unconditionally show keyguard again. There's some logic that relies on this
-        // being called even when the keyguard is already showing, e.g. for updating
-        // sensitiveness of notifications and making sure the panels are expanded.
-        showKeyguardImpl();
+        updateIsKeyguard();
     }
 
     public boolean hideKeyguard() {
@@ -4214,18 +4208,26 @@
     }
 
     private boolean updateIsKeyguard() {
+        boolean wakeAndUnlocking = mFingerprintUnlockController.getMode()
+                == FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+
         // For dozing, keyguard needs to be shown whenever the device is non-interactive. Otherwise
         // there's no surface we can show to the user. Note that the device goes fully interactive
         // late in the transition, so we also allow the device to start dozing once the screen has
         // turned off fully.
         boolean keyguardForDozing = mDozingRequested &&
-                (!mDeviceInteractive || mStartedGoingToSleep && (mScreenFullyOff || mIsKeyguard));
-        boolean shouldBeKeyguard = mKeyguardRequested || keyguardForDozing;
+                (!mDeviceInteractive || isGoingToSleep() && (isScreenFullyOff() || mIsKeyguard));
+        boolean shouldBeKeyguard = (mKeyguardRequested || keyguardForDozing) && !wakeAndUnlocking;
         if (keyguardForDozing) {
             updatePanelExpansionForKeyguard();
         }
         if (shouldBeKeyguard) {
-            showKeyguardImpl();
+            if (isGoingToSleep()
+                    && mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_OFF) {
+                // Delay showing the keyguard until screen turned off.
+            } else {
+                showKeyguardImpl();
+            }
         } else {
             return hideKeyguardImpl();
         }
@@ -4257,7 +4259,8 @@
     }
 
     private void updatePanelExpansionForKeyguard() {
-        if (mState == StatusBarState.KEYGUARD) {
+        if (mState == StatusBarState.KEYGUARD && mFingerprintUnlockController.getMode()
+                != FingerprintUnlockController.MODE_WAKE_AND_UNLOCK) {
             instantExpandNotificationsPanel();
         } else if (mState == StatusBarState.FULLSCREEN_USER_SWITCHER) {
             instantCollapseNotificationPanel();
@@ -5108,78 +5111,96 @@
         recomputeDisableFlags(true /* animate */);
     }
 
-    public void onStartedGoingToSleep() {
-        mStartedGoingToSleep = true;
-    }
-
-    public void onFinishedGoingToSleep() {
-        mNotificationPanel.onAffordanceLaunchEnded();
-        releaseGestureWakeLock();
-        mLaunchCameraOnScreenTurningOn = false;
-        mStartedGoingToSleep = false;
-        mDeviceInteractive = false;
-        mWakeUpComingFromTouch = false;
-        mWakeUpTouchLocation = null;
-        mStackScroller.setAnimationsEnabled(false);
-        mVisualStabilityManager.setScreenOn(false);
-        updateVisibleToUser();
-
-        // We need to disable touch events because these might
-        // collapse the panel after we expanded it, and thus we would end up with a blank
-        // Keyguard.
-        mNotificationPanel.setTouchDisabled(true);
-        mStatusBarWindow.cancelCurrentTouch();
-        if (mLaunchCameraOnFinishedGoingToSleep) {
-            mLaunchCameraOnFinishedGoingToSleep = false;
-
-            // This gets executed before we will show Keyguard, so post it in order that the state
-            // is correct.
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    onCameraLaunchGestureDetected(mLastCameraLaunchSource);
-                }
-            });
-        }
-        updateIsKeyguard();
-    }
-
-    public void onStartedWakingUp() {
-        mDeviceInteractive = true;
-        mStackScroller.setAnimationsEnabled(true);
-        mVisualStabilityManager.setScreenOn(true);
-        mNotificationPanel.setTouchDisabled(false);
-        updateVisibleToUser();
-        updateIsKeyguard();
-    }
-
-    public void onScreenTurningOn() {
-        mScreenFullyOff = false;
-        mScreenTurningOn = true;
-        mFalsingManager.onScreenTurningOn();
-        mNotificationPanel.onScreenTurningOn();
-        if (mLaunchCameraOnScreenTurningOn) {
-            mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
+    WakefulnessLifecycle.Observer mWakefulnessObserver = new WakefulnessLifecycle.Observer() {
+        @Override
+        public void onFinishedGoingToSleep() {
+            mNotificationPanel.onAffordanceLaunchEnded();
+            releaseGestureWakeLock();
             mLaunchCameraOnScreenTurningOn = false;
+            mDeviceInteractive = false;
+            mWakeUpComingFromTouch = false;
+            mWakeUpTouchLocation = null;
+            mStackScroller.setAnimationsEnabled(false);
+            mVisualStabilityManager.setScreenOn(false);
+            updateVisibleToUser();
+
+            // We need to disable touch events because these might
+            // collapse the panel after we expanded it, and thus we would end up with a blank
+            // Keyguard.
+            mNotificationPanel.setTouchDisabled(true);
+            mStatusBarWindow.cancelCurrentTouch();
+            if (mLaunchCameraOnFinishedGoingToSleep) {
+                mLaunchCameraOnFinishedGoingToSleep = false;
+
+                // This gets executed before we will show Keyguard, so post it in order that the state
+                // is correct.
+                mHandler.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        onCameraLaunchGestureDetected(mLastCameraLaunchSource);
+                    }
+                });
+            }
+            updateIsKeyguard();
         }
-    }
+
+        @Override
+        public void onStartedWakingUp() {
+            mDeviceInteractive = true;
+            mStackScroller.setAnimationsEnabled(true);
+            mVisualStabilityManager.setScreenOn(true);
+            mNotificationPanel.setTouchDisabled(false);
+            updateVisibleToUser();
+            updateIsKeyguard();
+        }
+    };
+
+    ScreenLifecycle.Observer mScreenObserver = new ScreenLifecycle.Observer() {
+        @Override
+        public void onScreenTurningOn() {
+            mFalsingManager.onScreenTurningOn();
+            mNotificationPanel.onScreenTurningOn();
+
+            int wakefulness = mWakefulnessLifecycle.getWakefulness();
+            if (mDozing && (wakefulness == WAKEFULNESS_WAKING
+                    || wakefulness == WAKEFULNESS_ASLEEP) && !isPulsing()) {
+                mScrimController.prepareWakeUpFromAod();
+            }
+
+            if (mLaunchCameraOnScreenTurningOn) {
+                mNotificationPanel.launchCamera(false, mLastCameraLaunchSource);
+                mLaunchCameraOnScreenTurningOn = false;
+            }
+        }
+
+        @Override
+        public void onScreenTurnedOn() {
+            mScrimController.wakeUpFromAod();
+            mDozeScrimController.onScreenTurnedOn();
+        }
+
+        @Override
+        public void onScreenTurnedOff() {
+            mFalsingManager.onScreenOff();
+            // If we pulse in from AOD, we turn the screen off first. However, updatingIsKeyguard
+            // in that case destroys the HeadsUpManager state, so don't do it in that case.
+            if (!isPulsing()) {
+                updateIsKeyguard();
+            }
+        }
+    };
 
     private void vibrateForCameraGesture() {
         // Make sure to pass -1 for repeat so VibratorService doesn't stop us when going to sleep.
         mVibrator.vibrate(mCameraLaunchGestureVibePattern, -1 /* repeat */);
     }
 
-    public void onScreenTurnedOn() {
-        mScreenTurningOn = false;
-        mDozeScrimController.onScreenTurnedOn();
-    }
-
     /**
      * @return true if the screen is currently fully off, i.e. has finished turning off and has
      *         since not started turning on.
      */
     public boolean isScreenFullyOff() {
-        return mScreenFullyOff;
+        return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_OFF;
     }
 
     @Override
@@ -5226,7 +5247,7 @@
     @Override
     public void onCameraLaunchGestureDetected(int source) {
         mLastCameraLaunchSource = source;
-        if (mStartedGoingToSleep) {
+        if (isGoingToSleep()) {
             if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Finish going to sleep before launching camera");
             mLaunchCameraOnFinishedGoingToSleep = true;
             return;
@@ -5253,7 +5274,7 @@
                 mScrimController.dontAnimateBouncerChangesUntilNextFrame();
                 mGestureWakeLock.acquire(LAUNCH_TRANSITION_TIMEOUT_MS + 1000L);
             }
-            if (mScreenTurningOn || mStatusBarKeyguardViewManager.isScreenTurnedOn()) {
+            if (isScreenTurningOnOrOn()) {
                 if (DEBUG_CAMERA_LIFT) Slog.d(TAG, "Launching camera");
                 mNotificationPanel.launchCamera(mDeviceInteractive /* animate */, source);
             } else {
@@ -5279,6 +5300,16 @@
         return true;
     }
 
+    private boolean isGoingToSleep() {
+        return mWakefulnessLifecycle.getWakefulness()
+                == WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP;
+    }
+
+    private boolean isScreenTurningOnOrOn() {
+        return mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_TURNING_ON
+                || mScreenLifecycle.getScreenState() == ScreenLifecycle.SCREEN_ON;
+    }
+
     public void notifyFpAuthModeChanged() {
         updateDozing();
     }
@@ -7182,24 +7213,6 @@
         setAreThereNotifications();
     }
 
-    protected void updatePublicContentView(Entry entry,
-            StatusBarNotification sbn) {
-        final RemoteViews publicContentView = entry.cachedPublicContentView;
-        View inflatedView = entry.getPublicContentView();
-        if (entry.autoRedacted && publicContentView != null && inflatedView != null) {
-            final boolean disabledByPolicy =
-                    !adminAllowsUnredactedNotifications(entry.notification.getUserId());
-            String notificationHiddenText = mContext.getString(disabledByPolicy
-                    ? com.android.internal.R.string.notification_hidden_by_policy_text
-                    : com.android.internal.R.string.notification_hidden_text);
-            TextView titleView = (TextView) inflatedView.findViewById(android.R.id.title);
-            if (titleView != null
-                    && !titleView.getText().toString().equals(notificationHiddenText)) {
-                titleView.setText(notificationHiddenText);
-            }
-        }
-    }
-
     protected void notifyHeadsUpScreenOff() {
         maybeEscalateHeadsUp();
     }
@@ -7233,7 +7246,12 @@
             return false;
         }
 
-        if (mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
+        if (!isDozing() && mNotificationData.shouldSuppressScreenOn(sbn.getKey())) {
+            if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
+            return false;
+        }
+
+        if (isDozing() && mNotificationData.shouldSuppressScreenOff(sbn.getKey())) {
             if (DEBUG) Log.d(TAG, "No peeking: suppressed by DND: " + sbn.getKey());
             return false;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index be338de..252df17 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -16,6 +16,10 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static com.android.keyguard.KeyguardHostView.OnDismissAction;
+import static com.android.systemui.statusbar.phone.FingerprintUnlockController.MODE_WAKE_AND_UNLOCK;
+import static com.android.systemui.statusbar.phone.FingerprintUnlockController.MODE_WAKE_AND_UNLOCK_PULSING;
+
 import android.content.ComponentCallbacks2;
 import android.content.Context;
 import android.os.Bundle;
@@ -30,18 +34,15 @@
 import com.android.internal.widget.LockPatternUtils;
 import com.android.keyguard.KeyguardUpdateMonitor;
 import com.android.keyguard.KeyguardUpdateMonitorCallback;
+import com.android.keyguard.LatencyTracker;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.DejankUtils;
-import com.android.keyguard.LatencyTracker;
 import com.android.systemui.Dependency;
 import com.android.systemui.SystemUIFactory;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.RemoteInputController;
 
-import static com.android.keyguard.KeyguardHostView.OnDismissAction;
-import static com.android.systemui.statusbar.phone.FingerprintUnlockController.*;
-
 import java.util.ArrayList;
 
 /**
@@ -79,7 +80,6 @@
 
     private ViewGroup mContainer;
 
-    private boolean mDeviceInteractive = false;
     private boolean mScreenTurnedOn;
     protected KeyguardBouncer mBouncer;
     protected boolean mShowing;
@@ -95,10 +95,10 @@
     protected boolean mLastRemoteInputActive;
     private boolean mLastDozing;
     private boolean mLastDeferScrimFadeOut;
+    private int mLastFpMode;
 
     private OnDismissAction mAfterKeyguardGoneAction;
     private final ArrayList<Runnable> mAfterKeyguardGoneRunnables = new ArrayList<>();
-    private boolean mDeviceWillWakeUp;
     private boolean mDeferScrimFadeOut;
 
     private final KeyguardUpdateMonitorCallback mUpdateMonitorCallback =
@@ -211,31 +211,19 @@
     }
 
     public void onStartedGoingToSleep() {
-        mStatusBar.onStartedGoingToSleep();
+        // TODO: remove
     }
 
     public void onFinishedGoingToSleep() {
-        mDeviceInteractive = false;
-        mStatusBar.onFinishedGoingToSleep();
         mBouncer.onScreenTurnedOff();
     }
 
     public void onStartedWakingUp() {
-        Trace.beginSection("StatusBarKeyguardViewManager#onStartedWakingUp");
-        mDeviceInteractive = true;
-        mDeviceWillWakeUp = false;
-        mStatusBar.onStartedWakingUp();
-        Trace.endSection();
+        // TODO: remove
     }
 
     public void onScreenTurningOn() {
-        Trace.beginSection("StatusBarKeyguardViewManager#onScreenTurningOn");
-        mStatusBar.onScreenTurningOn();
-        Trace.endSection();
-    }
-
-    public boolean isScreenTurnedOn() {
-        return mScreenTurnedOn;
+        // TODO: remove
     }
 
     public void onScreenTurnedOn() {
@@ -247,7 +235,6 @@
                     true /* skipFirstFrame */);
             updateStates();
         }
-        mStatusBar.onScreenTurnedOn();
         Trace.endSection();
     }
 
@@ -267,11 +254,10 @@
 
     public void onScreenTurnedOff() {
         mScreenTurnedOn = false;
-        mStatusBar.onScreenTurnedOff();
     }
 
     public void notifyDeviceWakeUpRequested() {
-        mDeviceWillWakeUp = !mDeviceInteractive;
+        // TODO: remove
     }
 
     public void setNeedsInput(boolean needsInput) {
@@ -583,6 +569,7 @@
         mLastRemoteInputActive = remoteInputActive;
         mLastDozing = mDozing;
         mLastDeferScrimFadeOut = mDeferScrimFadeOut;
+        mLastFpMode = mFingerprintUnlockController.getMode();
         mStatusBar.onKeyguardViewManagerStatesUpdated();
     }
 
@@ -590,15 +577,20 @@
      * @return Whether the navigation bar should be made visible based on the current state.
      */
     protected boolean isNavBarVisible() {
-        return (!(mShowing && !mOccluded) && !mDozing || mBouncer.isShowing() || mRemoteInputActive)
-                && !mDeferScrimFadeOut;
+        int fpMode = mFingerprintUnlockController.getMode();
+        boolean keyguardShowing = mShowing && !mOccluded;
+        boolean hideWhileDozing = mDozing && fpMode != MODE_WAKE_AND_UNLOCK_PULSING;
+        return (!keyguardShowing && !hideWhileDozing || mBouncer.isShowing()
+                || mRemoteInputActive) && !mDeferScrimFadeOut;
     }
 
     /**
      * @return Whether the navigation bar was made visible based on the last known state.
      */
     protected boolean getLastNavBarVisible() {
-        return (!(mLastShowing && !mLastOccluded) && !mLastDozing || mLastBouncerShowing
+        boolean keyguardShowing = mLastShowing && !mLastOccluded;
+        boolean hideWhileDozing = mLastDozing && mLastFpMode != MODE_WAKE_AND_UNLOCK_PULSING;
+        return (!keyguardShowing && !hideWhileDozing || mLastBouncerShowing
                 || mLastRemoteInputActive) && !mLastDeferScrimFadeOut;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
index e8a456e..028da86 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/TrustDrawable.java
@@ -83,7 +83,7 @@
 
         mPaint = new Paint();
         mPaint.setStyle(Paint.Style.STROKE);
-        mPaint.setColor(Utils.getColorAttr(context, R.attr.bgProtectTextColor));
+        mPaint.setColor(Utils.getColorAttr(context, R.attr.wallpaperTextColor));
         mPaint.setAntiAlias(true);
         mPaint.setStrokeWidth(mThickness);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
index b89a77b..2bf62bb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/CastControllerImpl.java
@@ -182,7 +182,7 @@
                 Log.w(TAG, "Projection is no longer active: " + projection);
             }
         } else {
-            mMediaRouter.getDefaultRoute().select();
+            mMediaRouter.getFallbackRoute().select();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
index 728005d..ccfbb26 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/KeyguardMonitor.java
@@ -21,12 +21,13 @@
     boolean isSecure();
     boolean canSkipBouncer();
     boolean isShowing();
+    boolean isOccluded();
     boolean isKeyguardFadingAway();
     boolean isKeyguardGoingAway();
     long getKeyguardFadingAwayDuration();
     long getKeyguardFadingAwayDelay();
 
-    public interface Callback {
+    interface Callback {
         void onKeyguardShowingChanged();
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
index 0097391..42cebe2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/stack/NotificationStackScrollLayout.java
@@ -369,6 +369,7 @@
     private NotificationShelf mShelf;
     private int mMaxDisplayedNotifications = -1;
     private int mStatusBarHeight;
+    private int mMinInteractionHeight;
     private boolean mNoAmbient;
     private final Rect mClipRect = new Rect();
     private boolean mIsClipped;
@@ -517,6 +518,8 @@
                 R.dimen.min_top_overscroll_to_qs);
         mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
         mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
+        mMinInteractionHeight = res.getDimensionPixelSize(
+                R.dimen.notification_min_interaction_height);
     }
 
     public void setDrawBackgroundAsSrc(boolean asSrc) {
@@ -1079,7 +1082,7 @@
         final int count = getChildCount();
         for (int childIdx = 0; childIdx < count; childIdx++) {
             ExpandableView slidingChild = (ExpandableView) getChildAt(childIdx);
-            if (slidingChild.getVisibility() == GONE
+            if (slidingChild.getVisibility() != VISIBLE
                     || slidingChild instanceof StackScrollerDecorView) {
                 continue;
             }
@@ -1093,7 +1096,8 @@
             int left = 0;
             int right = getWidth();
 
-            if (touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
+            if (bottom - top >= mMinInteractionHeight
+                    && touchY >= top && touchY <= bottom && touchX >= left && touchX <= right) {
                 if (slidingChild instanceof ExpandableNotificationRow) {
                     ExpandableNotificationRow row = (ExpandableNotificationRow) slidingChild;
                     if (!mIsExpanded && row.isHeadsUp() && row.isPinned()
@@ -2005,6 +2009,7 @@
         }
         mContentHeight = height + mTopPadding + mBottomMargin;
         updateScrollability();
+        clampScrollPosition();
         mAmbientState.setLayoutMaxHeight(mContentHeight);
     }
 
@@ -3463,7 +3468,7 @@
     }
 
     private void updateScrollPositionOnExpandInBottom(ExpandableView view) {
-        if (view instanceof ExpandableNotificationRow) {
+        if (view instanceof ExpandableNotificationRow && !onKeyguard()) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) view;
             if (row.isUserLocked() && row != getFirstChildNotGone()) {
                 if (row.isSummaryWithChildren()) {
@@ -4344,10 +4349,10 @@
         @Override
         public void onDownUpdate(View currView, MotionEvent ev) {
             mTranslatingParentView = currView;
-            mCurrMenuRow = null;
             if (mCurrMenuRow != null) {
                 mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
             }
+            mCurrMenuRow = null;
             mHandler.removeCallbacks(mFalsingCheck);
 
             // Slide back any notifications that might be showing a menu
@@ -4358,6 +4363,7 @@
                 mCurrMenuRow = row.createMenu();
                 mCurrMenuRow.setSwipeActionHelper(NotificationSwipeHelper.this);
                 mCurrMenuRow.setMenuClickListener(NotificationStackScrollLayout.this);
+                mCurrMenuRow.onTouchEvent(currView, ev, 0 /* velocity */);
             }
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
index 203876b..e54c792 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/doze/DozeScreenStateTest.java
@@ -86,13 +86,13 @@
     }
 
     @Test
-    public void testScreen_onInRequestPulseWithAoD() {
+    public void testScreen_offInRequestPulseWithAoD() {
         mScreen.transitionTo(UNINITIALIZED, INITIALIZED);
         mScreen.transitionTo(INITIALIZED, DOZE_AOD);
 
         mScreen.transitionTo(DOZE, DOZE_REQUEST_PULSE);
 
-        assertEquals(Display.STATE_DOZE_SUSPEND, mServiceFake.screenState);
+        assertEquals(Display.STATE_OFF, mServiceFake.screenState);
     }
 
 }
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LifecycleTest.java
new file mode 100644
index 0000000..e0807d6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LifecycleTest.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.util.ArrayList;
+
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class LifecycleTest extends SysuiTestCase {
+
+    private final Object mObj1 = new Object();
+    private final Object mObj2 = new Object();
+
+    private Lifecycle<Object> mLifecycle;
+    private ArrayList<Object> mDispatchedObjects;
+
+    @Before
+    public void setUp() throws Exception {
+        mLifecycle = new Lifecycle<>();
+        mDispatchedObjects = new ArrayList<>();
+    }
+
+    @Test
+    public void addObserver_addsObserver() throws Exception {
+        mLifecycle.addObserver(mObj1);
+
+        mLifecycle.dispatch(mDispatchedObjects::add);
+
+        assertTrue(mDispatchedObjects.contains(mObj1));
+    }
+
+    @Test
+    public void removeObserver() throws Exception {
+        mLifecycle.addObserver(mObj1);
+        mLifecycle.removeObserver(mObj1);
+
+        mLifecycle.dispatch(mDispatchedObjects::add);
+
+        assertFalse(mDispatchedObjects.contains(mObj1));
+    }
+
+    @Test
+    public void dispatch() throws Exception {
+        mLifecycle.addObserver(mObj1);
+        mLifecycle.addObserver(mObj2);
+
+        mLifecycle.dispatch(mDispatchedObjects::add);
+
+        assertTrue(mDispatchedObjects.contains(mObj1));
+        assertTrue(mDispatchedObjects.contains(mObj2));
+    }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
new file mode 100644
index 0000000..8c918f6
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ScreenLifecycleTest.java
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class ScreenLifecycleTest extends SysuiTestCase {
+
+    private ScreenLifecycle mScreen;
+    private ScreenLifecycle.Observer mScreenObserverMock;
+
+    @Before
+    public void setUp() throws Exception {
+        mScreen = new ScreenLifecycle();
+        mScreenObserverMock = mock(ScreenLifecycle.Observer.class);
+        mScreen.addObserver(mScreenObserverMock);
+    }
+
+    @Test
+    public void baseState() throws Exception {
+        assertEquals(ScreenLifecycle.SCREEN_OFF, mScreen.getScreenState());
+        verifyNoMoreInteractions(mScreenObserverMock);
+    }
+
+    @Test
+    public void screenTurningOn() throws Exception {
+        mScreen.dispatchScreenTurningOn();
+
+        assertEquals(ScreenLifecycle.SCREEN_TURNING_ON, mScreen.getScreenState());
+        verify(mScreenObserverMock).onScreenTurningOn();
+    }
+
+    @Test
+    public void screenTurnedOn() throws Exception {
+        mScreen.dispatchScreenTurningOn();
+        mScreen.dispatchScreenTurnedOn();
+
+        assertEquals(ScreenLifecycle.SCREEN_ON, mScreen.getScreenState());
+        verify(mScreenObserverMock).onScreenTurnedOn();
+    }
+
+    @Test
+    public void screenTurningOff() throws Exception {
+        mScreen.dispatchScreenTurningOn();
+        mScreen.dispatchScreenTurnedOn();
+        mScreen.dispatchScreenTurningOff();
+
+        assertEquals(ScreenLifecycle.SCREEN_TURNING_OFF, mScreen.getScreenState());
+        verify(mScreenObserverMock).onScreenTurningOff();
+    }
+
+    @Test
+    public void screenTurnedOff() throws Exception {
+        mScreen.dispatchScreenTurningOn();
+        mScreen.dispatchScreenTurnedOn();
+        mScreen.dispatchScreenTurningOff();
+        mScreen.dispatchScreenTurnedOff();
+
+        assertEquals(ScreenLifecycle.SCREEN_OFF, mScreen.getScreenState());
+        verify(mScreenObserverMock).onScreenTurnedOff();
+    }
+
+    @Test
+    public void dump() throws Exception {
+        mScreen.dump(null, new PrintWriter(new ByteArrayOutputStream()), new String[0]);
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
new file mode 100644
index 0000000..e15e0b4
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/WakefulnessLifecycleTest.java
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2017 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.keyguard;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+
+import android.support.test.filters.SmallTest;
+import android.testing.AndroidTestingRunner;
+
+import com.android.systemui.SysuiTestCase;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+@RunWith(AndroidTestingRunner.class)
+@SmallTest
+public class WakefulnessLifecycleTest extends SysuiTestCase {
+
+    private WakefulnessLifecycle mWakefulness;
+    private WakefulnessLifecycle.Observer mWakefulnessObserver;
+
+    @Before
+    public void setUp() throws Exception {
+        mWakefulness = new WakefulnessLifecycle();
+        mWakefulnessObserver = mock(WakefulnessLifecycle.Observer.class);
+        mWakefulness.addObserver(mWakefulnessObserver);
+    }
+
+    @Test
+    public void baseState() throws Exception {
+        assertEquals(WakefulnessLifecycle.WAKEFULNESS_ASLEEP, mWakefulness.getWakefulness());
+
+        verifyNoMoreInteractions(mWakefulnessObserver);
+    }
+
+    @Test
+    public void dispatchStartedWakingUp() throws Exception {
+        mWakefulness.dispatchStartedWakingUp();
+
+        assertEquals(WakefulnessLifecycle.WAKEFULNESS_WAKING, mWakefulness.getWakefulness());
+
+        verify(mWakefulnessObserver).onStartedWakingUp();
+    }
+
+    @Test
+    public void dispatchFinishedWakingUp() throws Exception {
+        mWakefulness.dispatchStartedWakingUp();
+        mWakefulness.dispatchFinishedWakingUp();
+
+        assertEquals(WakefulnessLifecycle.WAKEFULNESS_AWAKE, mWakefulness.getWakefulness());
+
+        verify(mWakefulnessObserver).onFinishedWakingUp();
+    }
+
+    @Test
+    public void dispatchStartedGoingToSleep() throws Exception {
+        mWakefulness.dispatchStartedWakingUp();
+        mWakefulness.dispatchFinishedWakingUp();
+        mWakefulness.dispatchStartedGoingToSleep();
+
+        assertEquals(WakefulnessLifecycle.WAKEFULNESS_GOING_TO_SLEEP,
+                mWakefulness.getWakefulness());
+
+        verify(mWakefulnessObserver).onStartedGoingToSleep();
+    }
+
+    @Test
+    public void dispatchFinishedGoingToSleep() throws Exception {
+        mWakefulness.dispatchStartedWakingUp();
+        mWakefulness.dispatchFinishedWakingUp();
+        mWakefulness.dispatchStartedGoingToSleep();
+        mWakefulness.dispatchFinishedGoingToSleep();
+
+        assertEquals(WakefulnessLifecycle.WAKEFULNESS_ASLEEP,
+                mWakefulness.getWakefulness());
+
+        verify(mWakefulnessObserver).onFinishedGoingToSleep();
+    }
+
+    @Test
+    public void dump() throws Exception {
+        mWakefulness.dump(null, new PrintWriter(new ByteArrayOutputStream()), new String[0]);
+    }
+
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
index 8cacb4b..9603207 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/CommandQueueTest.java
@@ -269,9 +269,9 @@
     }
 
     @Test
-    public void testHandleSysnavKey() {
-        mCommandQueue.handleSystemNavigationKey(1);
+    public void testHandleSysKey() {
+        mCommandQueue.handleSystemKey(1);
         waitForIdleSync();
-        verify(mCallbacks).handleSystemNavigationKey(eq(1));
+        verify(mCallbacks).handleSystemKey(eq(1));
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
index 8a4983c..c33897e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarTest.java
@@ -334,6 +334,83 @@
     }
 
     @Test
+    public void testShouldPeek_suppressedScreenOn_dozing() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = true;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(true);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(false);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+
+        assertTrue(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+    @Test
+    public void testShouldPeek_suppressedScreenOn_noDoze() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = false;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(true);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(false);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        assertFalse(mStatusBar.shouldPeek(entry, sbn));
+    }
+    @Test
+    public void testShouldPeek_suppressedScreenOff_dozing() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = true;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(true);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        assertFalse(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+    @Test
+    public void testShouldPeek_suppressedScreenOff_noDoze() {
+        when(mPowerManager.isScreenOn()).thenReturn(true);
+        when(mHeadsUpManager.isSnoozed(anyString())).thenReturn(false);
+        when(mNotificationData.shouldFilterOut(any())).thenReturn(false);
+        when(mSystemServicesProxy.isDreaming()).thenReturn(false);
+        when(mNotificationData.getImportance(any())).thenReturn(IMPORTANCE_HIGH);
+
+        mStatusBar.mDozing = false;
+        when(mNotificationData.shouldSuppressScreenOn(any())).thenReturn(false);
+        when(mNotificationData.shouldSuppressScreenOff(any())).thenReturn(true);
+
+        Notification n = new Notification.Builder(getContext(), "a").build();
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "a", 0, 0, n,
+                UserHandle.of(0), null, 0);
+        NotificationData.Entry entry = new NotificationData.Entry(sbn);
+        assertTrue(mStatusBar.shouldPeek(entry, sbn));
+    }
+
+
+    @Test
     public void testLogHidden() {
         try {
             mStatusBar.handleVisibleToUserChanged(false);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
index 51e35cc..3f952c3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/utils/leaks/FakeKeyguardMonitor.java
@@ -47,6 +47,11 @@
     }
 
     @Override
+    public boolean isOccluded() {
+        return false;
+    }
+
+    @Override
     public boolean isKeyguardFadingAway() {
         return false;
     }
diff --git a/proto/src/system_messages.proto b/proto/src/system_messages.proto
index 93fae58..52f721b 100644
--- a/proto/src/system_messages.proto
+++ b/proto/src/system_messages.proto
@@ -183,6 +183,10 @@
     // Inform the user that the connected audio accessory is not supported
     NOTE_USB_AUDIO_ACCESSORY_NOT_SUPPORTED = 41;
 
+    // Inform the user that a wrong password was detected while attempting to connect
+    // to a Wi-Fi network
+    NOTE_WIFI_WRONG_PASSWORD = 42;
+
     // ADD_NEW_IDS_ABOVE_THIS_LINE
     // Legacy IDs with arbitrary values appear below
     // Legacy IDs existed as stable non-conflicting constants prior to the O release
diff --git a/services/Android.mk b/services/Android.mk
index 5c863b0..c376470 100644
--- a/services/Android.mk
+++ b/services/Android.mk
@@ -34,7 +34,6 @@
     net \
     print \
     restrictions \
-    retaildemo \
     usage \
     usb \
     voiceinteraction
diff --git a/services/backup/java/com/android/server/backup/BackupManagerService.java b/services/backup/java/com/android/server/backup/BackupManagerService.java
index abfc31e..a27a77e 100644
--- a/services/backup/java/com/android/server/backup/BackupManagerService.java
+++ b/services/backup/java/com/android/server/backup/BackupManagerService.java
@@ -123,8 +123,8 @@
 import com.android.server.SystemConfig;
 import com.android.server.SystemService;
 import com.android.server.backup.PackageManagerBackupAgent.Metadata;
-
 import com.android.server.power.BatterySaverPolicy.ServiceType;
+
 import libcore.io.IoUtils;
 
 import java.io.BufferedInputStream;
@@ -691,6 +691,7 @@
     final SparseArray<Operation> mCurrentOperations = new SparseArray<Operation>();
     final Object mCurrentOpLock = new Object();
     final Random mTokenGenerator = new Random();
+    final AtomicInteger mNextToken = new AtomicInteger();
 
     final SparseArray<AdbParams> mAdbBackupRestoreConfirmations = new SparseArray<AdbParams>();
 
@@ -763,15 +764,13 @@
     @GuardedBy("mQueueLock")
     ArrayList<FullBackupEntry> mFullBackupQueue;
 
-    // Utility: build a new random integer token
+    // Utility: build a new random integer token.  The low bits are the ordinal of the
+    // operation for near-time uniqueness, and the upper bits are random for app-
+    // side unpredictability.
     @Override
     public int generateRandomIntegerToken() {
-        int token;
-        do {
-            synchronized (mTokenGenerator) {
-                token = mTokenGenerator.nextInt();
-            }
-        } while (token < 0);
+        int token = mTokenGenerator.nextInt() & ~0xFF;
+        token |= (mNextToken.incrementAndGet() & 0xFF);
         return token;
     }
 
diff --git a/services/core/java/com/android/server/LocationManagerService.java b/services/core/java/com/android/server/LocationManagerService.java
index 7275461..a4e673d 100644
--- a/services/core/java/com/android/server/LocationManagerService.java
+++ b/services/core/java/com/android/server/LocationManagerService.java
@@ -243,8 +243,9 @@
 
     private GnssLocationProvider.GnssSystemInfoProvider mGnssSystemInfoProvider;
 
-    private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
     private GnssLocationProvider.GnssMetricsProvider mGnssMetricsProvider;
+
+    private GnssLocationProvider.GnssBatchingProvider mGnssBatchingProvider;
     private IBatchedLocationCallback mGnssBatchingCallback;
     private LinkedCallback mGnssBatchingDeathCallback;
     private boolean mGnssBatchingInProgress = false;
diff --git a/services/core/java/com/android/server/PinnerService.java b/services/core/java/com/android/server/PinnerService.java
index 45f9025..3d7408e 100644
--- a/services/core/java/com/android/server/PinnerService.java
+++ b/services/core/java/com/android/server/PinnerService.java
@@ -267,9 +267,10 @@
 
         // determine the ABI from either ApplicationInfo or Build
         String arch = "arm";
-        if (cameraInfo.primaryCpuAbi != null
-            && VMRuntime.is64BitAbi(cameraInfo.primaryCpuAbi)) {
-            arch = arch + "64";
+        if (cameraInfo.primaryCpuAbi != null) {
+            if (VMRuntime.is64BitAbi(cameraInfo.primaryCpuAbi)) {
+                arch = arch + "64";
+            }
         } else {
             if (VMRuntime.is64BitAbi(Build.SUPPORTED_ABIS[0])) {
                 arch = arch + "64";
diff --git a/services/core/java/com/android/server/am/ActivityStarter.java b/services/core/java/com/android/server/am/ActivityStarter.java
index a31c33e..4f04066 100644
--- a/services/core/java/com/android/server/am/ActivityStarter.java
+++ b/services/core/java/com/android/server/am/ActivityStarter.java
@@ -1640,6 +1640,16 @@
                                 REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
                                 "reparentToDisplay");
                         mMovedToFront = true;
+                    } else if (launchStack.getStackId() == StackId.HOME_STACK_ID
+                        && mTargetStack.getStackId() != StackId.HOME_STACK_ID) {
+                        // It is possible for the home activity to be in another stack initially.
+                        // For example, the activity may have been initially started with an intent
+                        // which placed it in the fullscreen stack. To ensure the proper handling of
+                        // the activity based on home stack assumptions, we must move it over.
+                        intentActivity.getTask().reparent(launchStack.mStackId, ON_TOP,
+                                REPARENT_MOVE_STACK_TO_FRONT, ANIMATE, DEFER_RESUME,
+                                "reparentingHome");
+                        mMovedToFront = true;
                     }
                     mOptions = null;
 
diff --git a/services/core/java/com/android/server/am/KeyguardController.java b/services/core/java/com/android/server/am/KeyguardController.java
index a46c851..d10f9fb 100644
--- a/services/core/java/com/android/server/am/KeyguardController.java
+++ b/services/core/java/com/android/server/am/KeyguardController.java
@@ -144,6 +144,7 @@
             failCallback(callback);
             return;
         }
+        Slog.i(TAG, "Activity requesting to dismiss Keyguard: " + activityRecord);
         mWindowManager.dismissKeyguard(callback);
     }
 
diff --git a/services/core/java/com/android/server/am/VrController.java b/services/core/java/com/android/server/am/VrController.java
index 048bef7..feddfe3 100644
--- a/services/core/java/com/android/server/am/VrController.java
+++ b/services/core/java/com/android/server/am/VrController.java
@@ -163,6 +163,7 @@
         ComponentName requestedPackage;
         ComponentName callingPackage;
         int userId;
+        int processId = -1;
         boolean changed = false;
         synchronized (mGlobalAmLock) {
             vrMode = record.requestedVrComponent != null;
@@ -172,11 +173,15 @@
 
             // Tell the VrController that a VR mode change is requested.
             changed = changeVrModeLocked(vrMode, record.app);
+
+            if (record.app != null) {
+                processId = record.app.pid;
+            }
         }
 
         // Tell VrManager that a VR mode changed is requested, VrManager will handle
         // notifying all non-AM dependencies if needed.
-        vrService.setVrMode(vrMode, requestedPackage, userId, callingPackage);
+        vrService.setVrMode(vrMode, requestedPackage, userId, processId, callingPackage);
         return changed;
     }
 
diff --git a/services/core/java/com/android/server/content/SyncJobService.java b/services/core/java/com/android/server/content/SyncJobService.java
index 1f02ebf..07f04b1 100644
--- a/services/core/java/com/android/server/content/SyncJobService.java
+++ b/services/core/java/com/android/server/content/SyncJobService.java
@@ -76,7 +76,7 @@
         m.what = SyncManager.SyncHandler.MESSAGE_START_SYNC;
         SyncOperation op = SyncOperation.maybeCreateFromJobExtras(params.getExtras());
 
-        mLogger.log("onStopJob() jobid=", params.getJobId(), " op=", op);
+        mLogger.log("onStartJob() jobid=", params.getJobId(), " op=", op);
 
         if (op == null) {
             Slog.e(TAG, "Got invalid job " + params.getJobId());
@@ -131,4 +131,4 @@
             }
         }
     }
-}
\ No newline at end of file
+}
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index e82724d..cbd02ac 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -165,6 +165,12 @@
     // a stylish color fade animation instead.
     private boolean mColorFadeFadesConfig;
 
+    // True if we need to transition to the off state when coming out of a doze state.
+    // Some display hardware will show artifacts (flickers, etc) when transitioning from a doze
+    // to a fully on state. In order to hide these, we first transition to off to let the system
+    // animate the screen on as it normally would, which is a much smoother experience.
+    private boolean mTransitionOffAfterDozeConfig;
+
     // The pending power request.
     // Initially null until the first call to requestPowerState.
     // Guarded by mLock.
@@ -410,6 +416,9 @@
         mColorFadeFadesConfig = resources.getBoolean(
                 com.android.internal.R.bool.config_animateScreenLights);
 
+        mTransitionOffAfterDozeConfig = resources.getBoolean(
+                com.android.internal.R.bool.config_displayTransitionOffAfterDoze);
+
         if (!DEBUG_PRETEND_PROXIMITY_SENSOR_ABSENT) {
             mProximitySensor = mSensorManager.getDefaultSensor(Sensor.TYPE_PROXIMITY);
             if (mProximitySensor != null) {
@@ -877,6 +886,10 @@
     }
 
     private boolean setScreenState(int state) {
+        return setScreenState(state, false /*force*/);
+    }
+
+    private boolean setScreenState(int state, boolean force) {
         final boolean isOff = (state == Display.STATE_OFF);
         if (mPowerState.getScreenState() != state) {
 
@@ -887,9 +900,17 @@
                     mReportedScreenStateToPolicy = REPORTED_TO_POLICY_SCREEN_TURNING_OFF;
                     blockScreenOff();
                     mWindowManagerPolicy.screenTurningOff(mPendingScreenOffUnblocker);
-                    return false;
+                    if (force) {
+                        // If we're forcing the power state transition then immediately
+                        // unblock the screen off event. This keeps the lifecycle consistent,
+                        // so WindowManagerPolicy will always see screenTurningOff before
+                        // screenTurnedOff, but we don't actually block on them for the state
+                        // change.
+                        unblockScreenOff();
+                    } else {
+                        return false;
+                    }
                 } else if (mPendingScreenOffUnblocker != null) {
-
                     // Abort doing the state change until screen off is unblocked.
                     return false;
                 }
@@ -968,6 +989,17 @@
             mPendingScreenOff = false;
         }
 
+        if (mTransitionOffAfterDozeConfig &&
+                Display.isDozeState(mPowerState.getScreenState())
+                && !Display.isDozeState(target)) {
+            setScreenState(Display.STATE_OFF, true /*force*/);
+            // Skip the screen off animation and add a black surface to hide the
+            // contents of the screen. This will also trigger another power state update so that we
+            // end up converging on the target state.
+            mColorFadeOffAnimator.end();
+            return;
+        }
+
         // If we were in the process of turning off the screen but didn't quite
         // finish.  Then finish up now to prevent a jarring transition back
         // to screen on if we skipped blocking screen on as usual.
diff --git a/services/core/java/com/android/server/location/GnssLocationProvider.java b/services/core/java/com/android/server/location/GnssLocationProvider.java
index 83bb17e..cdf25cf 100644
--- a/services/core/java/com/android/server/location/GnssLocationProvider.java
+++ b/services/core/java/com/android/server/location/GnssLocationProvider.java
@@ -1754,20 +1754,32 @@
     }
 
     /**
-     * called from native code - Gps measurements callback
+     * called from native code - GNSS measurements callback
      */
     private void reportMeasurementData(GnssMeasurementsEvent event) {
         if (!mItarSpeedLimitExceeded) {
-            mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+            // send to handler to allow native to return quickly
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mGnssMeasurementsProvider.onMeasurementsAvailable(event);
+                }
+            });
         }
     }
 
     /**
-     * called from native code - GPS navigation message callback
+     * called from native code - GNSS navigation message callback
      */
     private void reportNavigationMessage(GnssNavigationMessage event) {
         if (!mItarSpeedLimitExceeded) {
-            mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+            // send to handler to allow native to return quickly
+            mHandler.post(new Runnable() {
+                @Override
+                public void run() {
+                    mGnssNavigationMessageProvider.onNavigationMessageAvailable(event);
+                }
+            });
         }
     }
 
diff --git a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
index caf1d6c..924520b 100644
--- a/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
+++ b/services/core/java/com/android/server/location/GnssMeasurementsProvider.java
@@ -54,9 +54,8 @@
     }
 
     public void onGpsEnabledChanged() {
-        if (tryUpdateRegistrationWithService()) {
-            updateResult();
-        }
+        tryUpdateRegistrationWithService();
+        updateResult();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
index 8d21928..df3c49b 100644
--- a/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
+++ b/services/core/java/com/android/server/location/GnssNavigationMessageProvider.java
@@ -55,9 +55,8 @@
     }
 
     public void onGpsEnabledChanged() {
-        if (tryUpdateRegistrationWithService()) {
-            updateResult();
-        }
+        tryUpdateRegistrationWithService();
+        updateResult();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/location/RemoteListenerHelper.java b/services/core/java/com/android/server/location/RemoteListenerHelper.java
index ec2828b..f51bc87 100644
--- a/services/core/java/com/android/server/location/RemoteListenerHelper.java
+++ b/services/core/java/com/android/server/location/RemoteListenerHelper.java
@@ -25,6 +25,7 @@
 import android.os.RemoteException;
 import android.util.Log;
 
+import java.lang.Runnable;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -45,7 +46,7 @@
 
     private final Map<IBinder, LinkedListener> mListenerMap = new HashMap<>();
 
-    private boolean mIsRegistered;
+    private boolean mIsRegistered;  // must access only on handler thread
     private boolean mHasIsSupported;
     private boolean mIsSupported;
 
@@ -83,12 +84,12 @@
             } else if (mHasIsSupported && !mIsSupported) {
                 result = RESULT_NOT_SUPPORTED;
             } else if (!isGpsEnabled()) {
-                result = RESULT_GPS_LOCATION_DISABLED;
-            } else if (!tryRegister()) {
                 // only attempt to register if GPS is enabled, otherwise we will register once GPS
                 // becomes available
-                result = RESULT_INTERNAL_ERROR;
+                result = RESULT_GPS_LOCATION_DISABLED;
             } else if (mHasIsSupported && mIsSupported) {
+                tryRegister();
+                // initially presume success, possible internal error could follow asynchornously
                 result = RESULT_SUCCESS;
             } else {
                 // at this point if the supported flag is not set, the notification will be sent
@@ -117,8 +118,8 @@
 
     protected abstract boolean isAvailableInPlatform();
     protected abstract boolean isGpsEnabled();
-    protected abstract boolean registerWithService();
-    protected abstract void unregisterFromService();
+    protected abstract boolean registerWithService(); // must access only on handler thread
+    protected abstract void unregisterFromService(); // must access only on handler thread
     protected abstract ListenerOperation<TListener> getHandlerOperation(int result);
 
     protected interface ListenerOperation<TListener extends IInterface> {
@@ -138,22 +139,16 @@
         }
     }
 
-    protected boolean tryUpdateRegistrationWithService() {
+    protected void tryUpdateRegistrationWithService() {
         synchronized (mListenerMap) {
             if (!isGpsEnabled()) {
                 tryUnregister();
-                return true;
+                return;
             }
             if (mListenerMap.isEmpty()) {
-                return true;
+                return;
             }
-            if (tryRegister()) {
-                // registration was successful, there is no need to update the state
-                return true;
-            }
-            ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
-            foreachUnsafe(operation);
-            return false;
+            tryRegister();
         }
     }
 
@@ -180,19 +175,40 @@
         }
     }
 
-    private boolean tryRegister() {
-        if (!mIsRegistered) {
-            mIsRegistered = registerWithService();
-        }
-        return mIsRegistered;
+    private void tryRegister() {
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (!mIsRegistered) {
+                    mIsRegistered = registerWithService();
+                }
+                if (!mIsRegistered) {
+                    // post back a failure
+                    mHandler.post(new Runnable() {
+                        @Override
+                        public void run() {
+                            synchronized (mListenerMap) {
+                                ListenerOperation<TListener> operation = getHandlerOperation(RESULT_INTERNAL_ERROR);
+                                foreachUnsafe(operation);
+                            }
+                        }
+                    });
+                }
+            }
+        });
     }
 
     private void tryUnregister() {
-        if (!mIsRegistered) {
-            return;
-        }
-        unregisterFromService();
-        mIsRegistered = false;
+        mHandler.post(new Runnable() {
+            @Override
+            public void run() {
+                if (!mIsRegistered) {
+                    return;
+                }
+                unregisterFromService();
+                mIsRegistered = false;
+            }
+        });
     }
 
     private int calculateCurrentResultUnsafe() {
diff --git a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
index 9d92cbc..a6ea6b2 100644
--- a/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
+++ b/services/core/java/com/android/server/media/projection/MediaProjectionManagerService.java
@@ -111,7 +111,7 @@
             mProjectionGrant.stop();
         }
         if (mMediaRouteInfo != null) {
-            mMediaRouter.getDefaultRoute().select();
+            mMediaRouter.getFallbackRoute().select();
         }
         mProjectionToken = projection.asBinder();
         mProjectionGrant = projection;
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index a7eb2c6..5a8ebc2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -1080,7 +1080,7 @@
         mUsageStats = us;
     }
 
-    // TODO: Tests should call onStart instead once the methods above are removed.
+    // TODO: All tests should use this init instead of the one-off setters above.
     @VisibleForTesting
     void init(Looper looper, IPackageManager packageManager, PackageManager packageManagerClient,
             LightsManager lightsManager, NotificationListeners notificationListeners,
@@ -1211,6 +1211,37 @@
         mUserProfiles.updateCache(getContext());
         listenForCallState();
 
+        mSettingsObserver = new SettingsObserver(mHandler);
+
+        mArchive = new Archive(resources.getInteger(
+                R.integer.config_notificationServiceArchiveSize));
+
+        mIsTelevision = mPackageManagerClient.hasSystemFeature(FEATURE_LEANBACK)
+                || mPackageManagerClient.hasSystemFeature(FEATURE_TELEVISION);
+    }
+
+    @Override
+    public void onStart() {
+        SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
+            @Override
+            public void repost(int userId, NotificationRecord r) {
+                try {
+                    if (DBG) {
+                        Slog.d(TAG, "Reposting " + r.getKey());
+                    }
+                    enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
+                            r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
+                            r.sbn.getNotification(), userId);
+                } catch (Exception e) {
+                    Slog.e(TAG, "Cannot un-snooze notification", e);
+                }
+            }
+        }, mUserProfiles);
+
+        init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
+                getLocalService(LightsManager.class), new NotificationListeners(),
+                null, snoozeHelper, new NotificationUsageStats(getContext()));
+
         // register for various Intents
         IntentFilter filter = new IntentFilter();
         filter.addAction(Intent.ACTION_SCREEN_ON);
@@ -1248,36 +1279,6 @@
         timeoutFilter.addDataScheme(SCHEME_TIMEOUT);
         getContext().registerReceiver(mNotificationTimeoutReceiver, timeoutFilter);
 
-        mSettingsObserver = new SettingsObserver(mHandler);
-
-        mArchive = new Archive(resources.getInteger(
-                R.integer.config_notificationServiceArchiveSize));
-
-        mIsTelevision = mPackageManagerClient.hasSystemFeature(FEATURE_LEANBACK)
-                || mPackageManagerClient.hasSystemFeature(FEATURE_TELEVISION);
-    }
-
-    @Override
-    public void onStart() {
-        SnoozeHelper snoozeHelper = new SnoozeHelper(getContext(), new SnoozeHelper.Callback() {
-            @Override
-            public void repost(int userId, NotificationRecord r) {
-                try {
-                    if (DBG) {
-                        Slog.d(TAG, "Reposting " + r.getKey());
-                    }
-                    enqueueNotificationInternal(r.sbn.getPackageName(), r.sbn.getOpPkg(),
-                            r.sbn.getUid(), r.sbn.getInitialPid(), r.sbn.getTag(), r.sbn.getId(),
-                            r.sbn.getNotification(), userId);
-                } catch (Exception e) {
-                    Slog.e(TAG, "Cannot un-snooze notification", e);
-                }
-            }
-        }, mUserProfiles);
-
-        init(Looper.myLooper(), AppGlobals.getPackageManager(), getContext().getPackageManager(),
-                getLocalService(LightsManager.class), new NotificationListeners(),
-                null, snoozeHelper, new NotificationUsageStats(getContext()));
         publishBinderService(Context.NOTIFICATION_SERVICE, mService);
         publishLocalService(NotificationManagerInternal.class, mInternalService);
     }
@@ -3827,13 +3828,6 @@
             return true;
         }
 
-        // Suppressed for being too recently noisy
-        final String pkg = record.sbn.getPackageName();
-        if (mUsageStats.isAlertRateLimited(pkg)) {
-            Slog.e(TAG, "Muting recently noisy " + record.getKey());
-            return true;
-        }
-
         // muted by listener
         final String disableEffects = disableNotificationEffects(record);
         if (disableEffects != null) {
@@ -3851,6 +3845,13 @@
             return notification.suppressAlertingDueToGrouping();
         }
 
+        // Suppressed for being too recently noisy
+        final String pkg = record.sbn.getPackageName();
+        if (mUsageStats.isAlertRateLimited(pkg)) {
+            Slog.e(TAG, "Muting recently noisy " + record.getKey());
+            return true;
+        }
+
         return false;
     }
 
diff --git a/services/core/java/com/android/server/notification/RankingHelper.java b/services/core/java/com/android/server/notification/RankingHelper.java
index d7b36aa..8420c90 100644
--- a/services/core/java/com/android/server/notification/RankingHelper.java
+++ b/services/core/java/com/android/server/notification/RankingHelper.java
@@ -567,6 +567,13 @@
             existing.setDescription(channel.getDescription());
             existing.setBlockableSystem(channel.isBlockableSystem());
 
+            // Apps are allowed to downgrade channel importance if the user has not changed any
+            // fields on this channel yet.
+            if (existing.getUserLockedFields() == 0 &&
+                    channel.getImportance() < existing.getImportance()) {
+                existing.setImportance(channel.getImportance());
+            }
+
             updateConfig();
             return;
         }
diff --git a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
index 5090083..0b54e5e 100644
--- a/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
+++ b/services/core/java/com/android/server/policy/AccessibilityShortcutController.java
@@ -154,7 +154,7 @@
             // Don't check if haptics are disabled, as we need to alert the user that their
             // way of interacting with the phone may change if they activate the shortcut
             long[] vibePattern = PhoneWindowManager.getLongIntArray(mContext.getResources(),
-                    R.array.config_safeModeDisabledVibePattern);
+                    R.array.config_longPressVibePattern);
             vibrator.vibrate(vibePattern, -1, VIBRATION_ATTRIBUTES);
         }
 
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 75fc25a..66f9c57 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -431,9 +431,6 @@
     // Vibrator pattern for a short vibration when tapping on a day/month/year date of a Calendar.
     long[] mCalendarDateVibePattern;
 
-    // Vibrator pattern for haptic feedback during boot when safe mode is disabled.
-    long[] mSafeModeDisabledVibePattern;
-
     // Vibrator pattern for haptic feedback during boot when safe mode is enabled.
     long[] mSafeModeEnabledVibePattern;
 
@@ -1278,6 +1275,16 @@
             }
         }
 
+        // Inform the StatusBar; but do not allow it to consume the event.
+        IStatusBarService statusBar = getStatusBarService();
+        if (statusBar != null) {
+            try {
+                statusBar.handleSystemKey(event.getKeyCode());
+            } catch (RemoteException e) {
+                // Oh well.
+            }
+        }
+
         // If the power key has still not yet been handled, then detect short
         // press, long press, or multi press and decide what to do.
         mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
@@ -2066,8 +2073,6 @@
                 com.android.internal.R.array.config_longPressVibePattern);
         mCalendarDateVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_calendarDateVibePattern);
-        mSafeModeDisabledVibePattern = getLongIntArray(mContext.getResources(),
-                com.android.internal.R.array.config_safeModeDisabledVibePattern);
         mSafeModeEnabledVibePattern = getLongIntArray(mContext.getResources(),
                 com.android.internal.R.array.config_safeModeEnabledVibePattern);
 
@@ -3158,10 +3163,18 @@
 
     @Override
     public void selectRotationAnimationLw(int anim[]) {
+        // If the screen is off or non-interactive, force a jumpcut.
+        final boolean forceJumpcut = !mScreenOnFully || !mAwake;
         if (PRINT_ANIM) Slog.i(TAG, "selectRotationAnimation mTopFullscreen="
                 + mTopFullscreenOpaqueWindowState + " rotationAnimation="
                 + (mTopFullscreenOpaqueWindowState == null ?
-                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation));
+                        "0" : mTopFullscreenOpaqueWindowState.getAttrs().rotationAnimation)
+                + " forceJumpcut=" + forceJumpcut);
+        if (forceJumpcut) {
+            anim[0] = R.anim.rotation_animation_jump_exit;
+            anim[1] = R.anim.rotation_animation_enter;
+            return;
+        }
         if (mTopFullscreenOpaqueWindowState != null) {
             int animationHint = mTopFullscreenOpaqueWindowState.getRotationAnimationHint();
             if (animationHint < 0 && mTopIsFullscreen) {
@@ -5399,7 +5412,7 @@
             // represent should be hidden or if we should hide the lockscreen. For attached app
             // windows we defer the decision to the window it is attached to.
             if (appWindow && attached == null) {
-                if (isFullscreen(attrs) && StackId.normallyFullscreenWindows(stackId)) {
+                if (attrs.isFullscreen() && StackId.normallyFullscreenWindows(stackId)) {
                     if (DEBUG_LAYOUT) Slog.v(TAG, "Fullscreen window: " + win);
                     mTopFullscreenOpaqueWindowState = win;
                     if (mTopFullscreenOpaqueOrDimmingWindowState == null) {
@@ -5438,7 +5451,7 @@
         // separately, because both the "real fullscreen" opaque window and the one for the docked
         // stack can control View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR.
         if (mTopDockedOpaqueWindowState == null && affectsSystemUi && appWindow && attached == null
-                && isFullscreen(attrs) && stackId == DOCKED_STACK_ID) {
+                && attrs.isFullscreen() && stackId == DOCKED_STACK_ID) {
             mTopDockedOpaqueWindowState = win;
             if (mTopDockedOpaqueOrDimmingWindowState == null) {
                 mTopDockedOpaqueOrDimmingWindowState = win;
@@ -5463,12 +5476,6 @@
         }
     }
 
-    private boolean isFullscreen(WindowManager.LayoutParams attrs) {
-        return attrs.x == 0 && attrs.y == 0
-                && attrs.width == WindowManager.LayoutParams.MATCH_PARENT
-                && attrs.height == WindowManager.LayoutParams.MATCH_PARENT;
-    }
-
     /** {@inheritDoc} */
     @Override
     public int finishPostLayoutPolicyLw() {
@@ -6221,7 +6228,7 @@
                     IStatusBarService sbar = getStatusBarService();
                     if (sbar != null) {
                         try {
-                            sbar.handleSystemNavigationKey(event.getKeyCode());
+                            sbar.handleSystemKey(event.getKeyCode());
                         } catch (RemoteException e1) {
                             // oops, no statusbar. Ignore event.
                         }
@@ -6606,6 +6613,10 @@
     @Override
     public void finishedWakingUp() {
         if (DEBUG_WAKEUP) Slog.i(TAG, "Finished waking up...");
+
+        if (mKeyguardDelegate != null) {
+            mKeyguardDelegate.onFinishedWakingUp();
+        }
     }
 
     private void wakeUpFromPowerKey(long eventTime) {
@@ -6714,6 +6725,11 @@
     @Override
     public void screenTurningOff(ScreenOffListener screenOffListener) {
         mWindowManagerFuncs.screenTurningOff(screenOffListener);
+        synchronized (mLock) {
+            if (mKeyguardDelegate != null) {
+                mKeyguardDelegate.onScreenTurningOff();
+            }
+        }
     }
 
     private void reportScreenStateToVrManager(boolean isScreenOn) {
@@ -6810,8 +6826,8 @@
     }
 
     @Override
-    public boolean isInteractive() {
-        return mAwake;
+    public boolean okToAnimate() {
+        return mAwake && !mGoingToSleep;
     }
 
     /** {@inheritDoc} */
@@ -7199,9 +7215,9 @@
     @Override
     public void setSafeMode(boolean safeMode) {
         mSafeMode = safeMode;
-        performHapticFeedbackLw(null, safeMode
-                ? HapticFeedbackConstants.SAFE_MODE_ENABLED
-                : HapticFeedbackConstants.SAFE_MODE_DISABLED, true);
+        if (safeMode) {
+            performHapticFeedbackLw(null, HapticFeedbackConstants.SAFE_MODE_ENABLED, true);
+        }
     }
 
     static long[] getLongIntArray(Resources r, int resid) {
@@ -7720,9 +7736,6 @@
             case HapticFeedbackConstants.CALENDAR_DATE:
                 pattern = mCalendarDateVibePattern;
                 break;
-            case HapticFeedbackConstants.SAFE_MODE_DISABLED:
-                pattern = mSafeModeDisabledVibePattern;
-                break;
             case HapticFeedbackConstants.SAFE_MODE_ENABLED:
                 pattern = mSafeModeEnabledVibePattern;
                 break;
@@ -7832,21 +7845,17 @@
     }
 
     private int updateLightStatusBarLw(int vis, WindowState opaque, WindowState opaqueOrDimming) {
-        WindowState statusColorWin = isStatusBarKeyguard() && !mKeyguardOccluded
-                ? mStatusBar
-                : opaqueOrDimming;
-
-        if (statusColorWin != null) {
-            if (statusColorWin == opaque) {
-                // If the top fullscreen-or-dimming window is also the top fullscreen, respect
-                // its light flag.
-                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-                vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
-                        & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-            } else if (statusColorWin != null && statusColorWin.isDimming()) {
-                // Otherwise if it's dimming, clear the light flag.
-                vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
-            }
+        final boolean onKeyguard = isStatusBarKeyguard() && !mKeyguardOccluded;
+        final WindowState statusColorWin = onKeyguard ? mStatusBar : opaqueOrDimming;
+        if (statusColorWin != null && (statusColorWin == opaque || onKeyguard)) {
+            // If the top fullscreen-or-dimming window is also the top fullscreen, respect
+            // its light flag.
+            vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+            vis |= PolicyControl.getSystemUiVisibility(statusColorWin, null)
+                    & View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
+        } else if (statusColorWin != null && statusColorWin.isDimming()) {
+            // Otherwise if it's dimming, clear the light flag.
+            vis &= ~View.SYSTEM_UI_FLAG_LIGHT_STATUS_BAR;
         }
         return vis;
     }
@@ -7856,7 +7865,7 @@
         final WindowState imeWin = mWindowManagerFuncs.getInputMethodWindowLw();
 
         final WindowState navColorWin;
-        if (imeWin != null && imeWin.isVisibleLw()) {
+        if (imeWin != null && imeWin.isVisibleLw() && mNavigationBarPosition == NAV_BAR_BOTTOM) {
             navColorWin = imeWin;
         } else {
             navColorWin = opaqueOrDimming;
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
index 0121ee1..50e5e7b 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceDelegate.java
@@ -35,10 +35,12 @@
     private static final int SCREEN_STATE_OFF = 0;
     private static final int SCREEN_STATE_TURNING_ON = 1;
     private static final int SCREEN_STATE_ON = 2;
+    private static final int SCREEN_STATE_TURNING_OFF = 3;
 
     private static final int INTERACTIVE_STATE_SLEEP = 0;
-    private static final int INTERACTIVE_STATE_AWAKE = 1;
-    private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 2;
+    private static final int INTERACTIVE_STATE_WAKING = 1;
+    private static final int INTERACTIVE_STATE_AWAKE = 2;
+    private static final int INTERACTIVE_STATE_GOING_TO_SLEEP = 3;
 
     protected KeyguardServiceWrapper mKeyguardService;
     private final Context mContext;
@@ -164,9 +166,13 @@
                     mKeyguardService.setCurrentUser(mKeyguardState.currentUser);
                 }
                 // This is used to hide the scrim once keyguard displays.
-                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
+                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE
+                        || mKeyguardState.interactiveState == INTERACTIVE_STATE_WAKING) {
                     mKeyguardService.onStartedWakingUp();
                 }
+                if (mKeyguardState.interactiveState == INTERACTIVE_STATE_AWAKE) {
+                    mKeyguardService.onFinishedWakingUp();
+                }
                 if (mKeyguardState.screenState == SCREEN_STATE_ON
                         || mKeyguardState.screenState == SCREEN_STATE_TURNING_ON) {
                     mKeyguardService.onScreenTurningOn(
@@ -277,9 +283,25 @@
             if (DEBUG) Log.v(TAG, "onStartedWakingUp()");
             mKeyguardService.onStartedWakingUp();
         }
+        mKeyguardState.interactiveState = INTERACTIVE_STATE_WAKING;
+    }
+
+    public void onFinishedWakingUp() {
+        if (mKeyguardService != null) {
+            if (DEBUG) Log.v(TAG, "onFinishedWakingUp()");
+            mKeyguardService.onFinishedWakingUp();
+        }
         mKeyguardState.interactiveState = INTERACTIVE_STATE_AWAKE;
     }
 
+    public void onScreenTurningOff() {
+        if (mKeyguardService != null) {
+            if (DEBUG) Log.v(TAG, "onScreenTurningOff()");
+            mKeyguardService.onScreenTurningOff();
+        }
+        mKeyguardState.screenState = SCREEN_STATE_TURNING_OFF;
+    }
+
     public void onScreenTurnedOff() {
         if (mKeyguardService != null) {
             if (DEBUG) Log.v(TAG, "onScreenTurnedOff()");
diff --git a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
index 425be54..952e0b0 100644
--- a/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
+++ b/services/core/java/com/android/server/policy/keyguard/KeyguardServiceWrapper.java
@@ -128,6 +128,15 @@
     }
 
     @Override
+    public void onFinishedWakingUp() {
+        try {
+            mService.onFinishedWakingUp();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
+    @Override
     public void onScreenTurningOn(IKeyguardDrawnCallback callback) {
         try {
             mService.onScreenTurningOn(callback);
@@ -146,6 +155,15 @@
     }
 
     @Override
+    public void onScreenTurningOff() {
+        try {
+            mService.onScreenTurningOff();
+        } catch (RemoteException e) {
+            Slog.w(TAG , "Remote Exception", e);
+        }
+    }
+
+    @Override
     public void onScreenTurnedOff() {
         try {
             mService.onScreenTurnedOff();
diff --git a/services/core/java/com/android/server/power/PowerManagerService.java b/services/core/java/com/android/server/power/PowerManagerService.java
index a94484a..50f4f24 100644
--- a/services/core/java/com/android/server/power/PowerManagerService.java
+++ b/services/core/java/com/android/server/power/PowerManagerService.java
@@ -53,6 +53,7 @@
 import android.os.SystemProperties;
 import android.os.Trace;
 import android.os.UserHandle;
+import android.os.UserManager;
 import android.os.WorkSource;
 import android.provider.Settings;
 import android.provider.Settings.SettingNotFoundException;
@@ -197,6 +198,9 @@
     // System property indicating that the screen should remain off until an explicit user action
     private static final String SYSTEM_PROPERTY_QUIESCENT = "ro.boot.quiescent";
 
+    // System Property indicating that retail demo mode is currently enabled.
+    private static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
+
     // Possible reasons for shutting down for use in data/misc/reboot/last_shutdown_reason
     private static final String REASON_SHUTDOWN = "shutdown";
     private static final String REASON_REBOOT = "reboot";
@@ -805,6 +809,9 @@
         resolver.registerContentObserver(Settings.Secure.getUriFor(
                 Settings.Secure.DOUBLE_TAP_TO_WAKE),
                 false, mSettingsObserver, UserHandle.USER_ALL);
+        resolver.registerContentObserver(Settings.Global.getUriFor(
+                Settings.Global.DEVICE_DEMO_MODE),
+                false, mSettingsObserver, UserHandle.USER_SYSTEM);
         IVrManager vrManager = (IVrManager) getBinderService(Context.VR_SERVICE);
         if (vrManager != null) {
             try {
@@ -912,6 +919,11 @@
             }
         }
 
+        final String retailDemoValue = UserManager.isDeviceInDemoMode(mContext) ? "1" : "0";
+        if (!retailDemoValue.equals(SystemProperties.get(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED))) {
+            SystemProperties.set(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, retailDemoValue);
+        }
+
         final int oldScreenBrightnessSetting = getCurrentBrightnessSettingLocked();
 
         mScreenBrightnessForVrSetting = Settings.System.getIntForUser(resolver,
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 984b40f..2df0f10 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -404,12 +404,12 @@
     }
 
     @Override
-    public void handleSystemNavigationKey(int key) throws RemoteException {
+    public void handleSystemKey(int key) throws RemoteException {
         enforceExpandStatusBar();
 
         if (mBar != null) {
             try {
-                mBar.handleSystemNavigationKey(key);
+                mBar.handleSystemKey(key);
             } catch (RemoteException ex) {
             }
         }
diff --git a/services/core/java/com/android/server/vr/VrManagerInternal.java b/services/core/java/com/android/server/vr/VrManagerInternal.java
index 1f75640..bdd9de0 100644
--- a/services/core/java/com/android/server/vr/VrManagerInternal.java
+++ b/services/core/java/com/android/server/vr/VrManagerInternal.java
@@ -52,10 +52,11 @@
      * @param enabled {@code true} to enable VR mode.
      * @param packageName The package name of the requested VrListenerService to bind.
      * @param userId the user requesting the VrListenerService component.
+     * @param processId the process the component is running in.
      * @param calling the component currently using VR mode, or null to leave unchanged.
      */
     public abstract void setVrMode(boolean enabled, @NonNull ComponentName packageName,
-            int userId, @NonNull ComponentName calling);
+            int userId, int processId, @NonNull ComponentName calling);
 
     /**
      * Set whether the system has acquired a sleep token.
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index f13cc76..e737328 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -125,6 +125,8 @@
     private boolean mVrModeAllowed;
     private boolean mVrModeEnabled;
     private boolean mPersistentVrModeEnabled;
+    private boolean mRunning2dInVr;
+    private int mVrAppProcessId;
     private EnabledComponentsObserver mComponentObserver;
     private ManagedApplicationService mCurrentVrService;
     private ComponentName mDefaultVrService;
@@ -174,7 +176,7 @@
                 }
                 consumeAndApplyPendingStateLocked();
                 if (mBootsToVr && !mVrModeEnabled) {
-                  setVrMode(true, mDefaultVrService, 0, null);
+                  setVrMode(true, mDefaultVrService, 0, -1, null);
                 }
             } else {
                 // Disable persistent mode when VR mode isn't allowed, allows an escape hatch to
@@ -183,12 +185,12 @@
 
                 // Set pending state to current state.
                 mPendingState = (mVrModeEnabled && mCurrentVrService != null)
-                    ? new VrState(mVrModeEnabled, mCurrentVrService.getComponent(),
-                        mCurrentVrService.getUserId(), mCurrentVrModeComponent)
+                    ? new VrState(mVrModeEnabled, mRunning2dInVr, mCurrentVrService.getComponent(),
+                        mCurrentVrService.getUserId(), mVrAppProcessId, mCurrentVrModeComponent)
                     : null;
 
                 // Unbind current VR service and do necessary callbacks.
-                updateCurrentVrServiceLocked(false, null, 0, null);
+                updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
             }
         }
     }
@@ -270,26 +272,33 @@
 
     private static class VrState {
         final boolean enabled;
+        final boolean running2dInVr;
         final int userId;
+        final int processId;
         final ComponentName targetPackageName;
         final ComponentName callingPackage;
         final long timestamp;
         final boolean defaultPermissionsGranted;
 
-        VrState(boolean enabled, ComponentName targetPackageName, int userId,
-                ComponentName callingPackage) {
+
+        VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+                int processId, ComponentName callingPackage) {
             this.enabled = enabled;
+            this.running2dInVr = running2dInVr;
             this.userId = userId;
+            this.processId = processId;
             this.targetPackageName = targetPackageName;
             this.callingPackage = callingPackage;
             this.defaultPermissionsGranted = false;
             this.timestamp = System.currentTimeMillis();
         }
 
-        VrState(boolean enabled, ComponentName targetPackageName, int userId,
-            ComponentName callingPackage, boolean defaultPermissionsGranted) {
+        VrState(boolean enabled, boolean running2dInVr, ComponentName targetPackageName, int userId,
+            int processId, ComponentName callingPackage, boolean defaultPermissionsGranted) {
             this.enabled = enabled;
+            this.running2dInVr = running2dInVr;
             this.userId = userId;
+            this.processId = processId;
             this.targetPackageName = targetPackageName;
             this.callingPackage = callingPackage;
             this.defaultPermissionsGranted = defaultPermissionsGranted;
@@ -390,8 +399,9 @@
             }
 
             // There is an active service, update it if needed
-            updateCurrentVrServiceLocked(mVrModeEnabled, mCurrentVrService.getComponent(),
-                    mCurrentVrService.getUserId(), mCurrentVrModeComponent);
+            updateCurrentVrServiceLocked(mVrModeEnabled, mRunning2dInVr,
+                    mCurrentVrService.getComponent(), mCurrentVrService.getUserId(),
+                    mVrAppProcessId, mCurrentVrModeComponent);
         }
     }
 
@@ -527,9 +537,9 @@
      */
     private final class LocalService extends VrManagerInternal {
         @Override
-        public void setVrMode(boolean enabled, ComponentName packageName, int userId,
+        public void setVrMode(boolean enabled, ComponentName packageName, int userId, int processId,
                 ComponentName callingPackage) {
-            VrManagerService.this.setVrMode(enabled, packageName, userId, callingPackage);
+            VrManagerService.this.setVrMode(enabled, packageName, userId, processId, callingPackage);
         }
 
         @Override
@@ -704,14 +714,16 @@
      * Note: Must be called while holding {@code mLock}.
      *
      * @param enabled new state for VR mode.
+     * @param running2dInVr true if we have a top-level 2D intent.
      * @param component new component to be bound as a VR listener.
      * @param userId user owning the component to be bound.
-     * @param calling the component currently using VR mode.
+     * @param processId the process hosting the activity specified by calling.
+     * @param calling the component currently using VR mode or a 2D intent.
      *
      * @return {@code true} if the component/user combination specified is valid.
      */
-    private boolean updateCurrentVrServiceLocked(boolean enabled, @NonNull ComponentName component,
-            int userId, ComponentName calling) {
+    private boolean updateCurrentVrServiceLocked(boolean enabled, boolean running2dInVr,
+            @NonNull ComponentName component, int userId, int processId, ComponentName calling) {
 
         boolean sendUpdatedCaller = false;
         final long identity = Binder.clearCallingIdentity();
@@ -771,6 +783,8 @@
                 sendUpdatedCaller = true;
             }
             mCurrentVrModeComponent = calling;
+            mRunning2dInVr = running2dInVr;
+            mVrAppProcessId = processId;
 
             if (mCurrentVrModeUser != userId) {
                 mCurrentVrModeUser = userId;
@@ -788,11 +802,13 @@
 
             if (mCurrentVrService != null && sendUpdatedCaller) {
                 final ComponentName c = mCurrentVrModeComponent;
+                final boolean b = running2dInVr;
+                final int pid = processId;
                 mCurrentVrService.sendEvent(new PendingEvent() {
                     @Override
                     public void runEvent(IInterface service) throws RemoteException {
                         IVrListener l = (IVrListener) service;
-                        l.focusedActivityChanged(c);
+                        l.focusedActivityChanged(c, b, pid);
                     }
                 });
             }
@@ -1017,20 +1033,20 @@
      */
     private void consumeAndApplyPendingStateLocked(boolean disconnectIfNoPendingState) {
         if (mPendingState != null) {
-            updateCurrentVrServiceLocked(mPendingState.enabled,
-                    mPendingState.targetPackageName, mPendingState.userId,
+            updateCurrentVrServiceLocked(mPendingState.enabled, mPendingState.running2dInVr,
+                    mPendingState.targetPackageName, mPendingState.userId, mPendingState.processId,
                     mPendingState.callingPackage);
             mPendingState = null;
         } else if (disconnectIfNoPendingState) {
-            updateCurrentVrServiceLocked(false, null, 0, null);
+            updateCurrentVrServiceLocked(false, false, null, 0, -1, null);
         }
     }
 
     private void logStateLocked() {
         ComponentName currentBoundService = (mCurrentVrService == null) ? null :
             mCurrentVrService.getComponent();
-        VrState current = new VrState(mVrModeEnabled, currentBoundService, mCurrentVrModeUser,
-            mCurrentVrModeComponent, mWasDefaultGranted);
+        VrState current = new VrState(mVrModeEnabled, mRunning2dInVr, currentBoundService,
+            mCurrentVrModeUser, mVrAppProcessId, mCurrentVrModeComponent, mWasDefaultGranted);
         if (mLoggingDeque.size() == EVENT_LOG_SIZE) {
             mLoggingDeque.removeFirst();
         }
@@ -1074,27 +1090,24 @@
      * Implementation of VrManagerInternal calls.  These are callable from system services.
      */
     private void setVrMode(boolean enabled, @NonNull ComponentName targetPackageName,
-            int userId, @NonNull ComponentName callingPackage) {
+            int userId, int processId, @NonNull ComponentName callingPackage) {
 
         synchronized (mLock) {
             VrState pending;
             ComponentName targetListener;
-            ComponentName foregroundVrComponent;
 
             // If the device is in persistent VR mode, then calls to disable VR mode are ignored,
             // and the system default VR listener is used.
             boolean targetEnabledState = enabled || mPersistentVrModeEnabled;
-            if (!enabled && mPersistentVrModeEnabled) {
+            boolean running2dInVr = !enabled && mPersistentVrModeEnabled;
+            if (running2dInVr) {
                 targetListener = mDefaultVrService;
-
-                // Current foreground component isn't a VR one (in 2D app case)
-                foregroundVrComponent = null;
             } else {
                 targetListener = targetPackageName;
-                foregroundVrComponent = callingPackage;
             }
-            pending = new VrState(
-                    targetEnabledState, targetListener, userId, foregroundVrComponent);
+
+            pending = new VrState(targetEnabledState, running2dInVr, targetListener,
+                    userId, processId, callingPackage);
 
             if (!mVrModeAllowed) {
                 // We're not allowed to be in VR mode.  Make this state pending.  This will be
@@ -1119,8 +1132,8 @@
                 mPendingState = null;
             }
 
-            updateCurrentVrServiceLocked(
-                    targetEnabledState, targetListener, userId, foregroundVrComponent);
+            updateCurrentVrServiceLocked(targetEnabledState, running2dInVr, targetListener,
+                    userId, processId, callingPackage);
         }
     }
 
@@ -1129,7 +1142,7 @@
             setPersistentModeAndNotifyListenersLocked(enabled);
             // Disabling persistent mode when not showing a VR should disable the overall vr mode.
             if (!enabled && mCurrentVrModeComponent == null) {
-                setVrMode(false, null, 0, null);
+                setVrMode(false, null, 0, -1, null);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/AppWindowContainerController.java b/services/core/java/com/android/server/wm/AppWindowContainerController.java
index 86e130d..84fafe2 100644
--- a/services/core/java/com/android/server/wm/AppWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/AppWindowContainerController.java
@@ -115,41 +115,6 @@
         mListener.onWindowsGone();
     };
 
-    private final Runnable mRemoveStartingWindow = () -> {
-        StartingSurface surface = null;
-        synchronized (mWindowMap) {
-            if (mContainer == null) {
-                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "mContainer was null while trying to"
-                        + " remove starting window");
-                return;
-            }
-            if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Remove starting " + mContainer
-                    + ": startingWindow=" + mContainer.startingWindow
-                    + " startingView=" + mContainer.startingSurface);
-            if (mContainer.startingData != null) {
-                surface = mContainer.startingSurface;
-                mContainer.startingData = null;
-                mContainer.startingSurface = null;
-                mContainer.startingWindow = null;
-                mContainer.startingDisplayed = false;
-                if (surface == null && DEBUG_STARTING_WINDOW) {
-                    Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
-                            + "remove");
-                }
-            } else if (DEBUG_STARTING_WINDOW) {
-                Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
-                        + mContainer);
-            }
-        }
-        if (surface != null) {
-            try {
-                surface.remove();
-            } catch (Exception e) {
-                Slog.w(TAG_WM, "Exception when removing starting window", e);
-            }
-        }
-    };
-
     private final Runnable mAddStartingWindow = () -> {
         final StartingData startingData;
         final AppWindowToken container;
@@ -665,13 +630,6 @@
 
     void removeStartingWindow() {
         synchronized (mWindowMap) {
-            if (mHandler.hasCallbacks(mRemoveStartingWindow)) {
-                // Already scheduled.
-                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Trying to remove starting window but "
-                        + "already scheduled");
-                return;
-            }
-
             if (mContainer.startingWindow == null) {
                 if (mContainer.startingData != null) {
                     // Starting window has not been added yet, but it is scheduled to be added.
@@ -683,9 +641,39 @@
                 return;
             }
 
+            final StartingSurface surface;
+            if (mContainer.startingData != null) {
+                surface = mContainer.startingSurface;
+                mContainer.startingData = null;
+                mContainer.startingSurface = null;
+                mContainer.startingWindow = null;
+                mContainer.startingDisplayed = false;
+                if (surface == null && DEBUG_STARTING_WINDOW) {
+                    Slog.v(TAG_WM, "startingWindow was set but startingSurface==null, couldn't "
+                            + "remove");
+                }
+            } else {
+                if (DEBUG_STARTING_WINDOW) {
+                    Slog.v(TAG_WM, "Tried to remove starting window but startingWindow was null:"
+                            + mContainer);
+                }
+                return;
+            }
+
             if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Schedule remove starting " + mContainer
-                    + " startingWindow=" + mContainer.startingWindow);
-            mHandler.post(mRemoveStartingWindow);
+                    + " startingWindow=" + mContainer.startingWindow
+                    + " startingView=" + mContainer.startingSurface);
+
+            // Use the same thread to remove the window as we used to add it, as otherwise we end up
+            // with things in the view hierarchy being called from different threads.
+            mHandler.post(() -> {
+                if (DEBUG_STARTING_WINDOW) Slog.v(TAG_WM, "Removing startingView=" + surface);
+                try {
+                    surface.remove();
+                } catch (Exception e) {
+                    Slog.w(TAG_WM, "Exception when removing starting window", e);
+                }
+            });
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/AppWindowToken.java b/services/core/java/com/android/server/wm/AppWindowToken.java
index b9d02a9..63890bf 100644
--- a/services/core/java/com/android/server/wm/AppWindowToken.java
+++ b/services/core/java/com/android/server/wm/AppWindowToken.java
@@ -431,11 +431,18 @@
                 mEnteringAnimation = true;
                 mService.mActivityManagerAppTransitionNotifier.onAppTransitionFinishedLocked(token);
             }
+
             // If we are hidden but there is no delay needed we immediately
             // apply the Surface transaction so that the ActivityManager
-            // can have some guarantee on the Surface state
-            // following setting the visibility.
-            if (hidden && !delayed) {
+            // can have some guarantee on the Surface state following
+            // setting the visibility. This captures cases like dismissing
+            // the docked or pinned stack where there is no app transition.
+            //
+            // In the case of a "Null" animation, there will be
+            // no animation but there will still be a transition set.
+            // We still need to delay hiding the surface such that it
+            // can be synchronized with showing the next surface in the transition.
+            if (hidden && !delayed && !mService.mAppTransition.isTransitionSet()) {
                 SurfaceControl.openTransaction();
                 for (int i = mChildren.size() - 1; i >= 0; i--) {
                     mChildren.get(i).mWinAnimator.hide("immediately hidden");
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 05f4626..a37b2e5 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -2992,14 +2992,14 @@
                 // Don't include wallpaper in bounds calculation
                 if (!w.mIsWallpaper && !mutableIncludeFullDisplay.value) {
                     if (includeDecor) {
-                        final TaskStack stack = w.getStack();
-                        if (stack != null) {
-                            stack.getBounds(frame);
-                        }
+                        final Task task = w.getTask();
+                        if (task != null) {
+                            task.getBounds(frame);
+                        } else {
 
-                        // We want to screenshot with the exact bounds of the surface of the app. Thus,
-                        // intersect it with the frame.
-                        frame.intersect(w.mFrame);
+                            // No task bounds? Too bad! Ain't no screenshot then.
+                            return true;
+                        }
                     } else {
                         final Rect wf = w.mFrame;
                         final Rect cr = w.mContentInsets;
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index cc3b146..e5055e9 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -624,6 +624,17 @@
         return token != null ? token.findMainWindow() : null;
     }
 
+    AppWindowToken getTopFullscreenAppToken() {
+        for (int i = mChildren.size() - 1; i >= 0; i--) {
+            final AppWindowToken token = mChildren.get(i);
+            final WindowState win = token.findMainWindow();
+            if (win != null && win.mAttrs.isFullscreen()) {
+                return token;
+            }
+        }
+        return null;
+    }
+
     AppWindowToken getTopVisibleAppToken() {
         for (int i = mChildren.size() - 1; i >= 0; i--) {
             final AppWindowToken token = mChildren.get(i);
diff --git a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
index 469dab4..d7f0496 100644
--- a/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
+++ b/services/core/java/com/android/server/wm/TaskSnapshotSurface.java
@@ -151,14 +151,27 @@
         final int currentOrientation;
         synchronized (service.mWindowMap) {
             final WindowState mainWindow = token.findMainWindow();
-            if (mainWindow == null) {
+            final Task task = token.getTask();
+            if (task == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find task for token="
+                        + token);
+                return null;
+            }
+            final AppWindowToken topFullscreenToken = token.getTask().getTopFullscreenAppToken();
+            if (topFullscreenToken == null) {
+                Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find top fullscreen for task="
+                        + task);
+                return null;
+            }
+            final WindowState topFullscreenWindow = topFullscreenToken.findMainWindow();
+            if (mainWindow == null || topFullscreenWindow == null) {
                 Slog.w(TAG, "TaskSnapshotSurface.create: Failed to find main window for token="
                         + token);
                 return null;
             }
-            sysUiVis = mainWindow.getSystemUiVisibility();
-            windowFlags = mainWindow.getAttrs().flags;
-            windowPrivateFlags = mainWindow.getAttrs().privateFlags;
+            sysUiVis = topFullscreenWindow.getSystemUiVisibility();
+            windowFlags = topFullscreenWindow.getAttrs().flags;
+            windowPrivateFlags = topFullscreenWindow.getAttrs().privateFlags;
 
             layoutParams.dimAmount = mainWindow.getAttrs().dimAmount;
             layoutParams.type = TYPE_APPLICATION_STARTING;
@@ -172,22 +185,17 @@
             layoutParams.width = LayoutParams.MATCH_PARENT;
             layoutParams.height = LayoutParams.MATCH_PARENT;
             layoutParams.systemUiVisibility = sysUiVis;
-            final Task task = token.getTask();
-            if (task != null) {
-                layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
+            layoutParams.setTitle(String.format(TITLE_FORMAT, task.mTaskId));
 
-                final TaskDescription taskDescription = task.getTaskDescription();
-                if (taskDescription != null) {
-                    backgroundColor = taskDescription.getBackgroundColor();
-                    statusBarColor = taskDescription.getStatusBarColor();
-                    navigationBarColor = taskDescription.getNavigationBarColor();
-                }
-                taskBounds = new Rect();
-                task.getBounds(taskBounds);
-            } else {
-                taskBounds = null;
+            final TaskDescription taskDescription = task.getTaskDescription();
+            if (taskDescription != null) {
+                backgroundColor = taskDescription.getBackgroundColor();
+                statusBarColor = taskDescription.getStatusBarColor();
+                navigationBarColor = taskDescription.getNavigationBarColor();
             }
-            currentOrientation = mainWindow.getConfiguration().orientation;
+            taskBounds = new Rect();
+            task.getBounds(taskBounds);
+            currentOrientation = topFullscreenWindow.getConfiguration().orientation;
         }
         try {
             final int res = session.addToDisplay(window, window.mSeq, layoutParams,
diff --git a/services/core/java/com/android/server/wm/TaskWindowContainerController.java b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
index 9f02485..54a6cc0 100644
--- a/services/core/java/com/android/server/wm/TaskWindowContainerController.java
+++ b/services/core/java/com/android/server/wm/TaskWindowContainerController.java
@@ -80,7 +80,9 @@
             final Task task = createTask(taskId, stack, userId, bounds, overrideConfig, resizeMode,
                     supportsPictureInPicture, homeTask, taskDescription);
             final int position = toTop ? POSITION_TOP : POSITION_BOTTOM;
-            stack.addTask(task, position, showForAllUsers, true /* moveParents */);
+            // We only want to move the parents to the parents if we are creating this task at the
+            // top of its stack.
+            stack.addTask(task, position, showForAllUsers, toTop /* moveParents */);
         }
     }
 
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 17e87a0..5bd5e21 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2403,7 +2403,7 @@
     }
 
     boolean okToAnimate() {
-        return okToDisplay() && mPolicy.isInteractive();
+        return okToDisplay() && mPolicy.okToAnimate();
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
index 82c862f..6909892 100644
--- a/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
+++ b/services/core/java/com/android/server/wm/WindowSurfacePlacer.java
@@ -233,7 +233,7 @@
      */
     int handleAppTransitionReadyLocked() {
         int appsCount = mService.mOpeningApps.size();
-        if (!transitionGoodToGo(appsCount)) {
+        if (!transitionGoodToGo(appsCount, mTempTransitionReasons)) {
             return 0;
         }
         Trace.traceBegin(Trace.TRACE_TAG_WINDOW_MANAGER, "AppTransitionReady");
@@ -375,6 +375,9 @@
                 true /*updateInputWindows*/);
         mService.mFocusMayChange = false;
 
+        mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING,
+                mTempTransitionReasons.clone()).sendToTarget();
+
         Trace.traceEnd(Trace.TRACE_TAG_WINDOW_MANAGER);
 
         return layoutRedo | FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_CONFIG;
@@ -499,7 +502,7 @@
         }
     }
 
-    private boolean transitionGoodToGo(int appsCount) {
+    private boolean transitionGoodToGo(int appsCount, SparseIntArray outReasons) {
         if (DEBUG_APP_TRANSITIONS) Slog.v(TAG,
                 "Checking " + appsCount + " opening apps (frozen="
                         + mService.mDisplayFrozen + " timeout="
@@ -508,7 +511,7 @@
             mService.mAnimator.getScreenRotationAnimationLocked(
                     Display.DEFAULT_DISPLAY);
 
-        final SparseIntArray reasons = mTempTransitionReasons;
+        outReasons.clear();
         if (!mService.mAppTransition.isTimeout()) {
             // Imagine the case where we are changing orientation due to an app transition, but a previous
             // orientation change is still in progress. We won't process the orientation change
@@ -542,10 +545,10 @@
                 final TaskStack stack = wtoken.getStack();
                 final int stackId = stack != null ? stack.mStackId : INVALID_STACK_ID;
                 if (allDrawn) {
-                    reasons.put(stackId, drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN
+                    outReasons.put(stackId, drawnBeforeRestoring ? APP_TRANSITION_WINDOWS_DRAWN
                             : APP_TRANSITION_SAVED_SURFACE);
                 } else {
-                    reasons.put(stackId, wtoken.startingData instanceof SplashScreenStartingData
+                    outReasons.put(stackId, wtoken.startingData instanceof SplashScreenStartingData
                             ? APP_TRANSITION_SPLASH_SCREEN
                             : APP_TRANSITION_SNAPSHOT);
                 }
@@ -569,13 +572,10 @@
             boolean wallpaperReady = !mWallpaperControllerLocked.isWallpaperVisible() ||
                     mWallpaperControllerLocked.wallpaperTransitionReady();
             if (wallpaperReady) {
-                mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reasons.clone())
-                        .sendToTarget();
                 return true;
             }
             return false;
         }
-        mService.mH.obtainMessage(NOTIFY_APP_TRANSITION_STARTING, reasons.clone()).sendToTarget();
         return true;
     }
 
diff --git a/services/core/jni/com_android_server_am_BatteryStatsService.cpp b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
index 2dfd8b9..413f430 100644
--- a/services/core/jni/com_android_server_am_BatteryStatsService.cpp
+++ b/services/core/jni/com_android_server_am_BatteryStatsService.cpp
@@ -301,30 +301,17 @@
             if (status != Status::SUCCESS)
                 return;
 
-            for (size_t i = 0; i < subsystems.size(); i++) {
-                int added;
-                const PowerStateSubsystem &subsystem = subsystems[i];
-
-                added = snprintf(offset, remaining,
-                                 "subsystem_%zu name=%s ", i + 1, subsystem.name.c_str());
-                if (added < 0) {
-                    break;
-                }
-
-                if (added > remaining) {
-                    added = remaining;
-                }
-
+            if (subsystems.size() > 0) {
+                int added = snprintf(offset, remaining, "SubsystemPowerState ");
                 offset += added;
                 remaining -= added;
                 total_added += added;
 
-                for (size_t j = 0; j < subsystem.states.size(); j++) {
-                    const PowerStateSubsystemSleepState& state = subsystem.states[j];
+                for (size_t i = 0; i < subsystems.size(); i++) {
+                    const PowerStateSubsystem &subsystem = subsystems[i];
+
                     added = snprintf(offset, remaining,
-                                     "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " last entry TS(ms)=%" PRIu64 " ",
-                                     j + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
-                                     state.totalTransitions, state.lastEntryTimestampMs);
+                                     "subsystem_%zu name=%s ", i + 1, subsystem.name.c_str());
                     if (added < 0) {
                         break;
                     }
@@ -336,14 +323,33 @@
                     offset += added;
                     remaining -= added;
                     total_added += added;
-                }
 
-                if (remaining <= 0) {
-                    /* rewrite NULL character*/
-                    offset--;
-                    total_added--;
-                    ALOGE("PowerHal: buffer not enough");
-                    break;
+                    for (size_t j = 0; j < subsystem.states.size(); j++) {
+                        const PowerStateSubsystemSleepState& state = subsystem.states[j];
+                        added = snprintf(offset, remaining,
+                                         "state_%zu name=%s time=%" PRIu64 " count=%" PRIu64 " last entry=%" PRIu64 " ",
+                                         j + 1, state.name.c_str(), state.residencyInMsecSinceBoot,
+                                         state.totalTransitions, state.lastEntryTimestampMs);
+                        if (added < 0) {
+                            break;
+                        }
+
+                        if (added > remaining) {
+                            added = remaining;
+                        }
+
+                        offset += added;
+                        remaining -= added;
+                        total_added += added;
+                    }
+
+                    if (remaining <= 0) {
+                        /* rewrite NULL character*/
+                        offset--;
+                        total_added--;
+                        ALOGE("PowerHal: buffer not enough");
+                        break;
+                    }
                 }
             }
         }
diff --git a/services/core/jni/com_android_server_power_PowerManagerService.cpp b/services/core/jni/com_android_server_power_PowerManagerService.cpp
index 23e3f67..3ce9916 100644
--- a/services/core/jni/com_android_server_power_PowerManagerService.cpp
+++ b/services/core/jni/com_android_server_power_PowerManagerService.cpp
@@ -63,7 +63,7 @@
 static nsecs_t gLastEventTime[USER_ACTIVITY_EVENT_LAST + 1];
 
 // Throttling interval for user activity calls.
-static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 500 * 1000000L; // 500ms
+static const nsecs_t MIN_TIME_BETWEEN_USERACTIVITIES = 100 * 1000000L; // 100ms
 
 // ----------------------------------------------------------------------------
 
@@ -103,19 +103,6 @@
 }
 
 void android_server_PowerManagerService_userActivity(nsecs_t eventTime, int32_t eventType) {
-    // Tell the power HAL when user activity occurs.
-    gPowerHalMutex.lock();
-    if (getPowerHal()) {
-        Return<void> ret;
-        if (gPowerHalV1_1 != nullptr) {
-            ret = gPowerHalV1_1->powerHintAsync(PowerHint::INTERACTION, 0);
-        } else {
-            ret = gPowerHalV1_0->powerHint(PowerHint::INTERACTION, 0);
-        }
-        processReturn(ret, "powerHint");
-    }
-    gPowerHalMutex.unlock();
-
     if (gPowerManagerServiceObj) {
         // Throttle calls into user activity by event type.
         // We're a little conservative about argument checking here in case the caller
@@ -130,6 +117,21 @@
                 return;
             }
             gLastEventTime[eventType] = eventTime;
+
+
+            // Tell the power HAL when user activity occurs.
+            gPowerHalMutex.lock();
+            if (getPowerHal()) {
+              Return<void> ret;
+              if (gPowerHalV1_1 != nullptr) {
+                ret = gPowerHalV1_1->powerHintAsync(PowerHint::INTERACTION, 0);
+              } else {
+                ret = gPowerHalV1_0->powerHint(PowerHint::INTERACTION, 0);
+              }
+              processReturn(ret, "powerHint");
+            }
+            gPowerHalMutex.unlock();
+
         }
 
         JNIEnv* env = AndroidRuntime::getJNIEnv();
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index c9be3a2..a902a19 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -100,7 +100,6 @@
 import com.android.server.power.ShutdownThread;
 import com.android.server.radio.RadioService;
 import com.android.server.restrictions.RestrictionsManagerService;
-import com.android.server.retaildemo.RetailDemoModeService;
 import com.android.server.security.KeyAttestationApplicationIdProviderService;
 import com.android.server.security.KeyChainSystemService;
 import com.android.server.soundtrigger.SoundTriggerService;
@@ -1551,10 +1550,6 @@
         mmsService = mSystemServiceManager.startService(MmsServiceBroker.class);
         traceEnd();
 
-        traceBeginAndSlog("StartRetailDemoModeService");
-        mSystemServiceManager.startService(RetailDemoModeService.class);
-        traceEnd();
-
         if (mPackageManager.hasSystemFeature(PackageManager.FEATURE_AUTOFILL)) {
             traceBeginAndSlog("StartAutoFillService");
             mSystemServiceManager.startService(AUTO_FILL_MANAGER_SERVICE_CLASS);
diff --git a/services/net/java/android/net/apf/ApfFilter.java b/services/net/java/android/net/apf/ApfFilter.java
index e4c6690..8cb2df7 100644
--- a/services/net/java/android/net/apf/ApfFilter.java
+++ b/services/net/java/android/net/apf/ApfFilter.java
@@ -179,6 +179,7 @@
     private static final int ETH_HEADER_LEN = 14;
     private static final int ETH_DEST_ADDR_OFFSET = 0;
     private static final int ETH_ETHERTYPE_OFFSET = 12;
+    private static final int ETH_TYPE_MIN = 0x0600;
     private static final byte[] ETH_BROADCAST_MAC_ADDRESS =
             {(byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff };
     // TODO: Make these offsets relative to end of link-layer header; don't include ETH_HEADER_LEN.
@@ -236,6 +237,7 @@
     private final IpManager.Callback mIpManagerCallback;
     private final NetworkInterface mNetworkInterface;
     private final IpConnectivityLog mMetricsLog;
+
     @VisibleForTesting
     byte[] mHardwareAddress;
     @VisibleForTesting
@@ -244,6 +246,7 @@
     private long mUniqueCounter;
     @GuardedBy("this")
     private boolean mMulticastFilter;
+    private final boolean mDrop802_3Frames;
     // Our IPv4 address, if we have just one, otherwise null.
     @GuardedBy("this")
     private byte[] mIPv4Address;
@@ -253,11 +256,13 @@
 
     @VisibleForTesting
     ApfFilter(ApfCapabilities apfCapabilities, NetworkInterface networkInterface,
-            IpManager.Callback ipManagerCallback, boolean multicastFilter, IpConnectivityLog log) {
+            IpManager.Callback ipManagerCallback, boolean multicastFilter,
+            boolean ieee802_3Filter, IpConnectivityLog log) {
         mApfCapabilities = apfCapabilities;
         mIpManagerCallback = ipManagerCallback;
         mNetworkInterface = networkInterface;
         mMulticastFilter = multicastFilter;
+        mDrop802_3Frames = ieee802_3Filter;
         mMetricsLog = log;
 
         // TODO: ApfFilter should not generate programs until IpManager sends provisioning success.
@@ -885,6 +890,7 @@
     /**
      * Begin generating an APF program to:
      * <ul>
+     * <li>Drop/Pass 802.3 frames (based on policy)
      * <li>Drop ARP requests not for us, if mIPv4Address is set,
      * <li>Drop IPv4 broadcast packets, except DHCP destined to our MAC,
      * <li>Drop IPv4 multicast packets, if mMulticastFilter,
@@ -906,6 +912,8 @@
 
         // Here's a basic summary of what the initial program does:
         //
+        // if it's a 802.3 Frame (ethtype < 0x0600):
+        //    drop or pass based on configurations
         // if it's ARP:
         //   insert ARP filter to drop or pass these appropriately
         // if it's IPv4:
@@ -916,9 +924,15 @@
         //   pass
         // insert IPv6 filter to drop, pass, or fall off the end for ICMPv6 packets
 
+        gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
+
+        if (mDrop802_3Frames) {
+            // drop 802.3 frames (ethtype < 0x0600)
+            gen.addJumpIfR0LessThan(ETH_TYPE_MIN, gen.DROP_LABEL);
+        }
+
         // Add ARP filters:
         String skipArpFiltersLabel = "skipArpFilters";
-        gen.addLoad16(Register.R0, ETH_ETHERTYPE_OFFSET);
         gen.addJumpIfR0NotEquals(ETH_P_ARP, skipArpFiltersLabel);
         generateArpFilterLocked(gen);
         gen.defineLabel(skipArpFiltersLabel);
@@ -1101,7 +1115,7 @@
      */
     public static ApfFilter maybeCreate(ApfCapabilities apfCapabilities,
             NetworkInterface networkInterface, IpManager.Callback ipManagerCallback,
-            boolean multicastFilter) {
+            boolean multicastFilter, boolean ieee802_3Filter) {
         if (apfCapabilities == null || networkInterface == null) return null;
         if (apfCapabilities.apfVersionSupported == 0) return null;
         if (apfCapabilities.maximumApfProgramSize < 512) {
@@ -1118,7 +1132,7 @@
             return null;
         }
         return new ApfFilter(apfCapabilities, networkInterface, ipManagerCallback,
-                multicastFilter, new IpConnectivityLog());
+                multicastFilter, ieee802_3Filter, new IpConnectivityLog());
     }
 
     public synchronized void shutdown() {
diff --git a/services/net/java/android/net/ip/IpManager.java b/services/net/java/android/net/ip/IpManager.java
index 4bd0bd2..0231991 100644
--- a/services/net/java/android/net/ip/IpManager.java
+++ b/services/net/java/android/net/ip/IpManager.java
@@ -49,6 +49,7 @@
 import android.util.SparseArray;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.R;
 import com.android.internal.util.IndentingPrintWriter;
 import com.android.internal.util.IState;
 import com.android.internal.util.State;
@@ -1286,8 +1287,12 @@
 
         @Override
         public void enter() {
+            // Get the Configuration for ApfFilter from Context
+            boolean filter802_3Frames =
+                    mContext.getResources().getBoolean(R.bool.config_apfDrop802_3Frames);
+
             mApfFilter = ApfFilter.maybeCreate(mConfiguration.mApfCapabilities, mNetworkInterface,
-                    mCallback, mMulticastFiltering);
+                    mCallback, mMulticastFiltering, filter802_3Frames);
             // TODO: investigate the effects of any multicast filtering racing/interfering with the
             // rest of this IP configuration startup.
             if (mApfFilter == null) {
diff --git a/services/profile-classes b/services/profile-classes
index b0d2da7..289b113 100644
--- a/services/profile-classes
+++ b/services/profile-classes
@@ -5085,11 +5085,6 @@
 Lcom/android/server/RescueParty$Threshold;
 Lcom/android/server/restrictions/RestrictionsManagerService;
 Lcom/android/server/restrictions/RestrictionsManagerService$RestrictionsManagerImpl;
-Lcom/android/server/retaildemo/RetailDemoModeService;
-Lcom/android/server/retaildemo/RetailDemoModeService$1;
-Lcom/android/server/retaildemo/RetailDemoModeService$Injector;
-Lcom/android/server/retaildemo/RetailDemoModeService$MainHandler;
-Lcom/android/server/retaildemo/RetailDemoModeService$SettingsObserver;
 Lcom/android/server/SamplingProfilerService;
 Lcom/android/server/SamplingProfilerService$1;
 Lcom/android/server/SamplingProfilerService$SamplingProfilerSettingsObserver;
diff --git a/services/retaildemo/Android.mk b/services/retaildemo/Android.mk
deleted file mode 100644
index 670c6bf..0000000
--- a/services/retaildemo/Android.mk
+++ /dev/null
@@ -1,12 +0,0 @@
-LOCAL_PATH := $(call my-dir)
-
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := services.retaildemo
-
-LOCAL_SRC_FILES += \
-      $(call all-java-files-under,java)
-
-LOCAL_JAVA_LIBRARIES := services.core
-
-include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java b/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
deleted file mode 100644
index 90c58d0..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/PreloadAppsInstaller.java
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * 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.retaildemo;
-
-import android.app.AppGlobals;
-import android.app.PackageInstallObserver;
-import android.content.Context;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.Bundle;
-import android.os.Environment;
-import android.os.RemoteException;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.util.ArrayMap;
-import android.util.Log;
-import android.util.Slog;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.util.ArrayUtils;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Map;
-
-/**
- * Helper class for installing preloaded APKs
- */
-class PreloadAppsInstaller {
-    private static final String SYSTEM_SERVER_PACKAGE_NAME = "android";
-    private static String TAG = PreloadAppsInstaller.class.getSimpleName();
-    private static final String PRELOAD_APK_EXT = ".apk.preload";
-    private static boolean DEBUG = Log.isLoggable(TAG, Log.DEBUG);
-
-    private final IPackageManager mPackageManager;
-    private final File preloadsAppsDirectory;
-    private final Context mContext;
-
-    private final Map<String, String> mApkToPackageMap;
-
-    PreloadAppsInstaller(Context context) {
-        this(context, AppGlobals.getPackageManager(), Environment.getDataPreloadsAppsDirectory());
-    }
-
-    @VisibleForTesting
-    PreloadAppsInstaller(Context context, IPackageManager packageManager, File preloadsAppsDirectory) {
-        mContext = context;
-        mPackageManager = packageManager;
-        mApkToPackageMap = Collections.synchronizedMap(new ArrayMap<>());
-        this.preloadsAppsDirectory = preloadsAppsDirectory;
-    }
-
-    void installApps(int userId) {
-        File[] files = preloadsAppsDirectory.listFiles();
-        AppInstallCounter counter = new AppInstallCounter(mContext, userId);
-        if (ArrayUtils.isEmpty(files)) {
-            counter.setExpectedAppsCount(0);
-            return;
-        }
-        int expectedCount = 0;
-        for (File file : files) {
-            String apkName = file.getName();
-            if (apkName.endsWith(PRELOAD_APK_EXT) && file.isFile()) {
-                String packageName = mApkToPackageMap.get(apkName);
-                if (packageName != null) {
-                    try {
-                        expectedCount++;
-                        installExistingPackage(packageName, userId, counter);
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Failed to install existing package " + packageName, e);
-                    }
-                } else {
-                    try {
-                        installPackage(file, userId, counter);
-                        expectedCount++;
-                    } catch (Exception e) {
-                        Slog.e(TAG, "Failed to install package from " + file, e);
-                    }
-                }
-            }
-        }
-        counter.setExpectedAppsCount(expectedCount);
-    }
-
-    private void installExistingPackage(String packageName, int userId,
-            AppInstallCounter counter) {
-        if (DEBUG) {
-            Log.d(TAG, "installExistingPackage " + packageName + " u" + userId);
-        }
-        try {
-            mPackageManager.installExistingPackageAsUser(packageName, userId,
-                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
-        } catch (RemoteException e) {
-            throw e.rethrowFromSystemServer();
-        } finally {
-            counter.appInstallFinished();
-        }
-    }
-
-    private void installPackage(File file, final int userId, AppInstallCounter counter)
-            throws IOException, RemoteException {
-        final String apkName = file.getName();
-        if (DEBUG) {
-            Log.d(TAG, "installPackage " + apkName + " u" + userId);
-        }
-        mPackageManager.installPackageAsUser(file.getPath(), new PackageInstallObserver() {
-            @Override
-            public void onPackageInstalled(String basePackageName, int returnCode, String msg,
-                    Bundle extras) {
-                if (DEBUG) {
-                    Log.d(TAG, "Package " + basePackageName + " installed u" + userId
-                            + " returnCode: " + returnCode + " msg: " + msg);
-                }
-                // Don't notify the counter for now, we'll do it in installExistingPackage
-                if (returnCode == PackageManager.INSTALL_SUCCEEDED) {
-                    mApkToPackageMap.put(apkName, basePackageName);
-                    // Install on user 0 so that the package is cached when demo user is re-created
-                    installExistingPackage(basePackageName, UserHandle.USER_SYSTEM, counter);
-                } else if (returnCode == PackageManager.INSTALL_FAILED_ALREADY_EXISTS) {
-                    // This can only happen in first session after a reboot
-                    if (!mApkToPackageMap.containsKey(apkName)) {
-                        mApkToPackageMap.put(apkName, basePackageName);
-                    }
-                    installExistingPackage(basePackageName, userId, counter);
-                } else {
-                    Log.e(TAG, "Package " + basePackageName + " cannot be installed from "
-                            + apkName + ": " + msg + " (returnCode " + returnCode + ")");
-                    counter.appInstallFinished();
-                }
-            }
-        }.getBinder(), 0, SYSTEM_SERVER_PACKAGE_NAME, userId);
-    }
-
-    private static class AppInstallCounter {
-        private int expectedCount = -1; // -1 means expectedCount not set
-        private int finishedCount;
-        private final Context mContext;
-        private final int userId;
-
-        AppInstallCounter(Context context, int userId) {
-            mContext = context;
-            this.userId = userId;
-        }
-
-        synchronized void appInstallFinished() {
-            this.finishedCount++;
-            checkIfAllFinished();
-        }
-
-        synchronized void setExpectedAppsCount(int expectedCount) {
-            this.expectedCount = expectedCount;
-            checkIfAllFinished();
-        }
-
-        private void checkIfAllFinished() {
-            if (expectedCount == finishedCount) {
-                Log.i(TAG, "All preloads finished installing for user " + userId);
-                Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, "1", userId);
-            }
-        }
-    }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java b/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
deleted file mode 100644
index 711d4d9d..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/RetailDemoModeService.java
+++ /dev/null
@@ -1,868 +0,0 @@
-/*
- * 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.retaildemo;
-
-import android.Manifest;
-import android.app.ActivityManager;
-import android.app.ActivityManagerInternal;
-import android.app.AppGlobals;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.PendingIntent;
-import android.app.RetailDemoModeServiceInternal;
-import android.content.BroadcastReceiver;
-import android.content.ComponentName;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.DialogInterface;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.database.ContentObserver;
-import android.hardware.camera2.CameraAccessException;
-import android.hardware.camera2.CameraCharacteristics;
-import android.hardware.camera2.CameraManager;
-import android.media.AudioManager;
-import android.media.AudioSystem;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.Environment;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.Message;
-import android.os.PowerManager;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.SystemProperties;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.text.TextUtils;
-import android.util.KeyValueListParser;
-import android.util.Slog;
-
-import com.android.internal.messages.nano.SystemMessageProto.SystemMessage;
-import com.android.internal.notification.SystemNotificationChannels;
-import com.android.internal.os.BackgroundThread;
-import com.android.internal.R;
-import com.android.internal.annotations.GuardedBy;
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.logging.MetricsLogger;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.LocalServices;
-import com.android.server.PreloadsFileCacheExpirationJobService;
-import com.android.server.ServiceThread;
-import com.android.server.SystemService;
-import com.android.server.am.ActivityManagerService;
-import com.android.server.retaildemo.UserInactivityCountdownDialog.OnCountDownExpiredListener;
-
-import java.io.File;
-import java.util.ArrayList;
-
-public class RetailDemoModeService extends SystemService {
-    private static final boolean DEBUG = false;
-
-    private static final String TAG = RetailDemoModeService.class.getSimpleName();
-    private static final String DEMO_USER_NAME = "Demo";
-    private static final String ACTION_RESET_DEMO =
-            "com.android.server.retaildemo.ACTION_RESET_DEMO";
-    @VisibleForTesting
-    static final String SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED = "sys.retaildemo.enabled";
-
-    private static final int MSG_TURN_SCREEN_ON = 0;
-    private static final int MSG_INACTIVITY_TIME_OUT = 1;
-    private static final int MSG_START_NEW_SESSION = 2;
-
-    private static final long SCREEN_WAKEUP_DELAY = 2500;
-    private static final long USER_INACTIVITY_TIMEOUT_MIN = 10000;
-    private static final long USER_INACTIVITY_TIMEOUT_DEFAULT = 90000;
-    private static final long WARNING_DIALOG_TIMEOUT_DEFAULT = 0;
-    private static final long MILLIS_PER_SECOND = 1000;
-
-    @VisibleForTesting
-    static final int[] VOLUME_STREAMS_TO_MUTE = {
-            AudioSystem.STREAM_RING,
-            AudioSystem.STREAM_MUSIC
-    };
-
-    // Tron Vars
-    private static final String DEMO_SESSION_COUNT = "retail_demo_session_count";
-    private static final String DEMO_SESSION_DURATION = "retail_demo_session_duration";
-
-    boolean mDeviceInDemoMode;
-    boolean mIsCarrierDemoMode;
-    int mCurrentUserId = UserHandle.USER_SYSTEM;
-    long mUserInactivityTimeout;
-    long mWarningDialogTimeout;
-    private Injector mInjector;
-    Handler mHandler;
-    private ServiceThread mHandlerThread;
-    private String[] mCameraIdsWithFlash;
-    private PreloadAppsInstaller mPreloadAppsInstaller;
-
-    final Object mActivityLock = new Object();
-    // Whether the newly created demo user has interacted with the screen yet
-    @GuardedBy("mActivityLock")
-    boolean mUserUntouched;
-    @GuardedBy("mActivityLock")
-    long mFirstUserActivityTime;
-    @GuardedBy("mActivityLock")
-    long mLastUserActivityTime;
-
-    private boolean mSafeBootRestrictionInitialState;
-    private int mPackageVerifierEnableInitialState;
-
-    private IntentReceiver mBroadcastReceiver = null;
-
-    private final class IntentReceiver extends BroadcastReceiver {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (!mDeviceInDemoMode) {
-                return;
-            }
-            final String action = intent.getAction();
-            switch (action) {
-                case Intent.ACTION_SCREEN_OFF:
-                    mHandler.removeMessages(MSG_TURN_SCREEN_ON);
-                    mHandler.sendEmptyMessageDelayed(MSG_TURN_SCREEN_ON, SCREEN_WAKEUP_DELAY);
-                    break;
-                case ACTION_RESET_DEMO:
-                    mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-                    break;
-            }
-        }
-    };
-
-    final class MainHandler extends Handler {
-
-        MainHandler(Looper looper) {
-            super(looper, null, true);
-        }
-
-        @Override
-        public void handleMessage(Message msg) {
-            if (!mDeviceInDemoMode) {
-                return;
-            }
-            switch (msg.what) {
-                case MSG_TURN_SCREEN_ON:
-                    if (mInjector.isWakeLockHeld()) {
-                        mInjector.releaseWakeLock();
-                    }
-                    mInjector.acquireWakeLock();
-                    break;
-                case MSG_INACTIVITY_TIME_OUT:
-                    if (!mIsCarrierDemoMode && isDemoLauncherDisabled()) {
-                        Slog.i(TAG, "User inactivity timeout reached");
-                        showInactivityCountdownDialog();
-                    }
-                    break;
-                case MSG_START_NEW_SESSION:
-                    if (DEBUG) {
-                        Slog.d(TAG, "Switching to a new demo user");
-                    }
-                    removeMessages(MSG_START_NEW_SESSION);
-                    removeMessages(MSG_INACTIVITY_TIME_OUT);
-                    if (!mIsCarrierDemoMode && mCurrentUserId != UserHandle.USER_SYSTEM) {
-                        logSessionDuration();
-                    }
-
-                    final UserManager um = mInjector.getUserManager();
-                    UserInfo demoUser = null;
-                    if (mIsCarrierDemoMode) {
-                        // Re-use the existing demo user in carrier demo mode.
-                        for (UserInfo user : um.getUsers()) {
-                            if (user.isDemo()) {
-                                demoUser = user;
-                                break;
-                            }
-                        }
-                    }
-
-                    if (demoUser == null) {
-                        // User in carrier demo mode should survive reboots.
-                        final int flags = UserInfo.FLAG_DEMO
-                                | (mIsCarrierDemoMode ? 0 : UserInfo.FLAG_EPHEMERAL);
-                        demoUser = um.createUser(DEMO_USER_NAME, flags);
-                    }
-
-                    if (demoUser != null && mCurrentUserId != demoUser.id) {
-                        setupDemoUser(demoUser);
-                        mInjector.switchUser(demoUser.id);
-                    }
-                    break;
-            }
-        }
-    }
-
-    @VisibleForTesting
-    class SettingsObserver extends ContentObserver {
-
-        private final static String KEY_USER_INACTIVITY_TIMEOUT = "user_inactivity_timeout_ms";
-        private final static String KEY_WARNING_DIALOG_TIMEOUT = "warning_dialog_timeout_ms";
-
-        private final Uri mDeviceDemoModeUri = Settings.Global
-                .getUriFor(Settings.Global.DEVICE_DEMO_MODE);
-        private final Uri mDeviceProvisionedUri = Settings.Global
-                .getUriFor(Settings.Global.DEVICE_PROVISIONED);
-        private final Uri mRetailDemoConstantsUri = Settings.Global
-                .getUriFor(Settings.Global.RETAIL_DEMO_MODE_CONSTANTS);
-
-        private final KeyValueListParser mParser = new KeyValueListParser(',');
-
-        public SettingsObserver(Handler handler) {
-            super(handler);
-        }
-
-        public void register() {
-            final ContentResolver cr = mInjector.getContentResolver();
-            cr.registerContentObserver(mDeviceDemoModeUri, false, this, UserHandle.USER_SYSTEM);
-            cr.registerContentObserver(mDeviceProvisionedUri, false, this, UserHandle.USER_SYSTEM);
-            cr.registerContentObserver(mRetailDemoConstantsUri, false, this,
-                    UserHandle.USER_SYSTEM);
-        }
-
-        @Override
-        public void onChange(boolean selfChange, Uri uri) {
-            if (mRetailDemoConstantsUri.equals(uri)) {
-                refreshTimeoutConstants();
-                return;
-            }
-
-            // If device is provisioned and left demo mode - run the cleanup in demo folder
-            if (isDeviceProvisioned()) {
-                if (UserManager.isDeviceInDemoMode(getContext())) {
-                    startDemoMode();
-                } else {
-                    mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "0");
-
-                    // Run on the bg thread to not block the fg thread
-                    BackgroundThread.getHandler().post(() -> {
-                        if (!deletePreloadsFolderContents()) {
-                            Slog.w(TAG, "Failed to delete preloads folder contents");
-                        }
-                        PreloadsFileCacheExpirationJobService.schedule(mInjector.getContext());
-                    });
-
-                    stopDemoMode();
-
-                    if (mInjector.isWakeLockHeld()) {
-                        mInjector.releaseWakeLock();
-                    }
-                }
-            }
-        }
-
-        private void refreshTimeoutConstants() {
-            try {
-                mParser.setString(Settings.Global.getString(mInjector.getContentResolver(),
-                        Settings.Global.RETAIL_DEMO_MODE_CONSTANTS));
-            } catch (IllegalArgumentException exc) {
-                Slog.e(TAG, "Invalid string passed to KeyValueListParser");
-                // Consuming the exception to fall back to default values.
-            }
-            mWarningDialogTimeout = mParser.getLong(KEY_WARNING_DIALOG_TIMEOUT,
-                    WARNING_DIALOG_TIMEOUT_DEFAULT);
-            mUserInactivityTimeout = mParser.getLong(KEY_USER_INACTIVITY_TIMEOUT,
-                    USER_INACTIVITY_TIMEOUT_DEFAULT);
-            mUserInactivityTimeout = Math.max(mUserInactivityTimeout, USER_INACTIVITY_TIMEOUT_MIN);
-        }
-    }
-
-    private void showInactivityCountdownDialog() {
-        UserInactivityCountdownDialog dialog = new UserInactivityCountdownDialog(getContext(),
-                mWarningDialogTimeout, MILLIS_PER_SECOND);
-        dialog.setNegativeButtonClickListener(null);
-        dialog.setPositiveButtonClickListener(new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int which) {
-                mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-            }
-        });
-        dialog.setOnCountDownExpiredListener(new OnCountDownExpiredListener() {
-            @Override
-            public void onCountDownExpired() {
-                mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-            }
-        });
-        dialog.show();
-    }
-
-    public RetailDemoModeService(Context context) {
-        this(new Injector(context));
-    }
-
-    @VisibleForTesting
-    RetailDemoModeService(Injector injector) {
-        super(injector.getContext());
-
-        mInjector = injector;
-        synchronized (mActivityLock) {
-            mFirstUserActivityTime = mLastUserActivityTime = SystemClock.uptimeMillis();
-        }
-    }
-
-    boolean isDemoLauncherDisabled() {
-        int enabledState = PackageManager.COMPONENT_ENABLED_STATE_DEFAULT;
-        try {
-            final IPackageManager iPm = mInjector.getIPackageManager();
-            final String demoLauncherComponent =
-                    getContext().getString(R.string.config_demoModeLauncherComponent);
-            enabledState = iPm.getComponentEnabledSetting(
-                    ComponentName.unflattenFromString(demoLauncherComponent), mCurrentUserId);
-        } catch (RemoteException re) {
-            Slog.e(TAG, "Error retrieving demo launcher enabled setting", re);
-        }
-        return enabledState == PackageManager.COMPONENT_ENABLED_STATE_DISABLED;
-    }
-
-    private void setupDemoUser(UserInfo userInfo) {
-        final UserManager um = mInjector.getUserManager();
-        final UserHandle user = UserHandle.of(userInfo.id);
-        um.setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
-        um.setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
-        // Set this to false because the default is true on user creation
-        um.setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
-        // Disallow rebooting in safe mode - controlled by user 0
-        um.setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
-        if (mIsCarrierDemoMode) {
-            // Enable SMS in carrier demo mode.
-            um.setUserRestriction(UserManager.DISALLOW_SMS, false, user);
-        }
-
-        Settings.Secure.putIntForUser(mInjector.getContentResolver(),
-                Settings.Secure.SKIP_FIRST_USE_HINTS, 1, userInfo.id);
-        Settings.Global.putInt(mInjector.getContentResolver(),
-                Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-
-        grantRuntimePermissionToCamera(user);
-        clearPrimaryCallLog();
-
-        if (!mIsCarrierDemoMode) {
-            // Enable demo launcher.
-            final String demoLauncher = getContext().getString(
-                    R.string.config_demoModeLauncherComponent);
-            if (!TextUtils.isEmpty(demoLauncher)) {
-                final ComponentName componentToEnable =
-                        ComponentName.unflattenFromString(demoLauncher);
-                final String packageName = componentToEnable.getPackageName();
-                try {
-                    final IPackageManager iPm = AppGlobals.getPackageManager();
-                    iPm.setComponentEnabledSetting(componentToEnable,
-                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id);
-                    iPm.setApplicationEnabledSetting(packageName,
-                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
-                } catch (RemoteException re) {
-                    // Internal, shouldn't happen
-                }
-            }
-        } else {
-            // Set the carrier demo mode setting for the demo user.
-            final String carrierDemoModeSetting = getContext().getString(
-                    R.string.config_carrierDemoModeSetting);
-            Settings.Secure.putIntForUser(getContext().getContentResolver(),
-                    carrierDemoModeSetting, 1, userInfo.id);
-
-            // Enable packages for carrier demo mode.
-            final String packageList = getContext().getString(
-                    R.string.config_carrierDemoModePackages);
-            final String[] packageNames = packageList == null ? new String[0]
-                    : TextUtils.split(packageList, ",");
-            final IPackageManager iPm = AppGlobals.getPackageManager();
-            for (String packageName : packageNames) {
-                try {
-                    iPm.setApplicationEnabledSetting(packageName,
-                            PackageManager.COMPONENT_ENABLED_STATE_ENABLED, 0, userInfo.id, null);
-                } catch (RemoteException re) {
-                    Slog.e(TAG, "Error enabling application: " + packageName, re);
-                }
-            }
-        }
-    }
-
-    private void grantRuntimePermissionToCamera(UserHandle user) {
-        final Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-        final PackageManager pm = mInjector.getPackageManager();
-        final ResolveInfo handler = pm.resolveActivityAsUser(cameraIntent,
-                PackageManager.MATCH_DIRECT_BOOT_AWARE | PackageManager.MATCH_DIRECT_BOOT_UNAWARE,
-                user.getIdentifier());
-        if (handler == null || handler.activityInfo == null) {
-            return;
-        }
-        try {
-            pm.grantRuntimePermission(handler.activityInfo.packageName,
-                    Manifest.permission.ACCESS_FINE_LOCATION, user);
-        } catch (Exception e) {
-            // Ignore
-        }
-    }
-
-    private void clearPrimaryCallLog() {
-        final ContentResolver resolver = mInjector.getContentResolver();
-
-        // Deleting primary user call log so that it doesn't get copied to the new demo user
-        final Uri uri = CallLog.Calls.CONTENT_URI;
-        try {
-            resolver.delete(uri, null, null);
-        } catch (Exception e) {
-            Slog.w(TAG, "Deleting call log failed: " + e);
-        }
-    }
-
-    void logSessionDuration() {
-        final int sessionDuration;
-        synchronized (mActivityLock) {
-            sessionDuration = (int) ((mLastUserActivityTime - mFirstUserActivityTime) / 1000);
-        }
-        mInjector.logSessionDuration(sessionDuration);
-    }
-
-    private boolean isDeviceProvisioned() {
-        return Settings.Global.getInt(
-                mInjector.getContentResolver(), Settings.Global.DEVICE_PROVISIONED, 0) != 0;
-    }
-
-    /**
-     * Deletes contents of {@link Environment#getDataPreloadsDirectory()},
-     * but leave {@link Environment#getDataPreloadsFileCacheDirectory()}
-     * @return true if contents was sucessfully deleted
-     */
-    private boolean deletePreloadsFolderContents() {
-        final File dir = mInjector.getDataPreloadsDirectory();
-        final File[] files = FileUtils.listFilesOrEmpty(dir);
-        final File fileCacheDirectory = mInjector.getDataPreloadsFileCacheDirectory();
-        Slog.i(TAG, "Deleting contents of " + dir);
-        boolean success = true;
-        for (File file : files) {
-            if (file.isFile()) {
-                if (!file.delete()) {
-                    success = false;
-                    Slog.w(TAG, "Cannot delete file " + file);
-                }
-            } else {
-                // Do not remove file_cache dir
-                if (!file.equals(fileCacheDirectory)) {
-                    if (!FileUtils.deleteContentsAndDir(file)) {
-                        success = false;
-                        Slog.w(TAG, "Cannot delete dir and its content " + file);
-                    }
-                } else {
-                    Slog.i(TAG, "Skipping directory with file cache " + file);
-                }
-            }
-        }
-        return success;
-    }
-
-    private void registerBroadcastReceiver() {
-        if (mBroadcastReceiver != null) {
-            return;
-        }
-
-        final IntentFilter filter = new IntentFilter();
-        if (!mIsCarrierDemoMode) {
-            filter.addAction(Intent.ACTION_SCREEN_OFF);
-        }
-        filter.addAction(ACTION_RESET_DEMO);
-        mBroadcastReceiver = new IntentReceiver();
-        getContext().registerReceiver(mBroadcastReceiver, filter);
-    }
-
-    private void unregisterBroadcastReceiver() {
-        if (mBroadcastReceiver != null) {
-            getContext().unregisterReceiver(mBroadcastReceiver);
-            mBroadcastReceiver = null;
-        }
-    }
-
-    private String[] getCameraIdsWithFlash() {
-        ArrayList<String> cameraIdsList = new ArrayList<String>();
-        final CameraManager cm = mInjector.getCameraManager();
-        if (cm != null) {
-            try {
-                for (String cameraId : cm.getCameraIdList()) {
-                    CameraCharacteristics c = cm.getCameraCharacteristics(cameraId);
-                    if (Boolean.TRUE.equals(c.get(CameraCharacteristics.FLASH_INFO_AVAILABLE))) {
-                        cameraIdsList.add(cameraId);
-                    }
-                }
-            } catch (CameraAccessException e) {
-                Slog.e(TAG, "Unable to access camera while getting camera id list", e);
-            }
-        }
-        return cameraIdsList.toArray(new String[cameraIdsList.size()]);
-    }
-
-    private void muteVolumeStreams() {
-        for (int stream : VOLUME_STREAMS_TO_MUTE) {
-            mInjector.getAudioManager().setStreamVolume(stream,
-                    mInjector.getAudioManager().getStreamMinVolume(stream), 0);
-        }
-    }
-
-    private void startDemoMode() {
-        mDeviceInDemoMode = true;
-
-        mPreloadAppsInstaller = mInjector.getPreloadAppsInstaller();
-        mInjector.initializeWakeLock();
-        if (mCameraIdsWithFlash == null) {
-            mCameraIdsWithFlash = getCameraIdsWithFlash();
-        }
-        registerBroadcastReceiver();
-
-        final String carrierDemoModeSetting =
-                getContext().getString(R.string.config_carrierDemoModeSetting);
-        mIsCarrierDemoMode = !TextUtils.isEmpty(carrierDemoModeSetting)
-                && (Settings.Secure.getInt(getContext().getContentResolver(),
-                        carrierDemoModeSetting, 0) == 1);
-
-        mInjector.systemPropertiesSet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED, "1");
-        mHandler.sendEmptyMessage(MSG_START_NEW_SESSION);
-
-        mSafeBootRestrictionInitialState = mInjector.getUserManager().hasUserRestriction(
-                UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM);
-        mPackageVerifierEnableInitialState = Settings.Global.getInt(mInjector.getContentResolver(),
-                Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
-    }
-
-    private void stopDemoMode() {
-        mPreloadAppsInstaller = null;
-        mCameraIdsWithFlash = null;
-        mInjector.destroyWakeLock();
-        unregisterBroadcastReceiver();
-
-        if (mDeviceInDemoMode) {
-            mInjector.getUserManager().setUserRestriction(UserManager.DISALLOW_SAFE_BOOT,
-                    mSafeBootRestrictionInitialState, UserHandle.SYSTEM);
-            Settings.Global.putInt(mInjector.getContentResolver(),
-                        Settings.Global.PACKAGE_VERIFIER_ENABLE,
-                        mPackageVerifierEnableInitialState);
-        }
-
-        mDeviceInDemoMode = false;
-        mIsCarrierDemoMode = false;
-    }
-
-    @Override
-    public void onStart() {
-        if (DEBUG) {
-            Slog.d(TAG, "Service starting up");
-        }
-        mHandlerThread = new ServiceThread(TAG, android.os.Process.THREAD_PRIORITY_FOREGROUND,
-                false);
-        mHandlerThread.start();
-        mHandler = new MainHandler(mHandlerThread.getLooper());
-        mInjector.publishLocalService(this, mLocalService);
-    }
-
-    @Override
-    public void onBootPhase(int bootPhase) {
-        switch (bootPhase) {
-            case PHASE_THIRD_PARTY_APPS_CAN_START:
-                final SettingsObserver settingsObserver = new SettingsObserver(mHandler);
-                settingsObserver.register();
-                settingsObserver.refreshTimeoutConstants();
-                break;
-            case PHASE_BOOT_COMPLETED:
-                if (UserManager.isDeviceInDemoMode(getContext())) {
-                    startDemoMode();
-                }
-                break;
-        }
-    }
-
-    @Override
-    public void onSwitchUser(int userId) {
-        if (!mDeviceInDemoMode) {
-            return;
-        }
-        if (DEBUG) {
-            Slog.d(TAG, "onSwitchUser: " + userId);
-        }
-        final UserInfo ui = mInjector.getUserManager().getUserInfo(userId);
-        if (!ui.isDemo()) {
-            Slog.wtf(TAG, "Should not allow switch to non-demo user in demo mode");
-            return;
-        }
-        if (!mIsCarrierDemoMode && !mInjector.isWakeLockHeld()) {
-            mInjector.acquireWakeLock();
-        }
-        mCurrentUserId = userId;
-        mInjector.getActivityManagerInternal().updatePersistentConfigurationForUser(
-                mInjector.getSystemUsersConfiguration(), userId);
-
-        mInjector.turnOffAllFlashLights(mCameraIdsWithFlash);
-        muteVolumeStreams();
-        if (!mInjector.getWifiManager().isWifiEnabled()) {
-            mInjector.getWifiManager().setWifiEnabled(true);
-        }
-
-        // Disable lock screen for demo users.
-        mInjector.getLockPatternUtils().setLockScreenDisabled(true, userId);
-
-        if (!mIsCarrierDemoMode) {
-            // Show reset notification (except in carrier demo mode).
-            mInjector.getNotificationManager().notifyAsUser(TAG, SystemMessage.NOTE_RETAIL_RESET,
-                    mInjector.createResetNotification(), UserHandle.of(userId));
-
-            synchronized (mActivityLock) {
-                mUserUntouched = true;
-            }
-            mInjector.logSessionCount(1);
-            mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
-            mHandler.post(new Runnable() {
-                @Override
-                public void run() {
-                    mPreloadAppsInstaller.installApps(userId);
-                }
-            });
-        }
-    }
-
-    private RetailDemoModeServiceInternal mLocalService = new RetailDemoModeServiceInternal() {
-        private static final long USER_ACTIVITY_DEBOUNCE_TIME = 2000;
-
-        @Override
-        public void onUserActivity() {
-            if (!mDeviceInDemoMode || mIsCarrierDemoMode) {
-                return;
-            }
-            long timeOfActivity = SystemClock.uptimeMillis();
-            synchronized (mActivityLock) {
-                if (timeOfActivity < mLastUserActivityTime + USER_ACTIVITY_DEBOUNCE_TIME) {
-                    return;
-                }
-                mLastUserActivityTime = timeOfActivity;
-                if (mUserUntouched && isDemoLauncherDisabled()) {
-                    Slog.d(TAG, "retail_demo first touch");
-                    mUserUntouched = false;
-                    mFirstUserActivityTime = timeOfActivity;
-                }
-            }
-            mHandler.removeMessages(MSG_INACTIVITY_TIME_OUT);
-            mHandler.sendEmptyMessageDelayed(MSG_INACTIVITY_TIME_OUT, mUserInactivityTimeout);
-        }
-    };
-
-    static class Injector {
-        private Context mContext;
-        private UserManager mUm;
-        private PackageManager mPm;
-        private NotificationManager mNm;
-        private ActivityManagerService mAms;
-        private ActivityManagerInternal mAmi;
-        private AudioManager mAudioManager;
-        private PowerManager mPowerManager;
-        private CameraManager mCameraManager;
-        private PowerManager.WakeLock mWakeLock;
-        private WifiManager mWifiManager;
-        private Configuration mSystemUserConfiguration;
-        private PendingIntent mResetDemoPendingIntent;
-        private PreloadAppsInstaller mPreloadAppsInstaller;
-
-        Injector(Context context) {
-            mContext = context;
-        }
-
-        Context getContext() {
-            return mContext;
-        }
-
-        WifiManager getWifiManager() {
-            if (mWifiManager == null) {
-                mWifiManager = (WifiManager) mContext.getSystemService(Context.WIFI_SERVICE);
-            }
-            return mWifiManager;
-        }
-
-        UserManager getUserManager() {
-            if (mUm == null) {
-                mUm = getContext().getSystemService(UserManager.class);
-            }
-            return mUm;
-        }
-
-        void switchUser(int userId) {
-            if (mAms == null) {
-                mAms = (ActivityManagerService) ActivityManager.getService();
-            }
-            mAms.switchUser(userId);
-        }
-
-        AudioManager getAudioManager() {
-            if (mAudioManager == null) {
-                mAudioManager = getContext().getSystemService(AudioManager.class);
-            }
-            return mAudioManager;
-        }
-
-        private PowerManager getPowerManager() {
-            if (mPowerManager == null) {
-                mPowerManager = (PowerManager) getContext().getSystemService(
-                        Context.POWER_SERVICE);
-            }
-            return mPowerManager;
-        }
-
-        NotificationManager getNotificationManager() {
-            if (mNm == null) {
-                mNm = NotificationManager.from(getContext());
-            }
-            return mNm;
-        }
-
-        ActivityManagerInternal getActivityManagerInternal() {
-            if (mAmi == null) {
-                mAmi = LocalServices.getService(ActivityManagerInternal.class);
-            }
-            return mAmi;
-        }
-
-        CameraManager getCameraManager() {
-            if (mCameraManager == null) {
-                mCameraManager = (CameraManager) getContext().getSystemService(
-                        Context.CAMERA_SERVICE);
-            }
-            return mCameraManager;
-        }
-
-        PackageManager getPackageManager() {
-            if (mPm == null) {
-                mPm = getContext().getPackageManager();
-            }
-            return mPm;
-        }
-
-        IPackageManager getIPackageManager() {
-            return AppGlobals.getPackageManager();
-        }
-
-        ContentResolver getContentResolver() {
-            return getContext().getContentResolver();
-        }
-
-        PreloadAppsInstaller getPreloadAppsInstaller() {
-            if (mPreloadAppsInstaller == null) {
-                mPreloadAppsInstaller = new PreloadAppsInstaller(getContext());
-            }
-            return mPreloadAppsInstaller;
-        }
-
-        void systemPropertiesSet(String key, String value) {
-            SystemProperties.set(key, value);
-        }
-
-        void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
-            for (String cameraId : cameraIdsWithFlash) {
-                try {
-                    getCameraManager().setTorchMode(cameraId, false);
-                } catch (CameraAccessException e) {
-                    Slog.e(TAG, "Unable to access camera " + cameraId
-                            + " while turning off flash", e);
-                }
-            }
-        }
-
-        void initializeWakeLock() {
-            if (mWakeLock == null) {
-                mWakeLock = getPowerManager().newWakeLock(
-                        PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, TAG);
-            }
-        }
-
-        void destroyWakeLock() {
-            mWakeLock = null;
-        }
-
-        boolean isWakeLockHeld() {
-            return mWakeLock != null && mWakeLock.isHeld();
-        }
-
-        void acquireWakeLock() {
-            mWakeLock.acquire();
-        }
-
-        void releaseWakeLock() {
-            mWakeLock.release();
-        }
-
-        void logSessionDuration(int duration) {
-            MetricsLogger.histogram(getContext(), DEMO_SESSION_DURATION, duration);
-        }
-
-        void logSessionCount(int count) {
-            MetricsLogger.count(getContext(), DEMO_SESSION_COUNT, count);
-        }
-
-        Configuration getSystemUsersConfiguration() {
-            if (mSystemUserConfiguration == null) {
-                Settings.System.getConfiguration(getContentResolver(),
-                        mSystemUserConfiguration = new Configuration());
-            }
-            return mSystemUserConfiguration;
-        }
-
-        LockPatternUtils getLockPatternUtils() {
-            return new LockPatternUtils(getContext());
-        }
-
-        Notification createResetNotification() {
-            return new Notification.Builder(getContext(), SystemNotificationChannels.RETAIL_MODE)
-                    .setContentTitle(getContext().getString(R.string.reset_retail_demo_mode_title))
-                    .setContentText(getContext().getString(R.string.reset_retail_demo_mode_text))
-                    .setOngoing(true)
-                    .setSmallIcon(R.drawable.platlogo)
-                    .setShowWhen(false)
-                    .setVisibility(Notification.VISIBILITY_PUBLIC)
-                    .setContentIntent(getResetDemoPendingIntent())
-                    .setColor(getContext().getColor(R.color.system_notification_accent_color))
-                    .build();
-        }
-
-        private PendingIntent getResetDemoPendingIntent() {
-            if (mResetDemoPendingIntent == null) {
-                Intent intent = new Intent(ACTION_RESET_DEMO);
-                mResetDemoPendingIntent = PendingIntent.getBroadcast(getContext(), 0, intent, 0);
-            }
-            return mResetDemoPendingIntent;
-        }
-
-        File getDataPreloadsDirectory() {
-            return Environment.getDataPreloadsDirectory();
-        }
-
-        File getDataPreloadsFileCacheDirectory() {
-            return Environment.getDataPreloadsFileCacheDirectory();
-        }
-
-        void publishLocalService(RetailDemoModeService service,
-                RetailDemoModeServiceInternal localService) {
-            service.publishLocalService(RetailDemoModeServiceInternal.class, localService);
-        }
-    }
-}
diff --git a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java b/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
deleted file mode 100644
index 013eab8..0000000
--- a/services/retaildemo/java/com/android/server/retaildemo/UserInactivityCountdownDialog.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.retaildemo;
-
-import android.app.AlertDialog;
-import android.app.Dialog;
-import android.content.Context;
-import android.os.CountDownTimer;
-import android.view.WindowManager;
-import android.widget.TextView;
-
-import com.android.internal.R;
-
-public class UserInactivityCountdownDialog extends AlertDialog {
-
-    private OnCountDownExpiredListener mOnCountDownExpiredListener;
-    private CountDownTimer mCountDownTimer;
-    private long mCountDownDuration;
-    private long mRefreshInterval;
-
-    UserInactivityCountdownDialog(Context context, long duration, long refreshInterval) {
-        super(context);
-        mCountDownDuration = duration;
-        mRefreshInterval = refreshInterval;
-
-        getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ERROR);
-        WindowManager.LayoutParams attrs = getWindow().getAttributes();
-        attrs.privateFlags = WindowManager.LayoutParams.PRIVATE_FLAG_SHOW_FOR_ALL_USERS;
-        getWindow().setAttributes(attrs);
-
-        setTitle(R.string.demo_user_inactivity_timeout_title);
-        setMessage(getContext().getString(R.string.demo_user_inactivity_timeout_countdown,
-                duration));
-    }
-
-    public void setOnCountDownExpiredListener(
-            OnCountDownExpiredListener onCountDownExpiredListener) {
-        mOnCountDownExpiredListener = onCountDownExpiredListener;
-    }
-
-    public void setPositiveButtonClickListener(OnClickListener onClickListener) {
-        setButton(Dialog.BUTTON_POSITIVE,
-                getContext().getString(R.string.demo_user_inactivity_timeout_right_button),
-                onClickListener);
-    }
-
-    public void setNegativeButtonClickListener(OnClickListener onClickListener) {
-        setButton(Dialog.BUTTON_NEGATIVE,
-                getContext().getString(R.string.demo_user_inactivity_timeout_left_button),
-                onClickListener);
-    }
-
-    @Override
-    public void show() {
-        super.show();
-        final TextView messageView = findViewById(R.id.message);
-        messageView.post(new Runnable() {
-            @Override
-            public void run() {
-                mCountDownTimer = new CountDownTimer(mCountDownDuration, mRefreshInterval) {
-
-                    @Override
-                    public void onTick(long millisUntilFinished) {
-                        String msg = getContext().getString(
-                                R.string.demo_user_inactivity_timeout_countdown,
-                                millisUntilFinished / 1000);
-                        messageView.setText(msg);
-                    }
-
-                    @Override
-                    public void onFinish() {
-                        dismiss();
-                        if (mOnCountDownExpiredListener != null)
-                            mOnCountDownExpiredListener.onCountDownExpired();
-                    }
-                }.start();
-            }
-        });
-    }
-
-    @Override
-    public void onStop() {
-        if (mCountDownTimer != null) {
-            mCountDownTimer.cancel();
-        }
-    }
-
-    interface OnCountDownExpiredListener {
-        void onCountDownExpired();
-    }
-}
diff --git a/services/tests/notification/Android.mk b/services/tests/notification/Android.mk
index 940db79..79f96fd 100644
--- a/services/tests/notification/Android.mk
+++ b/services/tests/notification/Android.mk
@@ -18,7 +18,6 @@
     services.core \
     services.devicepolicy \
     services.net \
-    services.retaildemo \
     services.usage \
     guava \
     android-support-test \
diff --git a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
index 807703b..b023126 100644
--- a/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
+++ b/services/tests/notification/src/com/android/server/notification/BuzzBeepBlinkTest.java
@@ -831,6 +831,16 @@
     }
 
     @Test
+    public void testPostingGroupSuppressedDoesNotAffectRateLimiting() throws Exception {
+        NotificationRecord summary = getBeepyNotificationRecord("a", GROUP_ALERT_CHILDREN);
+        summary.getNotification().flags |= Notification.FLAG_GROUP_SUMMARY;
+
+        mService.buzzBeepBlinkLocked(summary);
+
+        verify(mUsageStats, never()).isAlertRateLimited(any());
+    }
+
+    @Test
     public void testCrossUserSoundMuted() throws Exception {
         final Notification n = new Builder(getContext(), "test")
                 .setSmallIcon(android.R.drawable.sym_def_app_icon).build();
diff --git a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
index 8b3fb18..bbec98c 100644
--- a/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/notification/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -81,7 +81,7 @@
 @RunWithLooper
 public class NotificationManagerServiceTest extends NotificationTestCase {
     private static final String TEST_CHANNEL_ID = "NotificationManagerServiceTestChannelId";
-    private final int uid = Binder.getCallingUid();
+    private final int mUid = Binder.getCallingUid();
     private NotificationManagerService mNotificationManagerService;
     private INotificationManager mBinderService;
     private NotificationManagerInternal mInternalService;
@@ -133,13 +133,13 @@
         // most tests assume badging is enabled
         Secure.putIntForUser(getContext().getContentResolver(),
                 Secure.NOTIFICATION_BADGING, 1,
-                UserHandle.getUserHandleForUid(uid).getIdentifier());
+                UserHandle.getUserHandleForUid(mUid).getIdentifier());
 
         mNotificationManagerService = new TestableNotificationManagerService(mContext);
 
         // MockPackageManager - default returns ApplicationInfo with matching calling UID
         final ApplicationInfo applicationInfo = new ApplicationInfo();
-        applicationInfo.uid = uid;
+        applicationInfo.uid = mUid;
         when(mPackageManager.getApplicationInfo(anyString(), anyInt(), anyInt()))
                 .thenReturn(applicationInfo);
         when(mPackageManagerClient.getApplicationInfoAsUser(anyString(), anyInt(), anyInt()))
@@ -151,7 +151,7 @@
         mTestableLooper = TestableLooper.get(this);
 
         mListener = mNotificationListeners.new ManagedServiceInfo(
-                null, new ComponentName(PKG, "test_class"), uid, true, null, 0);
+                null, new ComponentName(PKG, "test_class"), mUid, true, null, 0);
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
         try {
             mNotificationManagerService.init(mTestableLooper.getLooper(), mPackageManager,
@@ -183,8 +183,8 @@
                 .setGroup(groupKey)
                 .setGroupSummary(isSummary);
 
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", uid, 0,
-                nb.build(), new UserHandle(uid), null, 0);
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, id, "tag", mUid, 0,
+                nb.build(), new UserHandle(mUid), null, 0);
         return new NotificationRecord(mContext, sbn, channel);
     }
     private NotificationRecord generateNotificationRecord(NotificationChannel channel) {
@@ -202,8 +202,8 @@
         if (extender != null) {
             nb.extend(extender);
         }
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", uid, 0,
-                nb.build(), new UserHandle(uid), null, 0);
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
+                nb.build(), new UserHandle(mUid), null, 0);
         return new NotificationRecord(mContext, sbn, channel);
     }
 
@@ -211,17 +211,17 @@
     public void testCreateNotificationChannels_SingleChannel() throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
-        mBinderService.createNotificationChannels("test_pkg",
+        mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel("test_pkg", "id");
+                mBinderService.getNotificationChannel(PKG, "id");
         assertTrue(createdChannel != null);
     }
 
     @Test
     public void testCreateNotificationChannels_NullChannelThrowsException() throws Exception {
         try {
-            mBinderService.createNotificationChannels("test_pkg",
+            mBinderService.createNotificationChannels(PKG,
                     new ParceledListSlice(Arrays.asList(null)));
             fail("Exception should be thrown immediately.");
         } catch (NullPointerException e) {
@@ -235,10 +235,10 @@
                 new NotificationChannel("id1", "name", NotificationManager.IMPORTANCE_DEFAULT);
         final NotificationChannel channel2 =
                 new NotificationChannel("id2", "name", NotificationManager.IMPORTANCE_DEFAULT);
-        mBinderService.createNotificationChannels("test_pkg",
+        mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
-        assertTrue(mBinderService.getNotificationChannel("test_pkg", "id1") != null);
-        assertTrue(mBinderService.getNotificationChannel("test_pkg", "id2") != null);
+        assertTrue(mBinderService.getNotificationChannel(PKG, "id1") != null);
+        assertTrue(mBinderService.getNotificationChannel(PKG, "id2") != null);
     }
 
     @Test
@@ -246,30 +246,71 @@
             throws Exception {
         final NotificationChannel channel =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
-        mBinderService.createNotificationChannels("test_pkg",
+        mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel)));
 
         // Recreating the channel doesn't throw, but ignores importance.
         final NotificationChannel dupeChannel =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
-        mBinderService.createNotificationChannels("test_pkg",
+        mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(dupeChannel)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel("test_pkg", "id");
+                mBinderService.getNotificationChannel(PKG, "id");
         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
     }
 
     @Test
+    public void testCreateNotificationChannels_SecondCreateAllowedToDowngradeImportance()
+            throws Exception {
+        final NotificationChannel channel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+        mBinderService.createNotificationChannels(PKG,
+                new ParceledListSlice(Arrays.asList(channel)));
+
+        // Recreating with a lower importance is allowed to modify the channel.
+        final NotificationChannel dupeChannel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
+        mBinderService.createNotificationChannels(PKG,
+                new ParceledListSlice(Arrays.asList(dupeChannel)));
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel(PKG, "id");
+        assertEquals(NotificationManager.IMPORTANCE_LOW, createdChannel.getImportance());
+    }
+
+    @Test
+    public void testCreateNotificationChannels_CannotDowngradeImportanceIfAlreadyUpdated()
+            throws Exception {
+        final NotificationChannel channel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
+        mBinderService.createNotificationChannels(PKG,
+                new ParceledListSlice(Arrays.asList(channel)));
+
+        // The user modifies importance directly, can no longer be changed by the app.
+        final NotificationChannel updatedChannel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
+        mBinderService.updateNotificationChannelForPackage(PKG, mUid, updatedChannel);
+
+        // Recreating with a lower importance leaves channel unchanged.
+        final NotificationChannel dupeChannel =
+                new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_LOW);
+        mBinderService.createNotificationChannels(PKG,
+                new ParceledListSlice(Arrays.asList(dupeChannel)));
+        final NotificationChannel createdChannel =
+                mBinderService.getNotificationChannel(PKG, "id");
+        assertEquals(NotificationManager.IMPORTANCE_HIGH, createdChannel.getImportance());
+    }
+
+    @Test
     public void testCreateNotificationChannels_IdenticalChannelsInListIgnoresSecond()
             throws Exception {
         final NotificationChannel channel1 =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_DEFAULT);
         final NotificationChannel channel2 =
                 new NotificationChannel("id", "name", NotificationManager.IMPORTANCE_HIGH);
-        mBinderService.createNotificationChannels("test_pkg",
+        mBinderService.createNotificationChannels(PKG,
                 new ParceledListSlice(Arrays.asList(channel1, channel2)));
         final NotificationChannel createdChannel =
-                mBinderService.getNotificationChannel("test_pkg", "id");
+                mBinderService.getNotificationChannel(PKG, "id");
         assertEquals(NotificationManager.IMPORTANCE_DEFAULT, createdChannel.getImportance());
     }
 
@@ -300,7 +341,7 @@
     public void testEnqueuedBlockedNotifications_blockedApp() throws Exception {
         when(mPackageManager.isPackageSuspendedForUser(anyString(), anyInt())).thenReturn(false);
 
-        mBinderService.setNotificationsEnabledForPackage(PKG, uid, false);
+        mBinderService.setNotificationsEnabledForPackage(PKG, mUid, false);
 
         final StatusBarNotification sbn = generateNotificationRecord(null).sbn;
         mBinderService.enqueueNotificationWithTag(PKG, "opPkg", "tag",
@@ -381,7 +422,7 @@
                 n.sbn.getId(), n.sbn.getNotification(), n.sbn.getUserId());
         waitForIdle();
 
-        mNotificationManagerService.mNotificationDelegate.onClearAll(uid, Binder.getCallingPid(),
+        mNotificationManagerService.mNotificationDelegate.onClearAll(mUid, Binder.getCallingPid(),
                 n.getUserId());
         waitForIdle();
         StatusBarNotification[] notifs =
@@ -607,7 +648,7 @@
     public void testCreateChannelNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
@@ -632,7 +673,7 @@
     public void testCreateChannelGroupNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         NotificationChannelGroup group1 = new NotificationChannelGroup("a", "b");
         NotificationChannelGroup group2 = new NotificationChannelGroup("n", "m");
@@ -652,7 +693,7 @@
     public void testUpdateChannelNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         mTestNotificationChannel.setLightColor(Color.CYAN);
         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
@@ -670,7 +711,7 @@
     public void testDeleteChannelNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         when(mRankingHelper.getNotificationChannel(eq(PKG), anyInt(),
                 eq(mTestNotificationChannel.getId()), anyBoolean()))
@@ -686,7 +727,7 @@
     public void testDeleteChannelGroupNotifyListener() throws Exception {
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         NotificationChannelGroup ncg = new NotificationChannelGroup("a", "b/c");
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         when(mRankingHelper.getNotificationChannelGroup(eq(ncg.getId()), eq(PKG), anyInt()))
@@ -703,7 +744,7 @@
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
         mBinderService.updateNotificationChannelFromPrivilegedListener(
                 null, PKG, Process.myUserHandle(), mTestNotificationChannel);
@@ -719,7 +760,7 @@
     public void testUpdateNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
         try {
             mBinderService.updateNotificationChannelFromPrivilegedListener(
@@ -741,7 +782,7 @@
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
         mListener.component = new ComponentName(PKG, PKG);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
@@ -767,7 +808,7 @@
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
         mBinderService.getNotificationChannelsFromPrivilegedListener(
                 null, PKG, Process.myUserHandle());
@@ -780,7 +821,7 @@
     public void testGetNotificationChannelFromPrivilegedListener_noAccess() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
         try {
             mBinderService.getNotificationChannelsFromPrivilegedListener(
@@ -799,7 +840,7 @@
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
@@ -821,7 +862,7 @@
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
         associations.add("a");
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
         mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
                 null, PKG, Process.myUserHandle());
@@ -833,7 +874,7 @@
     public void testGetNotificationChannelGroupsFromPrivilegedListener_noAccess() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
 
         try {
             mBinderService.getNotificationChannelGroupsFromPrivilegedListener(
@@ -850,7 +891,7 @@
     public void testGetNotificationChannelGroupsFromPrivilegedListener_badUser() throws Exception {
         mNotificationManagerService.setRankingHelper(mRankingHelper);
         List<String> associations = new ArrayList<>();
-        when(mCompanionMgr.getAssociations(PKG, uid)).thenReturn(associations);
+        when(mCompanionMgr.getAssociations(PKG, mUid)).thenReturn(associations);
         mListener = mock(ManagedServices.ManagedServiceInfo.class);
         when(mListener.enabledAndUserMatches(anyInt())).thenReturn(false);
         when(mNotificationListeners.checkServiceTokenLocked(any())).thenReturn(mListener);
@@ -1020,8 +1061,8 @@
                 .setColorized(true)
                 .setFlag(Notification.FLAG_CAN_COLORIZE, true)
                 .setSmallIcon(android.R.drawable.sym_def_app_icon);
-        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", uid, 0,
-                nb.build(), new UserHandle(uid), null, 0);
+        StatusBarNotification sbn = new StatusBarNotification(PKG, PKG, 1, "tag", mUid, 0,
+                nb.build(), new UserHandle(mUid), null, 0);
         NotificationRecord nr = new NotificationRecord(mContext, sbn, mTestNotificationChannel);
 
         mBinderService.enqueueNotificationWithTag(PKG, PKG, null,
@@ -1037,11 +1078,13 @@
     @Test
     public void testGetNotificationCountLocked() throws Exception {
         for (int i = 0; i < 20; i++) {
-            NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, null, false);
+            NotificationRecord r =
+                    generateNotificationRecord(mTestNotificationChannel, i, null, false);
             mNotificationManagerService.addEnqueuedNotification(r);
         }
         for (int i = 0; i < 20; i++) {
-            NotificationRecord r = generateNotificationRecord(mTestNotificationChannel, i, null, false);
+            NotificationRecord r =
+                    generateNotificationRecord(mTestNotificationChannel, i, null, false);
             mNotificationManagerService.addNotification(r);
         }
 
@@ -1051,19 +1094,23 @@
                 .setSmallIcon(android.R.drawable.sym_def_app_icon)
                 .build();
 
-        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", uid, 0,
-                n, new UserHandle(uid), null, 0);
+        StatusBarNotification sbn = new StatusBarNotification("a", "a", 0, "tag", mUid, 0,
+                n, new UserHandle(mUid), null, 0);
         NotificationRecord otherPackage =
                 new NotificationRecord(mContext, sbn, mTestNotificationChannel);
         mNotificationManagerService.addEnqueuedNotification(otherPackage);
         mNotificationManagerService.addNotification(otherPackage);
 
         // Same notifications are enqueued as posted, everything counts b/c id and tag don't match
-        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, new UserHandle(uid).getIdentifier(), 0, null));
-        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(PKG, new UserHandle(uid).getIdentifier(), 0, "tag2"));
-        assertEquals(2, mNotificationManagerService.getNotificationCountLocked("a", new UserHandle(uid).getIdentifier(), 0, "banana"));
+        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(
+                PKG, new UserHandle(mUid).getIdentifier(), 0, null));
+        assertEquals(40, mNotificationManagerService.getNotificationCountLocked(
+                PKG, new UserHandle(mUid).getIdentifier(), 0, "tag2"));
+        assertEquals(2, mNotificationManagerService.getNotificationCountLocked(
+                "a", new UserHandle(mUid).getIdentifier(), 0, "banana"));
 
         // exclude a known notification - it's excluded from only the posted list, not enqueued
-        assertEquals(39, mNotificationManagerService.getNotificationCountLocked(PKG, new UserHandle(uid).getIdentifier(), 0, "tag"));
+        assertEquals(39, mNotificationManagerService.getNotificationCountLocked(
+                PKG, new UserHandle(mUid).getIdentifier(), 0, "tag"));
     }
 }
diff --git a/services/tests/servicestests/Android.mk b/services/tests/servicestests/Android.mk
index 2c3283c..e3a6dae 100644
--- a/services/tests/servicestests/Android.mk
+++ b/services/tests/servicestests/Android.mk
@@ -19,7 +19,6 @@
     services.core \
     services.devicepolicy \
     services.net \
-    services.retaildemo \
     services.usage \
     guava \
     android-support-test \
diff --git a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
index 984a484..ea207f1 100644
--- a/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/TaskPersisterTest.java
@@ -58,7 +58,7 @@
     }
 
     public void testTaskIdsPersistence() {
-        SparseBooleanArray taskIdsOnFile = mTaskPersister.loadPersistedTaskIdsForUser(testUserId);
+        SparseBooleanArray taskIdsOnFile = new SparseBooleanArray();
         for (int i = 0; i < 100; i++) {
             taskIdsOnFile.put(getRandomTaskIdForUser(testUserId), true);
         }
diff --git a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
index 1964cad..b656d5e 100644
--- a/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/UserManagerTest.java
@@ -53,8 +53,7 @@
 
     // Packages which are used during tests.
     private static final String[] PACKAGES = new String[] {
-            "com.android.egg",
-            "com.android.retaildemo"
+            "com.android.egg"
     };
 
     private final Object mUserRemoveLock = new Object();
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
deleted file mode 100644
index cf27a50..0000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/PreloadAppsInstallerTest.java
+++ /dev/null
@@ -1,164 +0,0 @@
-/*
- * 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.retaildemo;
-
-import static org.junit.Assert.assertEquals;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.pm.IPackageInstallObserver2;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.os.FileUtils;
-import android.os.UserHandle;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentResolver;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-
-import java.io.File;
-import java.util.ArrayList;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class PreloadAppsInstallerTest {
-    private static final int TEST_DEMO_USER = 111;
-
-    private Context mContext;
-    private @Mock IPackageManager mIpm;
-    private MockContentResolver mContentResolver;
-    private File mPreloadsAppsDirectory;
-    private String[] mPreloadedApps =
-            new String[] {"test1.apk.preload", "test2.apk.preload", "test3.apk.preload"};
-    private ArrayList<String> mPreloadedAppPaths = new ArrayList<>();
-
-    private PreloadAppsInstaller mInstaller;
-
-    @BeforeClass
-    @AfterClass
-    public static void clearSettingsProvider() {
-        FakeSettingsProvider.clearSettingsProvider();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
-        mContentResolver = new MockContentResolver(mContext);
-        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
-        when(mContext.getContentResolver()).thenReturn(mContentResolver);
-        initializePreloadedApps();
-        Settings.Secure.putStringForUser(mContentResolver,
-                Settings.Secure.DEMO_USER_SETUP_COMPLETE, "0", TEST_DEMO_USER);
-
-        mInstaller = new PreloadAppsInstaller(mContext, mIpm, mPreloadsAppsDirectory);
-    }
-
-    private void initializePreloadedApps() throws Exception {
-        mPreloadsAppsDirectory = new File(InstrumentationRegistry.getContext().getFilesDir(),
-                 "test_preload_apps_dir");
-        mPreloadsAppsDirectory.mkdir();
-        for (String name : mPreloadedApps) {
-            final File f = new File(mPreloadsAppsDirectory, name);
-            f.createNewFile();
-            mPreloadedAppPaths.add(f.getPath());
-        }
-    }
-
-    @After
-    public void tearDown() {
-        if (mPreloadsAppsDirectory != null) {
-            FileUtils.deleteContentsAndDir(mPreloadsAppsDirectory);
-        }
-    }
-
-    @Test
-    public void testInstallApps() throws Exception {
-        mInstaller.installApps(TEST_DEMO_USER);
-        for (String path : mPreloadedAppPaths) {
-            ArgumentCaptor<IPackageInstallObserver2> observer =
-                    ArgumentCaptor.forClass(IPackageInstallObserver2.class);
-            verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
-                    anyString(), eq(TEST_DEMO_USER));
-            observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
-                    null, null);
-            // Verify that we try to install the package in system user.
-            verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
-                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
-        }
-        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
-                "1",
-                Settings.Secure.getStringForUser(mContentResolver,
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
-    }
-
-    @Test
-    public void testInstallApps_noPreloads() throws Exception {
-        // Delete all files in preloaded apps directory - no preloaded apps
-        FileUtils.deleteContents(mPreloadsAppsDirectory);
-        mInstaller.installApps(TEST_DEMO_USER);
-        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
-                "1",
-                Settings.Secure.getStringForUser(mContentResolver,
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
-    }
-
-    @Test
-    public void testInstallApps_installationFails() throws Exception {
-        mInstaller.installApps(TEST_DEMO_USER);
-        for (int i = 0; i < mPreloadedAppPaths.size(); ++i) {
-            ArgumentCaptor<IPackageInstallObserver2> observer =
-                    ArgumentCaptor.forClass(IPackageInstallObserver2.class);
-            final String path = mPreloadedAppPaths.get(i);
-            verify(mIpm).installPackageAsUser(eq(path), observer.capture(), anyInt(),
-                    anyString(), eq(TEST_DEMO_USER));
-            if (i == 0) {
-                observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_FAILED_DEXOPT,
-                        null, null);
-                continue;
-            }
-            observer.getValue().onPackageInstalled(path, PackageManager.INSTALL_SUCCEEDED,
-                    null, null);
-            // Verify that we try to install the package in system user.
-            verify(mIpm).installExistingPackageAsUser(path, UserHandle.USER_SYSTEM,
-                    0 /*installFlags*/, PackageManager.INSTALL_REASON_UNKNOWN);
-        }
-        assertEquals("DEMO_USER_SETUP should be set to 1 after preloaded apps are installed",
-                "1",
-                Settings.Secure.getStringForUser(mContentResolver,
-                        Settings.Secure.DEMO_USER_SETUP_COMPLETE, TEST_DEMO_USER));
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java b/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
deleted file mode 100644
index a93f6439..0000000
--- a/services/tests/servicestests/src/com/android/server/retaildemo/RetailDemoModeServiceTest.java
+++ /dev/null
@@ -1,484 +0,0 @@
-/*
- * 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.retaildemo;
-
-import static com.android.server.retaildemo.RetailDemoModeService.SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.anyInt;
-import static org.mockito.Matchers.anyString;
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import android.Manifest;
-import android.app.ActivityManagerInternal;
-import android.app.Notification;
-import android.app.NotificationManager;
-import android.app.RetailDemoModeServiceInternal;
-import android.app.job.JobInfo;
-import android.app.job.JobScheduler;
-import android.content.BroadcastReceiver;
-import android.content.ContentResolver;
-import android.content.Context;
-import android.content.ContextWrapper;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-import android.content.pm.IPackageManager;
-import android.content.pm.PackageManager;
-import android.content.pm.ResolveInfo;
-import android.content.pm.UserInfo;
-import android.content.res.Configuration;
-import android.media.AudioManager;
-import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.os.FileUtils;
-import android.os.Handler;
-import android.os.Looper;
-import android.os.UserHandle;
-import android.os.UserManager;
-import android.provider.CallLog;
-import android.provider.MediaStore;
-import android.provider.Settings;
-import android.support.test.InstrumentationRegistry;
-import android.support.test.filters.SmallTest;
-import android.support.test.runner.AndroidJUnit4;
-import android.test.mock.MockContentProvider;
-import android.test.mock.MockContentResolver;
-import android.util.ArrayMap;
-
-import com.android.internal.util.test.FakeSettingsProvider;
-import com.android.internal.widget.LockPatternUtils;
-import com.android.server.SystemService;
-import com.android.server.retaildemo.RetailDemoModeService.Injector;
-
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
-import org.mockito.MockitoAnnotations;
-import org.mockito.compat.ArgumentMatcher;
-
-import java.io.File;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.TimeUnit;
-
-@RunWith(AndroidJUnit4.class)
-@SmallTest
-public class RetailDemoModeServiceTest {
-    private static final int TEST_DEMO_USER = 111;
-    private static final long SETUP_COMPLETE_TIMEOUT_MS = 2000; // 2 sec
-    private static final String TEST_CAMERA_PKG = "test.cameraapp";
-    private static final String TEST_PRELOADS_DIR_NAME = "test_preloads";
-
-    private Context mContext;
-    private @Mock UserManager mUm;
-    private @Mock PackageManager mPm;
-    private @Mock IPackageManager mIpm;
-    private @Mock NotificationManager mNm;
-    private @Mock ActivityManagerInternal mAmi;
-    private @Mock AudioManager mAudioManager;
-    private @Mock WifiManager mWifiManager;
-    private @Mock LockPatternUtils mLockPatternUtils;
-    private @Mock JobScheduler mJobScheduler;
-    private MockPreloadAppsInstaller mPreloadAppsInstaller;
-    private MockContentResolver mContentResolver;
-    private MockContactsProvider mContactsProvider;
-    private Configuration mConfiguration;
-    private File mTestPreloadsDir;
-    private CountDownLatch mLatch;
-
-    private RetailDemoModeService mService;
-    private TestInjector mInjector;
-
-    @BeforeClass
-    @AfterClass
-    public static void clearSettingsProvider() {
-        FakeSettingsProvider.clearSettingsProvider();
-    }
-
-    @Before
-    public void setUp() throws Exception {
-        MockitoAnnotations.initMocks(this);
-        mContext = Mockito.spy(new ContextWrapper(InstrumentationRegistry.getTargetContext()));
-        when(mContext.getSystemServiceName(eq(JobScheduler.class))).thenReturn(
-                Context.JOB_SCHEDULER_SERVICE);
-        when(mContext.getSystemService(Context.JOB_SCHEDULER_SERVICE)).thenReturn(mJobScheduler);
-        when(mContext.getSystemService(Context.USER_SERVICE)).thenReturn(mUm);
-        mContentResolver = new MockContentResolver(mContext);
-        mContentResolver.addProvider(Settings.AUTHORITY, new FakeSettingsProvider());
-        mContactsProvider = new MockContactsProvider(mContext);
-        mContentResolver.addProvider(CallLog.AUTHORITY, mContactsProvider);
-        when(mContext.getContentResolver()).thenReturn(mContentResolver);
-        mPreloadAppsInstaller = new MockPreloadAppsInstaller(mContext);
-        mConfiguration = new Configuration();
-        mTestPreloadsDir = new File(InstrumentationRegistry.getContext().getFilesDir(),
-                TEST_PRELOADS_DIR_NAME);
-
-        Settings.Global.putString(mContentResolver, Settings.Global.RETAIL_DEMO_MODE_CONSTANTS, "");
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_PROVISIONED, 1);
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 1);
-
-        // Initialize RetailDemoModeService
-        mInjector = new TestInjector();
-        mService = new RetailDemoModeService(mInjector);
-        mService.onStart();
-    }
-
-    @After
-    public void tearDown() {
-        if (mTestPreloadsDir != null) {
-            FileUtils.deleteContentsAndDir(mTestPreloadsDir);
-        }
-    }
-
-    @Test
-    public void testDemoUserSetup() throws Exception {
-        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
-
-        mLatch = new CountDownLatch(1);
-        final UserInfo userInfo = new UserInfo();
-        userInfo.id = TEST_DEMO_USER;
-        when(mUm.createUser(anyString(), anyInt())).thenReturn(userInfo);
-
-        setCameraPackage(TEST_CAMERA_PKG);
-        mService.onBootPhase(SystemService.PHASE_BOOT_COMPLETED);
-        assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
-                "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
-        final ArgumentCaptor<IntentFilter> intentFilter =
-                ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
-        assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
-                intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
-
-        // Wait for the setup to complete.
-        mLatch.await(SETUP_COMPLETE_TIMEOUT_MS, TimeUnit.MILLISECONDS);
-        ArgumentCaptor<Integer> flags = ArgumentCaptor.forClass(Integer.class);
-        verify(mUm).createUser(anyString(), flags.capture());
-        assertTrue("FLAG_DEMO not set during user creation",
-                (flags.getValue() & UserInfo.FLAG_DEMO) != 0);
-        assertTrue("FLAG_EPHEMERAL not set during user creation",
-                (flags.getValue() & UserInfo.FLAG_EPHEMERAL) != 0);
-        // Verify if necessary restrictions are being set.
-        final UserHandle user = UserHandle.of(TEST_DEMO_USER);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_WIFI, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_INSTALL_UNKNOWN_SOURCES, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_MOBILE_NETWORKS, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_USB_FILE_TRANSFER, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_MODIFY_ACCOUNTS, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_CONFIG_BLUETOOTH, true, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_OUTGOING_CALLS, false, user);
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, true, UserHandle.SYSTEM);
-        // Verify if necessary settings are updated.
-        assertEquals("SKIP_FIRST_USE_HINTS setting is not set for demo user",
-                Settings.Secure.getIntForUser(mContentResolver,
-                        Settings.Secure.SKIP_FIRST_USE_HINTS, TEST_DEMO_USER),
-                1);
-        assertEquals("PACKAGE_VERIFIER_ENABLE settings should be set to 0 for demo user",
-                Settings.Global.getInt(mContentResolver,
-                        Settings.Global.PACKAGE_VERIFIER_ENABLE),
-                0);
-        // Verify if camera is granted location permission.
-        verify(mPm).grantRuntimePermission(TEST_CAMERA_PKG,
-                Manifest.permission.ACCESS_FINE_LOCATION, user);
-        // Verify call logs are cleared.
-        assertTrue("Call logs should be deleted", mContactsProvider.isCallLogDeleted());
-    }
-
-    @Test
-    public void testSettingsObserver_disableDemoMode() throws Exception {
-        final RetailDemoModeService.SettingsObserver observer =
-                mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
-        final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
-        when(mUm.hasUserRestriction(UserManager.DISALLOW_SAFE_BOOT, UserHandle.SYSTEM))
-                .thenReturn(false);
-        Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 1);
-        // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
-        observer.onChange(false, deviceDemoModeUri);
-        final ArgumentCaptor<BroadcastReceiver> receiver =
-                ArgumentCaptor.forClass(BroadcastReceiver.class);
-        verify(mContext).registerReceiver(receiver.capture(), any(IntentFilter.class));
-
-        Settings.Global.putInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE, 0);
-        new File(mTestPreloadsDir, "dir1").mkdirs();
-        new File(mTestPreloadsDir, "file1").createNewFile();
-        Settings.Global.putInt(mContentResolver, Settings.Global.DEVICE_DEMO_MODE, 0);
-        observer.onChange(false, deviceDemoModeUri);
-        verify(mContext).unregisterReceiver(receiver.getValue());
-        verify(mUm).setUserRestriction(UserManager.DISALLOW_SAFE_BOOT, false, UserHandle.SYSTEM);
-        assertEquals("Package verifier enable value has not been reset", 1,
-                Settings.Global.getInt(mContentResolver, Settings.Global.PACKAGE_VERIFIER_ENABLE));
-        Thread.sleep(20); // Wait for the deletion to complete.
-        // verify that the preloaded directory is emptied.
-        assertEquals("Preloads directory is not emptied",
-                0, mTestPreloadsDir.list().length);
-        // Verify that the expiration job was scheduled
-        verify(mJobScheduler).schedule(any(JobInfo.class));
-    }
-
-    @Test
-    public void testSettingsObserver_enableDemoMode() throws Exception {
-        final RetailDemoModeService.SettingsObserver observer =
-                mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
-        final Uri deviceDemoModeUri = Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE);
-        // Settings.Global.DEVICE_DEMO_MODE has been set to 1 initially.
-        observer.onChange(false, deviceDemoModeUri);
-        assertEquals(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED + " property not set",
-                "1", mInjector.systemPropertiesGet(SYSTEM_PROPERTY_RETAIL_DEMO_ENABLED));
-
-        final ArgumentCaptor<IntentFilter> intentFilter =
-                ArgumentCaptor.forClass(IntentFilter.class);
-        verify(mContext).registerReceiver(any(BroadcastReceiver.class), intentFilter.capture());
-        assertTrue("Not registered for " + Intent.ACTION_SCREEN_OFF,
-                intentFilter.getValue().hasAction(Intent.ACTION_SCREEN_OFF));
-    }
-
-    @Test
-    public void testSwitchToDemoUser() {
-        // To make the RetailDemoModeService update it's internal state.
-        mService.onBootPhase(SystemService.PHASE_THIRD_PARTY_APPS_CAN_START);
-        final RetailDemoModeService.SettingsObserver observer =
-                mService.new SettingsObserver(new Handler(Looper.getMainLooper()));
-        observer.onChange(false, Settings.Global.getUriFor(Settings.Global.DEVICE_DEMO_MODE));
-
-        final UserInfo userInfo = new UserInfo(TEST_DEMO_USER, "demo_user",
-                UserInfo.FLAG_DEMO | UserInfo.FLAG_EPHEMERAL);
-        when(mUm.getUserInfo(TEST_DEMO_USER)).thenReturn(userInfo);
-        when(mWifiManager.isWifiEnabled()).thenReturn(false);
-        final int minVolume = -111;
-        for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
-            when(mAudioManager.getStreamMinVolume(stream)).thenReturn(minVolume);
-        }
-
-        mService.onSwitchUser(TEST_DEMO_USER);
-        verify(mAmi).updatePersistentConfigurationForUser(mConfiguration, TEST_DEMO_USER);
-        for (int stream : RetailDemoModeService.VOLUME_STREAMS_TO_MUTE) {
-            verify(mAudioManager).setStreamVolume(stream, minVolume, 0);
-        }
-        verify(mLockPatternUtils).setLockScreenDisabled(true, TEST_DEMO_USER);
-        verify(mWifiManager).setWifiEnabled(true);
-    }
-
-    private void setCameraPackage(String pkgName) {
-        final ResolveInfo ri = new ResolveInfo();
-        final ActivityInfo ai = new ActivityInfo();
-        ai.packageName = pkgName;
-        ri.activityInfo = ai;
-        when(mPm.resolveActivityAsUser(
-                argThat(new IntentMatcher(MediaStore.ACTION_IMAGE_CAPTURE)),
-                anyInt(),
-                eq(TEST_DEMO_USER))).thenReturn(ri);
-    }
-
-    private class IntentMatcher extends ArgumentMatcher<Intent> {
-        private final Intent mIntent;
-
-        IntentMatcher(String action) {
-            mIntent = new Intent(action);
-        }
-
-        @Override
-        public boolean matchesObject(Object argument) {
-            if (argument instanceof Intent) {
-                return ((Intent) argument).filterEquals(mIntent);
-            }
-            return false;
-        }
-
-        @Override
-        public String toString() {
-            return "Expected: " + mIntent;
-        }
-    }
-
-    private class MockContactsProvider extends MockContentProvider {
-        private boolean mCallLogDeleted;
-
-        MockContactsProvider(Context context) {
-            super(context);
-        }
-
-        @Override
-        public int delete(Uri uri, String selection, String[] selectionArgs) {
-            if (CallLog.Calls.CONTENT_URI.equals(uri)) {
-                mCallLogDeleted = true;
-            }
-            return 0;
-        }
-
-        public boolean isCallLogDeleted() {
-            return mCallLogDeleted;
-        }
-    }
-
-    private class MockPreloadAppsInstaller extends PreloadAppsInstaller {
-        MockPreloadAppsInstaller(Context context) {
-            super(context);
-        }
-
-        @Override
-        public void installApps(int userId) {
-        }
-    }
-
-    private class TestInjector extends Injector {
-        private ArrayMap<String, String> mSystemProperties = new ArrayMap<>();
-
-        TestInjector() {
-            super(mContext);
-        }
-
-        @Override
-        Context getContext() {
-            return mContext;
-        }
-
-        @Override
-        UserManager getUserManager() {
-            return mUm;
-        }
-
-        @Override
-        WifiManager getWifiManager() {
-            return mWifiManager;
-        }
-
-        @Override
-        void switchUser(int userId) {
-            if (mLatch != null) {
-                mLatch.countDown();
-            }
-        }
-
-        @Override
-        AudioManager getAudioManager() {
-            return mAudioManager;
-        }
-
-        @Override
-        NotificationManager getNotificationManager() {
-            return mNm;
-        }
-
-        @Override
-        ActivityManagerInternal getActivityManagerInternal() {
-            return mAmi;
-        }
-
-        @Override
-        PackageManager getPackageManager() {
-            return mPm;
-        }
-
-        @Override
-        IPackageManager getIPackageManager() {
-            return mIpm;
-        }
-
-        @Override
-        ContentResolver getContentResolver() {
-            return mContentResolver;
-        }
-
-        @Override
-        PreloadAppsInstaller getPreloadAppsInstaller() {
-            return mPreloadAppsInstaller;
-        }
-
-        @Override
-        void systemPropertiesSet(String key, String value) {
-            mSystemProperties.put(key, value);
-        }
-
-        @Override
-        void turnOffAllFlashLights(String[] cameraIdsWithFlash) {
-        }
-
-        @Override
-        void initializeWakeLock() {
-        }
-
-        @Override
-        void destroyWakeLock() {
-        }
-
-        @Override
-        boolean isWakeLockHeld() {
-            return false;
-        }
-
-        @Override
-        void acquireWakeLock() {
-        }
-
-        @Override
-        void releaseWakeLock() {
-        }
-
-        @Override
-        void logSessionDuration(int duration) {
-        }
-
-        @Override
-        void logSessionCount(int count) {
-        }
-
-        @Override
-        Configuration getSystemUsersConfiguration() {
-            return mConfiguration;
-        }
-
-        @Override
-        LockPatternUtils getLockPatternUtils() {
-            return mLockPatternUtils;
-        }
-
-        @Override
-        Notification createResetNotification() {
-            return null;
-        }
-
-        @Override
-        File getDataPreloadsDirectory() {
-            return mTestPreloadsDir;
-        }
-
-        @Override
-        File getDataPreloadsFileCacheDirectory() {
-            return new File(mTestPreloadsDir, "file_cache");
-        }
-
-        @Override
-        void publishLocalService(RetailDemoModeService service,
-                RetailDemoModeServiceInternal localService) {
-        }
-
-        String systemPropertiesGet(String key) {
-            return mSystemProperties.get(key);
-        }
-    }
-}
diff --git a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 0a7a5f2..828d405 100644
--- a/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/servicestests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -382,7 +382,7 @@
     }
 
     @Override
-    public boolean isInteractive() {
+    public boolean okToAnimate() {
         return true;
     }
 
diff --git a/services/usb/java/com/android/server/usb/UsbDeviceManager.java b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
index b0fefc4..c696b50 100644
--- a/services/usb/java/com/android/server/usb/UsbDeviceManager.java
+++ b/services/usb/java/com/android/server/usb/UsbDeviceManager.java
@@ -956,11 +956,6 @@
                         Slog.i(TAG, "HOST_STATE connected:" + connected);
                     }
 
-                    if ((mHideUsbNotification && connected)
-                            || (!mHideUsbNotification && !connected)) {
-                        break;
-                    }
-
                     mHideUsbNotification = false;
                     while (devices.hasNext()) {
                         Map.Entry pair = (Map.Entry) devices.next();
@@ -1061,12 +1056,22 @@
 
         private void updateUsbNotification(boolean force) {
             if (mNotificationManager == null || !mUseUsbNotification
-                    || ("0".equals(SystemProperties.get("persist.charging.notify")))
-                    // Dont show the notification when connected to a USB peripheral
-                    // and the link does not support PR_SWAP and DR_SWAP
-                    || (mHideUsbNotification && !mSupportsAllCombinations)) {
+                    || ("0".equals(SystemProperties.get("persist.charging.notify")))) {
                 return;
             }
+
+            // Dont show the notification when connected to a USB peripheral
+            // and the link does not support PR_SWAP and DR_SWAP
+            if (mHideUsbNotification && !mSupportsAllCombinations) {
+                if (mUsbNotificationId != 0) {
+                    mNotificationManager.cancelAsUser(null, mUsbNotificationId,
+                            UserHandle.ALL);
+                    mUsbNotificationId = 0;
+                    Slog.d(TAG, "Clear notification");
+                }
+                return;
+            }
+
             int id = 0;
             int titleRes = 0;
             Resources r = mContext.getResources();
@@ -1117,6 +1122,7 @@
                 if (mUsbNotificationId != 0) {
                     mNotificationManager.cancelAsUser(null, mUsbNotificationId,
                             UserHandle.ALL);
+                    Slog.d(TAG, "Clear notification");
                     mUsbNotificationId = 0;
                 }
                 if (id != 0) {
@@ -1173,6 +1179,7 @@
 
                     mNotificationManager.notifyAsUser(null, id, notification,
                             UserHandle.ALL);
+                    Slog.d(TAG, "push notification:" + title);
                     mUsbNotificationId = id;
                 }
             }
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f6deb0a..3821b9c 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1066,6 +1066,13 @@
             "carrier_app_no_wake_signal_config";
 
     /**
+     * Default value for {@link Settings.Global#DATA_ROAMING}
+     * @hide
+     */
+    public static final String KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL =
+            "carrier_default_data_roaming_enabled_bool";
+
+    /**
      * Determines whether the carrier supports making non-emergency phone calls while the phone is
      * in emergency callback mode.  Default value is {@code true}, meaning that non-emergency calls
      * are allowed in emergency callback mode.
@@ -1632,6 +1639,7 @@
         sDefaults.putBoolean(KEY_CARRIER_NAME_OVERRIDE_BOOL, false);
         sDefaults.putString(KEY_CARRIER_NAME_STRING, "");
         sDefaults.putBoolean(KEY_SUPPORT_DIRECT_FDN_DIALING_BOOL, false);
+        sDefaults.putBoolean(KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL, false);
 
         // MMS defaults
         sDefaults.putBoolean(KEY_MMS_ALIAS_ENABLED_BOOL, false);
diff --git a/telephony/java/android/telephony/Telephony.java b/telephony/java/android/telephony/Telephony.java
index 3282f5f..e64e815 100644
--- a/telephony/java/android/telephony/Telephony.java
+++ b/telephony/java/android/telephony/Telephony.java
@@ -2765,6 +2765,13 @@
         public static final String USER_VISIBLE = "user_visible";
 
         /**
+         * Is the user allowed to edit this APN?
+         * <p>Type: INTEGER (boolean) </p>
+         * @hide
+         */
+        public static final String USER_EDITABLE = "user_editable";
+
+        /**
          * Following are possible values for the EDITED field
          * @hide
          */
diff --git a/tests/Internal/src/android/app/WallpaperColorsTest.java b/tests/Internal/src/android/app/WallpaperColorsTest.java
index 5bbd82b..fb529b9 100644
--- a/tests/Internal/src/android/app/WallpaperColorsTest.java
+++ b/tests/Internal/src/android/app/WallpaperColorsTest.java
@@ -77,4 +77,16 @@
         Assert.assertFalse("Light surface shouldn't support dark text "
                 + "when it contains dark pixels", supportsDarkText);
     }
+
+    /**
+     * WallpaperColors should not recycle bitmaps that it didn't create.
+     */
+    @Test
+    public void wallpaperRecycleBitmapTest() {
+        Bitmap image = Bitmap.createBitmap(300, 300, Bitmap.Config.ARGB_8888);
+        WallpaperColors.fromBitmap(image);
+        Canvas canvas = new Canvas();
+        // This would crash:
+        canvas.drawBitmap(image, 0, 0, new Paint());
+    }
 }
diff --git a/tests/net/java/android/net/apf/ApfTest.java b/tests/net/java/android/net/apf/ApfTest.java
index 6bf3b6b..bfbb8cc 100644
--- a/tests/net/java/android/net/apf/ApfTest.java
+++ b/tests/net/java/android/net/apf/ApfTest.java
@@ -92,6 +92,9 @@
     private final static boolean DROP_MULTICAST = true;
     private final static boolean ALLOW_MULTICAST = false;
 
+    private final static boolean DROP_802_3_FRAMES = true;
+    private final static boolean ALLOW_802_3_FRAMES = false;
+
     private static String label(int code) {
         switch (code) {
             case PASS: return "PASS";
@@ -611,9 +614,9 @@
         private final long mFixedTimeMs = SystemClock.elapsedRealtime();
 
         public TestApfFilter(IpManager.Callback ipManagerCallback, boolean multicastFilter,
-                IpConnectivityLog log) throws Exception {
+                boolean ieee802_3Filter, IpConnectivityLog log) throws Exception {
             super(new ApfCapabilities(2, 1700, ARPHRD_ETHER), NetworkInterface.getByName("lo"),
-                    ipManagerCallback, multicastFilter, log);
+                    ipManagerCallback, multicastFilter, ieee802_3Filter, log);
         }
 
         // Pretend an RA packet has been received and show it to ApfFilter.
@@ -742,7 +745,8 @@
         LinkProperties lp = new LinkProperties();
         lp.addLinkAddress(link);
 
-        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
+        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
+                ALLOW_802_3_FRAMES, mLog);
         apfFilter.setLinkProperties(lp);
 
         byte[] program = ipManagerCallback.getApfProgram();
@@ -793,7 +797,8 @@
     @SmallTest
     public void testApfFilterIPv6() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
-        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
+        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+                ALLOW_802_3_FRAMES, mLog);
         byte[] program = ipManagerCallback.getApfProgram();
 
         // Verify empty IPv6 packet is passed
@@ -834,7 +839,8 @@
         LinkProperties lp = new LinkProperties();
         lp.addLinkAddress(link);
 
-        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
+        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
         apfFilter.setLinkProperties(lp);
 
         byte[] program = ipManagerCallback.getApfProgram();
@@ -896,7 +902,8 @@
         // Verify it can be initialized to on
         ipManagerCallback.resetApfProgramWait();
         apfFilter.shutdown();
-        apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
+        apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
         apfFilter.setLinkProperties(lp);
         program = ipManagerCallback.getApfProgram();
         assertDrop(program, mcastv4packet.array());
@@ -911,6 +918,56 @@
         apfFilter.shutdown();
     }
 
+    @SmallTest
+    public void testApfFilter802_3() throws Exception {
+        MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
+        LinkAddress link = new LinkAddress(InetAddress.getByAddress(MOCK_IPV4_ADDR), 19);
+        LinkProperties lp = new LinkProperties();
+        lp.addLinkAddress(link);
+
+        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+                ALLOW_802_3_FRAMES, mLog);
+        apfFilter.setLinkProperties(lp);
+
+        byte[] program = ipManagerCallback.getApfProgram();
+
+        // Verify empty packet of 100 zero bytes is passed
+        // Note that eth-type = 0 makes it an IEEE802.3 frame
+        ByteBuffer packet = ByteBuffer.wrap(new byte[100]);
+        assertPass(program, packet.array());
+
+        // Verify empty packet with IPv4 is passed
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+        assertPass(program, packet.array());
+
+        // Verify empty IPv6 packet is passed
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+        assertPass(program, packet.array());
+
+        // Now turn on the filter
+        ipManagerCallback.resetApfProgramWait();
+        apfFilter.shutdown();
+        apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
+        apfFilter.setLinkProperties(lp);
+        program = ipManagerCallback.getApfProgram();
+
+        // Verify that IEEE802.3 frame is dropped
+        // In this case ethtype is used for payload length
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)(100 - 14));
+        assertDrop(program, packet.array());
+
+        // Verify that IPv4 (as example of Ethernet II) frame will pass
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IP);
+        assertPass(program, packet.array());
+
+        // Verify that IPv6 (as example of Ethernet II) frame will pass
+        packet.putShort(ETH_ETHERTYPE_OFFSET, (short)ETH_P_IPV6);
+        assertPass(program, packet.array());
+
+        apfFilter.shutdown();
+    }
+
     private byte[] getProgram(MockIpManagerCallback cb, ApfFilter filter, LinkProperties lp) {
         cb.resetApfProgramWait();
         filter.setLinkProperties(lp);
@@ -935,7 +992,8 @@
     @SmallTest
     public void testApfFilterArp() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
-        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST, mLog);
+        ApfFilter apfFilter = new TestApfFilter(ipManagerCallback, ALLOW_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
 
         // Verify initially ARP request filter is off, and GARP filter is on.
         verifyArpFilter(ipManagerCallback.getApfProgram(), PASS);
@@ -1056,7 +1114,8 @@
     @SmallTest
     public void testApfFilterRa() throws Exception {
         MockIpManagerCallback ipManagerCallback = new MockIpManagerCallback();
-        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST, mLog);
+        TestApfFilter apfFilter = new TestApfFilter(ipManagerCallback, DROP_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
         byte[] program = ipManagerCallback.getApfProgram();
 
         final int ROUTER_LIFETIME = 1000;
@@ -1198,7 +1257,8 @@
         final int maxRandomPacketSize = 512;
         final Random r = new Random();
         MockIpManagerCallback cb = new MockIpManagerCallback();
-        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
+        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
         for (int i = 0; i < 1000; i++) {
             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
             r.nextBytes(packet);
@@ -1216,7 +1276,8 @@
         final int maxRandomPacketSize = 512;
         final Random r = new Random();
         MockIpManagerCallback cb = new MockIpManagerCallback();
-        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST, mLog);
+        TestApfFilter apfFilter = new TestApfFilter(cb, DROP_MULTICAST,
+                DROP_802_3_FRAMES, mLog);
         for (int i = 0; i < 1000; i++) {
             byte[] packet = new byte[r.nextInt(maxRandomPacketSize + 1)];
             r.nextBytes(packet);
diff --git a/wifi/java/android/net/wifi/WifiInfo.java b/wifi/java/android/net/wifi/WifiInfo.java
index e48f7bd..25c1a8b 100644
--- a/wifi/java/android/net/wifi/WifiInfo.java
+++ b/wifi/java/android/net/wifi/WifiInfo.java
@@ -105,34 +105,43 @@
     private boolean mEphemeral;
 
     /**
+     * Running total count of lost (not ACKed) transmitted unicast data packets.
      * @hide
      */
     public long txBad;
     /**
+     * Running total count of transmitted unicast data retry packets.
      * @hide
      */
     public long txRetries;
     /**
+     * Running total count of successfully transmitted (ACKed) unicast data packets.
      * @hide
      */
     public long txSuccess;
     /**
+     * Running total count of received unicast data packets.
      * @hide
      */
     public long rxSuccess;
+
     /**
+     * Average rate of lost transmitted packets, in units of packets per 5 seconds.
      * @hide
      */
     public double txBadRate;
     /**
+     * Average rate of transmitted retry packets, in units of packets per 5 seconds.
      * @hide
      */
     public double txRetriesRate;
     /**
+     * Average rate of successfully transmitted unicast packets, in units of packets per 5 seconds.
      * @hide
      */
     public double txSuccessRate;
     /**
+     * Average rate of received unicast data packets, in units of packets per 5 seconds.
      * @hide
      */
     public double rxSuccessRate;