Merge "RESTRICT AUTOMERGE Fix the bootloop happening due to missing permission." into sc-v2-dev
diff --git a/core/api/current.txt b/core/api/current.txt
index e015169..1dd401d 100644
--- a/core/api/current.txt
+++ b/core/api/current.txt
@@ -1298,7 +1298,7 @@
     field public static final int shortcutLongLabel = 16844074; // 0x101052a
     field public static final int shortcutShortLabel = 16844073; // 0x1010529
     field public static final int shouldDisableView = 16843246; // 0x10101ee
-    field public static final int shouldUseDefaultUnfoldTransition;
+    field public static final int shouldUseDefaultUnfoldTransition = 16844364; // 0x101064c
     field public static final int showAsAction = 16843481; // 0x10102d9
     field public static final int showDefault = 16843258; // 0x10101fa
     field public static final int showDividers = 16843561; // 0x1010329
@@ -2014,9 +2014,9 @@
   public static final class R.id {
     ctor public R.id();
     field public static final int accessibilityActionContextClick = 16908348; // 0x102003c
-    field public static final int accessibilityActionDragCancel;
-    field public static final int accessibilityActionDragDrop;
-    field public static final int accessibilityActionDragStart;
+    field public static final int accessibilityActionDragCancel = 16908375; // 0x1020057
+    field public static final int accessibilityActionDragDrop = 16908374; // 0x1020056
+    field public static final int accessibilityActionDragStart = 16908373; // 0x1020055
     field public static final int accessibilityActionHideTooltip = 16908357; // 0x1020045
     field public static final int accessibilityActionImeEnter = 16908372; // 0x1020054
     field public static final int accessibilityActionMoveWindow = 16908354; // 0x1020042
@@ -22582,7 +22582,7 @@
     field public static final String KEY_MAX_FPS_TO_ENCODER = "max-fps-to-encoder";
     field public static final String KEY_MAX_HEIGHT = "max-height";
     field public static final String KEY_MAX_INPUT_SIZE = "max-input-size";
-    field public static final String KEY_MAX_OUTPUT_CHANNEL_COUNT = "max-output-channel_count";
+    field public static final String KEY_MAX_OUTPUT_CHANNEL_COUNT = "max-output-channel-count";
     field public static final String KEY_MAX_PTS_GAP_TO_ENCODER = "max-pts-gap-to-encoder";
     field public static final String KEY_MAX_WIDTH = "max-width";
     field public static final String KEY_MIME = "mime";
@@ -30857,6 +30857,7 @@
     field public static final int Q = 29; // 0x1d
     field public static final int R = 30; // 0x1e
     field public static final int S = 31; // 0x1f
+    field public static final int S_V2 = 32; // 0x20
   }
 
   public final class Bundle extends android.os.BaseBundle implements java.lang.Cloneable android.os.Parcelable {
diff --git a/core/api/system-current.txt b/core/api/system-current.txt
index 47ccf10..3aa17f0 100644
--- a/core/api/system-current.txt
+++ b/core/api/system-current.txt
@@ -437,6 +437,11 @@
     method public void onUidImportance(int, int);
   }
 
+  public class ActivityOptions {
+    method public int getLaunchTaskId();
+    method @RequiresPermission("android.permission.START_TASKS_FROM_RECENTS") public void setLaunchTaskId(int);
+  }
+
   public class AlarmManager {
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, android.app.PendingIntent, android.os.WorkSource);
     method @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS) public void set(int, long, long, long, android.app.AlarmManager.OnAlarmListener, android.os.Handler, android.os.WorkSource);
diff --git a/core/api/test-current.txt b/core/api/test-current.txt
index ceab056..488f8b1 100644
--- a/core/api/test-current.txt
+++ b/core/api/test-current.txt
@@ -144,7 +144,6 @@
     method @NonNull @RequiresPermission(android.Manifest.permission.START_TASKS_FROM_RECENTS) public static android.app.ActivityOptions makeCustomTaskAnimation(@NonNull android.content.Context, int, int, @Nullable android.os.Handler, @Nullable android.app.ActivityOptions.OnAnimationStartedListener, @Nullable android.app.ActivityOptions.OnAnimationFinishedListener);
     method public static void setExitTransitionTimeout(long);
     method public void setLaunchActivityType(int);
-    method public void setLaunchTaskId(int);
     method public void setLaunchWindowingMode(int);
     method public void setLaunchedFromBubble(boolean);
     method public void setTaskAlwaysOnTop(boolean);
diff --git a/core/java/android/app/ActivityOptions.java b/core/java/android/app/ActivityOptions.java
index d1def7e..edcab29 100644
--- a/core/java/android/app/ActivityOptions.java
+++ b/core/java/android/app/ActivityOptions.java
@@ -26,6 +26,7 @@
 import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.annotation.RequiresPermission;
+import android.annotation.SystemApi;
 import android.annotation.TestApi;
 import android.app.ExitTransitionCoordinator.ActivityExitTransitionCallbacks;
 import android.app.ExitTransitionCoordinator.ExitTransitionCallbacks;
@@ -1521,7 +1522,8 @@
      * Sets the task the activity will be launched in.
      * @hide
      */
-    @TestApi
+    @RequiresPermission(START_TASKS_FROM_RECENTS)
+    @SystemApi
     public void setLaunchTaskId(int taskId) {
         mLaunchTaskId = taskId;
     }
@@ -1529,6 +1531,7 @@
     /**
      * @hide
      */
+    @SystemApi
     public int getLaunchTaskId() {
         return mLaunchTaskId;
     }
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 7114d73..b5ed171 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -2743,7 +2743,7 @@
      */
     private static Resources createWindowContextResources(@NonNull ContextImpl windowContextBase) {
         final LoadedApk packageInfo = windowContextBase.mPackageInfo;
-        final ClassLoader classLoader = windowContextBase.mClassLoader;
+        final ClassLoader classLoader = windowContextBase.getClassLoader();
         final IBinder token = windowContextBase.getWindowContextToken();
 
         final String resDir = packageInfo.getResDir();
diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java
index a2c9795..74208c3a 100644
--- a/core/java/android/app/LoadedApk.java
+++ b/core/java/android/app/LoadedApk.java
@@ -2134,4 +2134,38 @@
             final IBinder mService;
         }
     }
+
+    /**
+     * Check if the Apk paths in the cache are correct, and update them if they are not.
+     * @hide
+     */
+    public static void checkAndUpdateApkPaths(ApplicationInfo expectedAppInfo) {
+        // Get the LoadedApk from the cache
+        ActivityThread activityThread = ActivityThread.currentActivityThread();
+        if (activityThread == null) {
+            Log.e(TAG, "Cannot find activity thread");
+            return;
+        }
+        checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ true);
+        checkAndUpdateApkPaths(activityThread, expectedAppInfo, /* cacheWithCode */ false);
+    }
+
+    private static void checkAndUpdateApkPaths(ActivityThread activityThread,
+            ApplicationInfo expectedAppInfo, boolean cacheWithCode) {
+        String expectedCodePath = expectedAppInfo.getCodePath();
+        LoadedApk loadedApk = activityThread.peekPackageInfo(
+                expectedAppInfo.packageName, /* includeCode= */ cacheWithCode);
+        // If there is load apk cached, or if the cache is valid, don't do anything.
+        if (loadedApk == null || loadedApk.getApplicationInfo() == null
+                || loadedApk.getApplicationInfo().getCodePath().equals(expectedCodePath)) {
+            return;
+        }
+        // Duplicate framework logic
+        List<String> oldPaths = new ArrayList<>();
+        LoadedApk.makePaths(activityThread, expectedAppInfo, oldPaths);
+
+        // Force update the LoadedApk instance, which should update the reference in the cache
+        loadedApk.updateApplicationInfo(expectedAppInfo, oldPaths);
+    }
+
 }
diff --git a/core/java/android/appwidget/AppWidgetHostView.java b/core/java/android/appwidget/AppWidgetHostView.java
index dd147cc..7c2b1b7 100644
--- a/core/java/android/appwidget/AppWidgetHostView.java
+++ b/core/java/android/appwidget/AppWidgetHostView.java
@@ -20,6 +20,7 @@
 import android.annotation.Nullable;
 import android.app.Activity;
 import android.app.ActivityOptions;
+import android.app.LoadedApk;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentName;
 import android.content.Context;
@@ -554,7 +555,7 @@
             }
             // Prepare a local reference to the remote Context so we're ready to
             // inflate any requested LayoutParams.
-            mRemoteContext = getRemoteContext();
+            mRemoteContext = getRemoteContextEnsuringCorrectCachedApkPath();
 
             int layoutId = rvToApply.getLayoutId();
             if (rvToApply.canRecycleView(mView)) {
@@ -616,7 +617,7 @@
     private void inflateAsync(@NonNull RemoteViews remoteViews) {
         // Prepare a local reference to the remote Context so we're ready to
         // inflate any requested LayoutParams.
-        mRemoteContext = getRemoteContext();
+        mRemoteContext = getRemoteContextEnsuringCorrectCachedApkPath();
         int layoutId = remoteViews.getLayoutId();
 
         if (mLastExecutionSignal != null) {
@@ -625,7 +626,7 @@
 
         // If our stale view has been prepared to match active, and the new
         // layout matches, try recycling it
-        if (layoutId == mLayoutId && mView != null) {
+        if (remoteViews.canRecycleView(mView)) {
             try {
                 mLastExecutionSignal = remoteViews.reapplyAsync(mContext,
                         mView,
@@ -718,8 +719,10 @@
      * purposes of reading remote resources.
      * @hide
      */
-    protected Context getRemoteContext() {
+    protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
         try {
+            ApplicationInfo expectedAppInfo = mInfo.providerInfo.applicationInfo;
+            LoadedApk.checkAndUpdateApkPaths(expectedAppInfo);
             // Return if cloned successfully, otherwise default
             Context newContext = mContext.createApplicationContext(
                     mInfo.providerInfo.applicationInfo,
@@ -765,7 +768,7 @@
 
         try {
             if (mInfo != null) {
-                Context theirContext = getRemoteContext();
+                Context theirContext = getRemoteContextEnsuringCorrectCachedApkPath();
                 mRemoteContext = theirContext;
                 LayoutInflater inflater = (LayoutInflater)
                         theirContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index c3ec094..7f2a740 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -3246,7 +3246,11 @@
      * Service will call {@link android.app.Service#startForeground(int, android.app.Notification)
      * startForeground(int, android.app.Notification)} once it begins running.  The service is given
      * an amount of time comparable to the ANR interval to do this, otherwise the system
-     * will automatically stop the service and declare the app ANR.
+     * will automatically crash the process, in which case an internal exception
+     * {@code ForegroundServiceDidNotStartInTimeException} is logged on logcat on devices
+     * running SDK Version {@link android.os.Build.VERSION_CODES#S} or later. On older Android
+     * versions, an internal exception {@code RemoteServiceException} is logged instead, with
+     * a corresponding message.
      *
      * <p>Unlike the ordinary {@link #startService(Intent)}, this method can be used
      * at any time, regardless of whether the app hosting the service is in a foreground
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 95c5612..e28e4ad 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -994,9 +994,10 @@
      * OVERRIDE_MIN_ASPECT_RATIO_MEDIUM
      * OVERRIDE_MIN_ASPECT_RATIO_LARGE
      *
-     * If OVERRIDE_MIN_ASPECT_RATIO is applied, the min aspect ratio given in the app's
-     * manifest will be overridden to the largest enabled aspect ratio treatment unless the app's
-     * manifest value is higher.
+     * If OVERRIDE_MIN_ASPECT_RATIO is applied, and the activity's orientation is fixed to
+     * portrait, the min aspect ratio given in the app's manifest will be overridden to the
+     * largest enabled aspect ratio treatment unless the app's manifest value is higher.
+     * TODO(b/203647190): add OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY instead of portrait by default
      * @hide
      */
     @ChangeId
@@ -1232,8 +1233,8 @@
      * Returns true if the activity has maximum or minimum aspect ratio.
      * @hide
      */
-    public boolean hasFixedAspectRatio() {
-        return getMaxAspectRatio() != 0 || getMinAspectRatio() != 0;
+    public boolean hasFixedAspectRatio(@ScreenOrientation int orientation) {
+        return getMaxAspectRatio() != 0 || getMinAspectRatio(orientation) != 0;
     }
 
     /**
@@ -1392,10 +1393,14 @@
      * {@code getManifestMinAspectRatio}.
      * @hide
      */
-    public float getMinAspectRatio() {
+    public float getMinAspectRatio(@ScreenOrientation int orientation) {
+        // TODO(b/203647190): check orientation only if OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY
+        // In case the activity's orientation isn't fixed to portrait, OVERRIDE_MIN_ASPECT_RATIO
+        // shouldn't be applied.
         if (applicationInfo == null || !CompatChanges.isChangeEnabled(OVERRIDE_MIN_ASPECT_RATIO,
                 applicationInfo.packageName,
-                UserHandle.getUserHandleForUid(applicationInfo.uid))) {
+                UserHandle.getUserHandleForUid(applicationInfo.uid))
+                || !isFixedOrientationPortrait(orientation)) {
             return mMinAspectRatio;
         }
 
@@ -1521,9 +1526,10 @@
         if (getMaxAspectRatio() != 0) {
             pw.println(prefix + "maxAspectRatio=" + getMaxAspectRatio());
         }
-        if (getMinAspectRatio() != 0) {
-            pw.println(prefix + "minAspectRatio=" + getMinAspectRatio());
-            if (getManifestMinAspectRatio() !=  getMinAspectRatio()) {
+        final float minAspectRatio = getMinAspectRatio(screenOrientation);
+        if (minAspectRatio != 0) {
+            pw.println(prefix + "minAspectRatio=" + minAspectRatio);
+            if (getManifestMinAspectRatio() !=  minAspectRatio) {
                 pw.println(prefix + "getManifestMinAspectRatio=" + getManifestMinAspectRatio());
             }
         }
diff --git a/core/java/android/net/NetworkTemplate.java b/core/java/android/net/NetworkTemplate.java
index 249154a..fee2e2b 100644
--- a/core/java/android/net/NetworkTemplate.java
+++ b/core/java/android/net/NetworkTemplate.java
@@ -47,7 +47,6 @@
 import android.util.BackupUtils;
 import android.util.Log;
 
-import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.util.ArrayUtils;
 import com.android.net.module.util.NetworkIdentityUtils;
 
@@ -151,24 +150,6 @@
         }
     }
 
-    private static boolean sForceAllNetworkTypes = false;
-
-    /**
-     * Results in matching against all mobile network types.
-     *
-     * <p>See {@link #matchesMobile} and {@link matchesMobileWildcard}.
-     */
-    @VisibleForTesting
-    public static void forceAllNetworkTypes() {
-        sForceAllNetworkTypes = true;
-    }
-
-    /** Resets the affect of {@link #forceAllNetworkTypes}. */
-    @VisibleForTesting
-    public static void resetForceAllNetworkTypes() {
-        sForceAllNetworkTypes = false;
-    }
-
     /**
      * Template to match {@link ConnectivityManager#TYPE_MOBILE} networks with
      * the given IMSI.
@@ -179,19 +160,19 @@
     }
 
     /**
-     * Template to match cellular networks with the given IMSI and {@code ratType}.
-     * Use {@link #NETWORK_TYPE_ALL} to include all network types when filtering.
-     * See {@code TelephonyManager.NETWORK_TYPE_*}.
+     * Template to match cellular networks with the given IMSI, {@code ratType} and
+     * {@code metered}. Use {@link #NETWORK_TYPE_ALL} to include all network types when
+     * filtering. See {@code TelephonyManager.NETWORK_TYPE_*}.
      */
     public static NetworkTemplate buildTemplateMobileWithRatType(@Nullable String subscriberId,
-            @NetworkType int ratType) {
+            @NetworkType int ratType, int metered) {
         if (TextUtils.isEmpty(subscriberId)) {
             return new NetworkTemplate(MATCH_MOBILE_WILDCARD, null, null, null,
-                    METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+                    metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
                     SUBSCRIBER_ID_MATCH_RULE_EXACT);
         }
         return new NetworkTemplate(MATCH_MOBILE, subscriberId, new String[]{subscriberId}, null,
-                METERED_ALL, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
+                metered, ROAMING_ALL, DEFAULT_NETWORK_ALL, ratType, OEM_MANAGED_ALL,
                 SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
@@ -324,6 +305,7 @@
         }
     }
 
+    // TODO: Deprecate this constructor, mark it @UnsupportedAppUsage(maxTargetSdk = S)
     @UnsupportedAppUsage
     public NetworkTemplate(int matchRule, String subscriberId, String networkId) {
         this(matchRule, subscriberId, new String[] { subscriberId }, networkId);
@@ -331,9 +313,14 @@
 
     public NetworkTemplate(int matchRule, String subscriberId, String[] matchSubscriberIds,
             String networkId) {
-        this(matchRule, subscriberId, matchSubscriberIds, networkId, METERED_ALL, ROAMING_ALL,
-                DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
-                SUBSCRIBER_ID_MATCH_RULE_EXACT);
+        // Older versions used to only match MATCH_MOBILE and MATCH_MOBILE_WILDCARD templates
+        // to metered networks. It is now possible to match mobile with any meteredness, but
+        // in order to preserve backward compatibility of @UnsupportedAppUsage methods, this
+        //constructor passes METERED_YES for these types.
+        this(matchRule, subscriberId, matchSubscriberIds, networkId,
+                (matchRule == MATCH_MOBILE || matchRule == MATCH_MOBILE_WILDCARD) ? METERED_YES
+                : METERED_ALL , ROAMING_ALL, DEFAULT_NETWORK_ALL, NETWORK_TYPE_ALL,
+                OEM_MANAGED_ALL, SUBSCRIBER_ID_MATCH_RULE_EXACT);
     }
 
     // TODO: Remove it after updating all of the caller.
@@ -608,11 +595,7 @@
             // TODO: consider matching against WiMAX subscriber identity
             return true;
         } else {
-            // Only metered mobile network would be matched regardless of metered filter.
-            // This is used to exclude non-metered APNs, e.g. IMS. See ag/908650.
-            // TODO: Respect metered filter and remove mMetered condition.
-            return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
-                    && !ArrayUtils.isEmpty(mMatchSubscriberIds)
+            return ident.mType == TYPE_MOBILE && !ArrayUtils.isEmpty(mMatchSubscriberIds)
                     && ArrayUtils.contains(mMatchSubscriberIds, ident.mSubscriberId)
                     && matchesCollapsedRatType(ident);
         }
@@ -726,8 +709,7 @@
         if (ident.mType == TYPE_WIMAX) {
             return true;
         } else {
-            return (sForceAllNetworkTypes || (ident.mType == TYPE_MOBILE && ident.mMetered))
-                    && matchesCollapsedRatType(ident);
+            return ident.mType == TYPE_MOBILE && matchesCollapsedRatType(ident);
         }
     }
 
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 6bf394d..b7dd36e 100755
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -1024,7 +1024,7 @@
          * will also enable {@link StrictMode.ThreadPolicy.Builder#detectUnbufferedIo}.</li>
          * <li>{@link android.provider.DocumentsContract}'s various methods will throw failure
          * exceptions back to the caller instead of returning null.
-         * <li>{@link View#hasFocusable View.hasFocusable} now includes auto-focusable views.</li>
+         * <li>{@link View#hasFocusable() View.hasFocusable} now includes auto-focusable views.</li>
          * <li>{@link android.view.SurfaceView} will no longer always change the underlying
          * Surface object when something about it changes; apps need to look at the current
          * state of the object to determine which things they are interested in have changed.</li>
@@ -1130,6 +1130,15 @@
          * S.
          */
         public static final int S = 31;
+
+        /**
+         * S V2.
+         *
+         * Once more unto the breach, dear friends, once more.
+         *
+         */
+        public static final int S_V2 = 32;
+
     }
 
     /** The type of build, like "user" or "eng". */
diff --git a/core/java/android/provider/Telephony.java b/core/java/android/provider/Telephony.java
index f3a8b5d..9f3a847 100644
--- a/core/java/android/provider/Telephony.java
+++ b/core/java/android/provider/Telephony.java
@@ -5365,5 +5365,14 @@
          */
         public static final String COLUMN_D2D_STATUS_SHARING_SELECTED_CONTACTS =
                 "d2d_sharing_contacts";
+
+        /**
+        * TelephonyProvider column name for NR Advanced calling
+        * Determines if the user has enabled VoNR settings for this subscription.
+        *
+        * @hide
+        */
+        public static final String COLUMN_NR_ADVANCED_CALLING_ENABLED =
+                "nr_advanced_calling_enabled";
     }
 }
diff --git a/core/java/android/service/voice/VoiceInteractionSession.java b/core/java/android/service/voice/VoiceInteractionSession.java
index 9db856a..4d0fc16 100644
--- a/core/java/android/service/voice/VoiceInteractionSession.java
+++ b/core/java/android/service/voice/VoiceInteractionSession.java
@@ -2045,7 +2045,11 @@
     /**
      * Registers a callback that will be notified when visible activities have been changed.
      *
-     * @param executor The handler to receive the callback.
+     * Note: The {@link VisibleActivityCallback#onVisible(VisibleActivityInfo)} will be called
+     * immediately with current visible activities when the callback is registered for the first
+     * time. If the callback is already registered, this method does nothing.
+     *
+     * @param executor The executor which will be used to invoke the callback.
      * @param callback The callback to receive the response.
      *
      * @throws IllegalStateException if calling this method before onCreate().
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 8e149a9..9e41e4d 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -61,6 +61,7 @@
 import android.view.InputDevice;
 import android.view.IInputFilter;
 import android.view.AppTransitionAnimationSpec;
+import android.view.TaskTransitionSpec;
 import android.view.WindowContentFrameStats;
 import android.view.WindowManager;
 import android.view.SurfaceControl;
@@ -347,6 +348,14 @@
     Bitmap screenshotWallpaper();
 
     /**
+     * Mirrors the wallpaper for the given display.
+     *
+     * @param displayId ID of the display for the wallpaper.
+     * @return A SurfaceControl for the parent of the mirrored wallpaper.
+     */
+    SurfaceControl mirrorWallpaperSurface(int displayId);
+
+    /**
      * Registers a wallpaper visibility listener.
      * @return Current visibility.
      */
@@ -888,4 +897,17 @@
      * @see android.window.WindowProviderService#getLaunchedDisplayId
      */
     int getImeDisplayId();
+
+    /**
+     * Customized the task transition animation with a task transition spec.
+     *
+     * @param spec the spec that will be used to customize the task animations
+     */
+    void setTaskTransitionSpec(in TaskTransitionSpec spec);
+
+    /**
+     * Clears any task transition spec that has been previously set and
+     * reverts to using the default task transition with no spec changes.
+     */
+    void clearTaskTransitionSpec();
 }
diff --git a/core/java/android/view/TaskTransitionSpec.aidl b/core/java/android/view/TaskTransitionSpec.aidl
new file mode 100644
index 0000000..08af15c
--- /dev/null
+++ b/core/java/android/view/TaskTransitionSpec.aidl
@@ -0,0 +1,20 @@
+/*
+** Copyright 2021, 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.view;
+
+/** @hide */
+parcelable TaskTransitionSpec;
diff --git a/core/java/android/view/TaskTransitionSpec.java b/core/java/android/view/TaskTransitionSpec.java
new file mode 100644
index 0000000..e90d6e1
--- /dev/null
+++ b/core/java/android/view/TaskTransitionSpec.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2021 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.view;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.ArraySet;
+
+import java.util.Set;
+
+/**
+ * Holds information about how to execute task transition animations.
+ *
+ * This class is intended to be used with IWindowManager.setTaskTransitionSpec methods when
+ * we want more customization over the way default task transitions are executed.
+ *
+ * @hide
+ */
+public class TaskTransitionSpec implements Parcelable {
+    /**
+     * The background color to use during task animations (override the default background color)
+     */
+    public final int backgroundColor;
+
+    /**
+     * TEMPORARY FIELD (b/202383002)
+     * TODO: Remove once we use surfaceflinger rounded corners on tasks rather than taskbar overlays
+     *
+     * A set of {@InsetsState.InternalInsetsType}s we want to use as the source to set the bounds
+     * of the task during the animation. Used to make sure that task animate above the taskbar.
+     * Will also be used to crop to the frame size of the inset source to the inset size to prevent
+     * the taskbar rounded corners overlay from being invisible during task transition animation.
+     */
+    public final Set<Integer> animationBoundInsets;
+
+    public TaskTransitionSpec(
+            int backgroundColor, Set<Integer> animationBoundInsets) {
+        this.backgroundColor = backgroundColor;
+        this.animationBoundInsets = animationBoundInsets;
+    }
+
+    public TaskTransitionSpec(Parcel in) {
+        this.backgroundColor = in.readInt();
+
+        int animationBoundInsetsSize = in.readInt();
+        this.animationBoundInsets = new ArraySet<>(animationBoundInsetsSize);
+        for (int i = 0; i < animationBoundInsetsSize; i++) {
+            this.animationBoundInsets.add(in.readInt());
+        }
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(backgroundColor);
+
+        dest.writeInt(animationBoundInsets.size());
+        for (int insetType : animationBoundInsets) {
+            dest.writeInt(insetType);
+        }
+    }
+
+    public static final @android.annotation.NonNull Parcelable.Creator<TaskTransitionSpec>
+            CREATOR = new Parcelable.Creator<TaskTransitionSpec>() {
+                public TaskTransitionSpec createFromParcel(Parcel in) {
+                    return new TaskTransitionSpec(in);
+                }
+
+                public TaskTransitionSpec[] newArray(int size) {
+                    return new TaskTransitionSpec[size];
+                }
+            };
+}
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index 5a3a9d5..4c0c82f 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -820,11 +820,7 @@
                 context);
         mCompatibleVisibilityInfo = new SystemUiVisibilityInfo();
         mAccessibilityManager = AccessibilityManager.getInstance(context);
-        mAccessibilityManager.addAccessibilityStateChangeListener(
-                mAccessibilityInteractionConnectionManager, mHandler);
         mHighContrastTextManager = new HighContrastTextManager();
-        mAccessibilityManager.addHighTextContrastStateChangeListener(
-                mHighContrastTextManager, mHandler);
         mViewConfiguration = ViewConfiguration.get(context);
         mDensity = context.getResources().getDisplayMetrics().densityDpi;
         mNoncompatDensity = context.getResources().getDisplayMetrics().noncompatDensityDpi;
@@ -1024,8 +1020,6 @@
                 mView = view;
 
                 mAttachInfo.mDisplayState = mDisplay.getState();
-                mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
-
                 mViewLayoutDirectionInitial = mView.getRawLayoutDirection();
                 mFallbackEventHandler.setView(view);
                 mWindowAttributes.copyFrom(attrs);
@@ -1218,6 +1212,7 @@
                             "Unable to add window -- unknown error code " + res);
                 }
 
+                registerListeners();
                 if ((res & WindowManagerGlobal.ADD_FLAG_USE_BLAST) != 0) {
                     mUseBLASTAdapter = true;
                 }
@@ -1274,6 +1269,28 @@
         }
     }
 
+    /**
+     * Register any kind of listeners if setView was success.
+     */
+    private void registerListeners() {
+        mAccessibilityManager.addAccessibilityStateChangeListener(
+                mAccessibilityInteractionConnectionManager, mHandler);
+        mAccessibilityManager.addHighTextContrastStateChangeListener(
+                mHighContrastTextManager, mHandler);
+        mDisplayManager.registerDisplayListener(mDisplayListener, mHandler);
+    }
+
+    /**
+     * Unregister all listeners while detachedFromWindow.
+     */
+    private void unregisterListeners() {
+        mAccessibilityManager.removeAccessibilityStateChangeListener(
+                mAccessibilityInteractionConnectionManager);
+        mAccessibilityManager.removeHighTextContrastStateChangeListener(
+                mHighContrastTextManager);
+        mDisplayManager.unregisterDisplayListener(mDisplayListener);
+    }
+
     private void setTag() {
         final String[] split = mWindowAttributes.getTitle().toString().split("\\.");
         if (split.length > 0) {
@@ -5016,10 +5033,6 @@
         }
 
         mAccessibilityInteractionConnectionManager.ensureNoConnection();
-        mAccessibilityManager.removeAccessibilityStateChangeListener(
-                mAccessibilityInteractionConnectionManager);
-        mAccessibilityManager.removeHighTextContrastStateChangeListener(
-                mHighContrastTextManager);
         removeSendWindowContentChangedCallback();
 
         destroyHardwareRenderer();
@@ -5052,8 +5065,7 @@
             mInputEventReceiver = null;
         }
 
-        mDisplayManager.unregisterDisplayListener(mDisplayListener);
-
+        unregisterListeners();
         unscheduleTraversals();
     }
 
diff --git a/core/java/android/view/WindowManagerGlobal.java b/core/java/android/view/WindowManagerGlobal.java
index 18013e8..c92a3a0 100644
--- a/core/java/android/view/WindowManagerGlobal.java
+++ b/core/java/android/view/WindowManagerGlobal.java
@@ -18,6 +18,7 @@
 
 import android.animation.ValueAnimator;
 import android.annotation.NonNull;
+import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.compat.annotation.UnsupportedAppUsage;
 import android.content.ComponentCallbacks2;
@@ -709,6 +710,16 @@
             }
         }
     }
+
+    /** @hide */
+    @Nullable
+    public SurfaceControl mirrorWallpaperSurface(int displayId) {
+        try {
+            return getWindowManagerService().mirrorWallpaperSurface(displayId);
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
 }
 
 final class WindowLeaked extends AndroidRuntimeException {
diff --git a/core/java/android/view/translation/UiTranslationController.java b/core/java/android/view/translation/UiTranslationController.java
index aa73ed7..9d1bf17 100644
--- a/core/java/android/view/translation/UiTranslationController.java
+++ b/core/java/android/view/translation/UiTranslationController.java
@@ -369,6 +369,10 @@
                     Log.v(TAG, "onVirtualViewTranslationCompleted: received response for "
                             + "AutofillId " + autofillId);
                 }
+                view.onVirtualViewTranslationResponses(virtualChildResponse);
+                if (mCurrentState == STATE_UI_TRANSLATION_PAUSED) {
+                    return;
+                }
                 mActivity.runOnUiThread(() -> {
                     if (view.getViewTranslationCallback() == null) {
                         if (DEBUG) {
@@ -377,7 +381,6 @@
                         }
                         return;
                     }
-                    view.onVirtualViewTranslationResponses(virtualChildResponse);
                     if (view.getViewTranslationCallback() != null) {
                         view.getViewTranslationCallback().onShowTranslation(view);
                     }
@@ -425,6 +428,8 @@
                             + " may be gone.");
                     continue;
                 }
+                int currentState;
+                currentState = mCurrentState;
                 mActivity.runOnUiThread(() -> {
                     ViewTranslationCallback callback = view.getViewTranslationCallback();
                     if (view.getViewTranslationResponse() != null
@@ -458,6 +463,9 @@
                         callback.enableContentPadding();
                     }
                     view.onViewTranslationResponse(response);
+                    if (currentState == STATE_UI_TRANSLATION_PAUSED) {
+                        return;
+                    }
                     callback.onShowTranslation(view);
                 });
             }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index fe5eb08..2357d13 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -34,6 +34,7 @@
 import android.app.ActivityOptions;
 import android.app.ActivityThread;
 import android.app.Application;
+import android.app.LoadedApk;
 import android.app.PendingIntent;
 import android.app.RemoteInput;
 import android.appwidget.AppWidgetHostView;
@@ -5475,7 +5476,8 @@
         // user. So build a context that loads resources from that user but
         // still returns the current users userId so settings like data / time formats
         // are loaded without requiring cross user persmissions.
-        final Context contextForResources = getContextForResources(context);
+        final Context contextForResources =
+                getContextForResourcesEnsuringCorrectCachedApkPaths(context);
         if (colorResources != null) {
             colorResources.apply(contextForResources);
         }
@@ -5793,7 +5795,7 @@
         // across orientation change, and has the RemoteViews re-applied in the new orientation,
         // we throw an exception, since the layouts may be completely unrelated.
         if (hasMultipleLayouts()) {
-            if ((Integer) v.getTag(R.id.widget_frame) != rvToApply.getLayoutId()) {
+            if (!rvToApply.canRecycleView(v)) {
                 throw new RuntimeException("Attempting to re-apply RemoteViews to a view that" +
                         " that does not share the same root layout id.");
             }
@@ -5853,13 +5855,14 @@
         }
     }
 
-    private Context getContextForResources(Context context) {
+    private Context getContextForResourcesEnsuringCorrectCachedApkPaths(Context context) {
         if (mApplication != null) {
             if (context.getUserId() == UserHandle.getUserId(mApplication.uid)
                     && context.getPackageName().equals(mApplication.packageName)) {
                 return context;
             }
             try {
+                LoadedApk.checkAndUpdateApkPaths(mApplication);
                 return context.createApplicationContext(mApplication,
                         Context.CONTEXT_RESTRICTED);
             } catch (NameNotFoundException e) {
diff --git a/core/java/android/widget/RemoteViewsAdapter.java b/core/java/android/widget/RemoteViewsAdapter.java
index 6b33428..8e293f4 100644
--- a/core/java/android/widget/RemoteViewsAdapter.java
+++ b/core/java/android/widget/RemoteViewsAdapter.java
@@ -408,7 +408,7 @@
         }
 
         @Override
-        protected Context getRemoteContext() {
+        protected Context getRemoteContextEnsuringCorrectCachedApkPath() {
             return null;
         }
 
diff --git a/core/java/android/window/ITransitionMetricsReporter.aidl b/core/java/android/window/ITransitionMetricsReporter.aidl
new file mode 100644
index 0000000..00f71dc
--- /dev/null
+++ b/core/java/android/window/ITransitionMetricsReporter.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2021 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.window;
+
+import android.os.IBinder;
+
+/**
+ * Implemented by WM Core to know the metrics of transition that runs on a different process.
+ * @hide
+ */
+oneway interface ITransitionMetricsReporter {
+
+    /**
+     * Called when the transition animation starts.
+     *
+     * @param startTime The time when the animation started.
+     */
+    void reportAnimationStart(IBinder transitionToken, long startTime);
+}
diff --git a/core/java/android/window/IWindowOrganizerController.aidl b/core/java/android/window/IWindowOrganizerController.aidl
index e65fcdd..3c7cd02 100644
--- a/core/java/android/window/IWindowOrganizerController.aidl
+++ b/core/java/android/window/IWindowOrganizerController.aidl
@@ -23,6 +23,7 @@
 import android.window.IDisplayAreaOrganizerController;
 import android.window.ITaskFragmentOrganizerController;
 import android.window.ITaskOrganizerController;
+import android.window.ITransitionMetricsReporter;
 import android.window.ITransitionPlayer;
 import android.window.IWindowContainerTransactionCallback;
 import android.window.WindowContainerToken;
@@ -98,4 +99,7 @@
      * this will replace the existing one if set.
      */
     void registerTransitionPlayer(in ITransitionPlayer player);
+
+    /** @return An interface enabling the transition players to report its metrics. */
+    ITransitionMetricsReporter getTransitionMetricsReporter();
 }
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index c2ffc03..7208930 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -140,7 +140,7 @@
     private TransitionInfo(Parcel in) {
         mType = in.readInt();
         mFlags = in.readInt();
-        in.readList(mChanges, null /* classLoader */);
+        in.readTypedList(mChanges, Change.CREATOR);
         mRootLeash = new SurfaceControl();
         mRootLeash.readFromParcel(in);
         mRootOffset.readFromParcel(in);
@@ -152,7 +152,7 @@
     public void writeToParcel(@NonNull Parcel dest, int flags) {
         dest.writeInt(mType);
         dest.writeInt(mFlags);
-        dest.writeList(mChanges);
+        dest.writeTypedList(mChanges);
         mRootLeash.writeToParcel(dest, flags);
         mRootOffset.writeToParcel(dest, flags);
         dest.writeTypedObject(mOptions, flags);
diff --git a/core/java/android/window/TransitionMetrics.java b/core/java/android/window/TransitionMetrics.java
new file mode 100644
index 0000000..9a93c1a
--- /dev/null
+++ b/core/java/android/window/TransitionMetrics.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2021 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.window;
+
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.os.SystemClock;
+import android.util.Singleton;
+
+/**
+ * A helper class for who plays transition animation can report its metrics easily.
+ * @hide
+ */
+public class TransitionMetrics {
+
+    private final ITransitionMetricsReporter mTransitionMetricsReporter;
+
+    private TransitionMetrics(ITransitionMetricsReporter reporter) {
+        mTransitionMetricsReporter = reporter;
+    }
+
+    /** Reports the current timestamp as when the transition animation starts. */
+    public void reportAnimationStart(IBinder transitionToken) {
+        try {
+            mTransitionMetricsReporter.reportAnimationStart(transitionToken,
+                    SystemClock.elapsedRealtime());
+        } catch (RemoteException e) {
+            e.rethrowFromSystemServer();
+        }
+    }
+
+    /** Gets the singleton instance of TransitionMetrics. */
+    public static TransitionMetrics getInstance() {
+        return sTransitionMetrics.get();
+    }
+
+    private static final Singleton<TransitionMetrics> sTransitionMetrics = new Singleton<>() {
+        @Override
+        protected TransitionMetrics create() {
+            return new TransitionMetrics(WindowOrganizer.getTransitionMetricsReporter());
+        }
+    };
+}
diff --git a/core/java/android/window/WindowOrganizer.java b/core/java/android/window/WindowOrganizer.java
index e9b8174..4ea5ea5 100644
--- a/core/java/android/window/WindowOrganizer.java
+++ b/core/java/android/window/WindowOrganizer.java
@@ -159,7 +159,19 @@
         }
     }
 
-    IWindowOrganizerController getWindowOrganizerController() {
+    /**
+     * @see TransitionMetrics
+     * @hide
+     */
+    public static ITransitionMetricsReporter getTransitionMetricsReporter() {
+        try {
+            return getWindowOrganizerController().getTransitionMetricsReporter();
+        } catch (RemoteException e) {
+            throw e.rethrowFromSystemServer();
+        }
+    }
+
+    static IWindowOrganizerController getWindowOrganizerController() {
         return IWindowOrganizerControllerSingleton.get();
     }
 
diff --git a/core/java/com/android/internal/inputmethod/InputMethodDebug.java b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
index a00b993..bf094db 100644
--- a/core/java/com/android/internal/inputmethod/InputMethodDebug.java
+++ b/core/java/com/android/internal/inputmethod/InputMethodDebug.java
@@ -236,6 +236,8 @@
                 return "HIDE_TOGGLE_SOFT_INPUT";
             case SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API:
                 return "SHOW_SOFT_INPUT_BY_INSETS_API";
+            case SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE:
+                return "HIDE_DISPLAY_IME_POLICY_HIDE";
             default:
                 return "Unknown=" + reason;
         }
diff --git a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
index e3713a3..9e57762 100644
--- a/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
+++ b/core/java/com/android/internal/inputmethod/SoftInputShowHideReason.java
@@ -19,6 +19,7 @@
 import static java.lang.annotation.RetentionPolicy.SOURCE;
 
 import android.annotation.IntDef;
+import android.view.WindowManager;
 import android.view.WindowManager.LayoutParams;
 
 import java.lang.annotation.Retention;
@@ -53,7 +54,8 @@
         SoftInputShowHideReason.SHOW_RESTORE_IME_VISIBILITY,
         SoftInputShowHideReason.SHOW_TOGGLE_SOFT_INPUT,
         SoftInputShowHideReason.HIDE_TOGGLE_SOFT_INPUT,
-        SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API})
+        SoftInputShowHideReason.SHOW_SOFT_INPUT_BY_INSETS_API,
+        SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE})
 public @interface SoftInputShowHideReason {
     /** Show soft input by {@link android.view.inputmethod.InputMethodManager#showSoftInput}. */
     int SHOW_SOFT_INPUT = 0;
@@ -195,4 +197,10 @@
      * {@link android.view.InsetsController#show(int)};
      */
     int SHOW_SOFT_INPUT_BY_INSETS_API = 25;
+
+    /**
+     * Hide soft input if Ime policy has been set to {@link WindowManager#DISPLAY_IME_POLICY_HIDE}.
+     * See also {@code InputMethodManagerService#mImeHiddenByDisplayPolicy}.
+     */
+    int HIDE_DISPLAY_IME_POLICY_HIDE = 26;
 }
diff --git a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
index 93baa19..9443070 100644
--- a/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
+++ b/core/java/com/android/internal/os/AmbientDisplayPowerCalculator.java
@@ -31,12 +31,15 @@
  * Estimates power consumed by the ambient display
  */
 public class AmbientDisplayPowerCalculator extends PowerCalculator {
-    private final UsageBasedPowerEstimator mPowerEstimator;
+    private final UsageBasedPowerEstimator[] mPowerEstimators;
 
     public AmbientDisplayPowerCalculator(PowerProfile powerProfile) {
-        // TODO(b/200239964): update to support multidisplay.
-        mPowerEstimator = new UsageBasedPowerEstimator(
-                powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 0));
+        final int numDisplays = powerProfile.getNumDisplays();
+        mPowerEstimators = new UsageBasedPowerEstimator[numDisplays];
+        for (int display = 0; display < numDisplays; display++) {
+            mPowerEstimators[display] = new UsageBasedPowerEstimator(
+                    powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, display));
+        }
     }
 
     /**
@@ -50,8 +53,8 @@
         final int powerModel = getPowerModel(measuredEnergyUC, query);
         final long durationMs = calculateDuration(batteryStats, rawRealtimeUs,
                 BatteryStats.STATS_SINCE_CHARGED);
-        final double powerMah = getMeasuredOrEstimatedPower(powerModel,
-                measuredEnergyUC, mPowerEstimator, durationMs);
+        final double powerMah = calculateTotalPower(powerModel, batteryStats, rawRealtimeUs,
+                measuredEnergyUC);
         builder.getAggregateBatteryConsumerBuilder(
                 BatteryUsageStats.AGGREGATE_BATTERY_CONSUMER_SCOPE_DEVICE)
                 .setUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY, durationMs)
@@ -71,9 +74,8 @@
         final long measuredEnergyUC = batteryStats.getScreenDozeMeasuredBatteryConsumptionUC();
         final long durationMs = calculateDuration(batteryStats, rawRealtimeUs, statsType);
         final int powerModel = getPowerModel(measuredEnergyUC);
-        final double powerMah = getMeasuredOrEstimatedPower(powerModel,
-                batteryStats.getScreenDozeMeasuredBatteryConsumptionUC(),
-                mPowerEstimator, durationMs);
+        final double powerMah = calculateTotalPower(powerModel, batteryStats, rawRealtimeUs,
+                measuredEnergyUC);
         if (powerMah > 0) {
             BatterySipper bs = new BatterySipper(BatterySipper.DrainType.AMBIENT_DISPLAY, null, 0);
             bs.usagePowerMah = powerMah;
@@ -86,4 +88,26 @@
     private long calculateDuration(BatteryStats batteryStats, long rawRealtimeUs, int statsType) {
         return batteryStats.getScreenDozeTime(rawRealtimeUs, statsType) / 1000;
     }
+
+    private double calculateTotalPower(@BatteryConsumer.PowerModel int powerModel,
+            BatteryStats batteryStats, long rawRealtimeUs, long consumptionUC) {
+        switch (powerModel) {
+            case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
+                return uCtoMah(consumptionUC);
+            case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
+            default:
+                return calculateEstimatedPower(batteryStats, rawRealtimeUs);
+        }
+    }
+
+    private double calculateEstimatedPower(BatteryStats batteryStats, long rawRealtimeUs) {
+        final int numDisplays = mPowerEstimators.length;
+        double power = 0;
+        for (int display = 0; display < numDisplays; display++) {
+            final long dozeTime = batteryStats.getDisplayScreenDozeTime(display, rawRealtimeUs)
+                    / 1000;
+            power += mPowerEstimators[display].calculatePower(dozeTime);
+        }
+        return power;
+    }
 }
diff --git a/core/java/com/android/internal/os/BatteryStatsImpl.java b/core/java/com/android/internal/os/BatteryStatsImpl.java
index 17fdb2e..169eff0 100644
--- a/core/java/com/android/internal/os/BatteryStatsImpl.java
+++ b/core/java/com/android/internal/os/BatteryStatsImpl.java
@@ -903,6 +903,11 @@
          */
         public StopwatchTimer[] screenBrightnessTimers =
                 new StopwatchTimer[NUM_SCREEN_BRIGHTNESS_BINS];
+        /**
+         * Per display screen state the last time {@link #updateDisplayMeasuredEnergyStatsLocked}
+         * was called.
+         */
+        public int screenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
 
         DisplayBatteryStats(Clocks clocks, TimeBase timeBase) {
             screenOnTimer = new StopwatchTimer(clocks, null, -1, null,
@@ -929,6 +934,8 @@
 
     DisplayBatteryStats[] mPerDisplayBatteryStats;
 
+    private int mDisplayMismatchWtfCount = 0;
+
     boolean mInteractive;
     StopwatchTimer mInteractiveTimer;
 
@@ -1073,8 +1080,6 @@
     @GuardedBy("this")
     @VisibleForTesting
     protected @Nullable MeasuredEnergyStats mGlobalMeasuredEnergyStats;
-    /** Last known screen state. Needed for apportioning display energy. */
-    int mScreenStateAtLastEnergyMeasurement = Display.STATE_UNKNOWN;
     /** Bluetooth Power calculator for attributing measured bluetooth charge consumption to uids */
     @Nullable BluetoothPowerCalculator mBluetoothPowerCalculator = null;
     /** Cpu Power calculator for attributing measured cpu charge consumption to uids */
@@ -12924,22 +12929,43 @@
      * is always 0 when the screen is not "ON" and whenever the rail energy is 0 (if supported).
      * To the extent that those assumptions are violated, the algorithm will err.
      *
-     * @param chargeUC amount of charge (microcoulombs) used by Display since this was last called.
-     * @param screenState screen state at the time this data collection was scheduled
+     * @param chargesUC amount of charge (microcoulombs) used by each Display since this was last
+     *                 called.
+     * @param screenStates each screen state at the time this data collection was scheduled
      */
     @GuardedBy("this")
-    public void updateDisplayMeasuredEnergyStatsLocked(long chargeUC, int screenState,
+    public void updateDisplayMeasuredEnergyStatsLocked(long[] chargesUC, int[] screenStates,
             long elapsedRealtimeMs) {
-        if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + chargeUC);
+        if (DEBUG_ENERGY) Slog.d(TAG, "Updating display stats: " + Arrays.toString(chargesUC));
         if (mGlobalMeasuredEnergyStats == null) {
             return;
         }
 
-        final @StandardPowerBucket int powerBucket =
-                MeasuredEnergyStats.getDisplayPowerBucket(mScreenStateAtLastEnergyMeasurement);
-        mScreenStateAtLastEnergyMeasurement = screenState;
+        final int numDisplays;
+        if (mPerDisplayBatteryStats.length == screenStates.length) {
+            numDisplays = screenStates.length;
+        } else {
+            // if this point is reached, it will be reached every display state change.
+            // Rate limit the wtf logging to once every 100 display updates.
+            if (mDisplayMismatchWtfCount++ % 100 == 0) {
+                Slog.wtf(TAG, "Mismatch between PowerProfile reported display count ("
+                        + mPerDisplayBatteryStats.length
+                        + ") and PowerStatsHal reported display count (" + screenStates.length
+                        + ")");
+            }
+            // Keep the show going, use the shorter of the two.
+            numDisplays = mPerDisplayBatteryStats.length < screenStates.length
+                    ? mPerDisplayBatteryStats.length : screenStates.length;
+        }
 
-        if (!mOnBatteryInternal || chargeUC <= 0) {
+        final int[] oldScreenStates = new int[numDisplays];
+        for (int i = 0; i < numDisplays; i++) {
+            final int screenState = screenStates[i];
+            oldScreenStates[i] = mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement;
+            mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
+        }
+
+        if (!mOnBatteryInternal) {
             // There's nothing further to update.
             return;
         }
@@ -12954,17 +12980,31 @@
             return;
         }
 
-        mGlobalMeasuredEnergyStats.updateStandardBucket(powerBucket, chargeUC);
+        long totalScreenOnChargeUC = 0;
+        for (int i = 0; i < numDisplays; i++) {
+            final long chargeUC = chargesUC[i];
+            if (chargeUC <= 0) {
+                // There's nothing further to update.
+                continue;
+            }
+
+            final @StandardPowerBucket int powerBucket =
+                    MeasuredEnergyStats.getDisplayPowerBucket(oldScreenStates[i]);
+            mGlobalMeasuredEnergyStats.updateStandardBucket(powerBucket, chargeUC);
+            if (powerBucket == MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON) {
+                totalScreenOnChargeUC += chargeUC;
+            }
+        }
 
         // Now we blame individual apps, but only if the display was ON.
-        if (powerBucket != MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON) {
+        if (totalScreenOnChargeUC <= 0) {
             return;
         }
         // TODO(b/175726779): Consider unifying the code with the non-rail display power blaming.
 
         // NOTE: fg time is NOT pooled. If two uids are both somehow in fg, then that time is
         // 'double counted' and will simply exceed the realtime that elapsed.
-        // If multidisplay becomes a reality, this is probably more reasonable than pooling.
+        // TODO(b/175726779): collect per display uid visibility for display power attribution.
 
         // Collect total time since mark so that we can normalize power.
         final SparseDoubleArray fgTimeUsArray = new SparseDoubleArray();
@@ -12977,7 +13017,8 @@
             if (fgTimeUs == 0) continue;
             fgTimeUsArray.put(uid.getUid(), (double) fgTimeUs);
         }
-        distributeEnergyToUidsLocked(powerBucket, chargeUC, fgTimeUsArray, 0);
+        distributeEnergyToUidsLocked(MeasuredEnergyStats.POWER_BUCKET_SCREEN_ON,
+                totalScreenOnChargeUC, fgTimeUsArray, 0);
     }
 
     /**
@@ -14883,7 +14924,12 @@
     public void initMeasuredEnergyStatsLocked(@Nullable boolean[] supportedStandardBuckets,
             String[] customBucketNames) {
         boolean supportedBucketMismatch = false;
-        mScreenStateAtLastEnergyMeasurement = mScreenState;
+
+        final int numDisplays = mPerDisplayBatteryStats.length;
+        for (int i = 0; i < numDisplays; i++) {
+            final int screenState = mPerDisplayBatteryStats[i].screenState;
+            mPerDisplayBatteryStats[i].screenStateAtLastEnergyMeasurement = screenState;
+        }
 
         if (supportedStandardBuckets == null) {
             if (mGlobalMeasuredEnergyStats != null) {
diff --git a/core/java/com/android/internal/os/PowerCalculator.java b/core/java/com/android/internal/os/PowerCalculator.java
index 4979ecb..93d562c 100644
--- a/core/java/com/android/internal/os/PowerCalculator.java
+++ b/core/java/com/android/internal/os/PowerCalculator.java
@@ -133,32 +133,6 @@
     }
 
     /**
-     * Returns either the measured energy converted to mAh or a usage-based estimate.
-     */
-    protected static double getMeasuredOrEstimatedPower(@BatteryConsumer.PowerModel int powerModel,
-            long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs) {
-        switch (powerModel) {
-            case BatteryConsumer.POWER_MODEL_MEASURED_ENERGY:
-                return uCtoMah(measuredEnergyUC);
-            case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
-            default:
-                return powerEstimator.calculatePower(durationMs);
-        }
-    }
-
-    /**
-     * Returns either the measured energy converted to mAh or a usage-based estimate.
-     */
-    protected static double getMeasuredOrEstimatedPower(
-            long measuredEnergyUC, UsageBasedPowerEstimator powerEstimator, long durationMs) {
-        if (measuredEnergyUC != BatteryStats.POWER_DATA_UNAVAILABLE) {
-            return uCtoMah(measuredEnergyUC);
-        } else {
-            return powerEstimator.calculatePower(durationMs);
-        }
-    }
-
-    /**
      * Prints formatted amount of power in milli-amp-hours.
      */
     public static void printPowerMah(PrintWriter pw, double powerMah) {
diff --git a/core/java/com/android/internal/os/ScreenPowerCalculator.java b/core/java/com/android/internal/os/ScreenPowerCalculator.java
index 72ad4e7..2b63459 100644
--- a/core/java/com/android/internal/os/ScreenPowerCalculator.java
+++ b/core/java/com/android/internal/os/ScreenPowerCalculator.java
@@ -44,8 +44,8 @@
     // Minimum amount of time the screen should be on to start smearing drain to apps
     public static final long MIN_ACTIVE_TIME_FOR_SMEARING = 10 * DateUtils.MINUTE_IN_MILLIS;
 
-    private final UsageBasedPowerEstimator mScreenOnPowerEstimator;
-    private final UsageBasedPowerEstimator mScreenFullPowerEstimator;
+    private final UsageBasedPowerEstimator[] mScreenOnPowerEstimators;
+    private final UsageBasedPowerEstimator[] mScreenFullPowerEstimators;
 
     private static class PowerAndDuration {
         public long durationMs;
@@ -53,11 +53,16 @@
     }
 
     public ScreenPowerCalculator(PowerProfile powerProfile) {
-        // TODO(b/200239964): update to support multidisplay.
-        mScreenOnPowerEstimator = new UsageBasedPowerEstimator(
-                powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 0));
-        mScreenFullPowerEstimator = new UsageBasedPowerEstimator(
-                powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 0));
+        final int numDisplays = powerProfile.getNumDisplays();
+        mScreenOnPowerEstimators = new UsageBasedPowerEstimator[numDisplays];
+        mScreenFullPowerEstimators = new UsageBasedPowerEstimator[numDisplays];
+        for (int display = 0; display < numDisplays; display++) {
+            mScreenOnPowerEstimators[display] = new UsageBasedPowerEstimator(
+                    powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, display));
+            mScreenFullPowerEstimators[display] = new UsageBasedPowerEstimator(
+                    powerProfile.getAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL,
+                            display));
+        }
     }
 
     @Override
@@ -172,7 +177,7 @@
             case BatteryConsumer.POWER_MODEL_POWER_PROFILE:
             default:
                 totalPowerAndDuration.powerMah = calculateTotalPowerFromBrightness(batteryStats,
-                        rawRealtimeUs, statsType, totalPowerAndDuration.durationMs);
+                        rawRealtimeUs);
         }
     }
 
@@ -194,19 +199,25 @@
         return batteryStats.getScreenOnTime(rawRealtimeUs, statsType) / 1000;
     }
 
-    private double calculateTotalPowerFromBrightness(BatteryStats batteryStats, long rawRealtimeUs,
-            int statsType, long durationMs) {
-        double power = mScreenOnPowerEstimator.calculatePower(durationMs);
-        for (int i = 0; i < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; i++) {
-            final long brightnessTime =
-                    batteryStats.getScreenBrightnessTime(i, rawRealtimeUs, statsType) / 1000;
-            final double binPowerMah = mScreenFullPowerEstimator.calculatePower(brightnessTime)
-                    * (i + 0.5f) / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
-            if (DEBUG && binPowerMah != 0) {
-                Slog.d(TAG, "Screen bin #" + i + ": time=" + brightnessTime
-                        + " power=" + formatCharge(binPowerMah));
+    private double calculateTotalPowerFromBrightness(BatteryStats batteryStats,
+            long rawRealtimeUs) {
+        final int numDisplays = mScreenOnPowerEstimators.length;
+        double power = 0;
+        for (int display = 0; display < numDisplays; display++) {
+            final long displayTime = batteryStats.getDisplayScreenOnTime(display, rawRealtimeUs)
+                    / 1000;
+            power += mScreenOnPowerEstimators[display].calculatePower(displayTime);
+            for (int bin = 0; bin < BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS; bin++) {
+                final long brightnessTime = batteryStats.getDisplayScreenBrightnessTime(display,
+                        bin, rawRealtimeUs) / 1000;
+                final double binPowerMah = mScreenFullPowerEstimators[display].calculatePower(
+                        brightnessTime) * (bin + 0.5f) / BatteryStats.NUM_SCREEN_BRIGHTNESS_BINS;
+                if (DEBUG && binPowerMah != 0) {
+                    Slog.d(TAG, "Screen bin #" + bin + ": time=" + brightnessTime
+                            + " power=" + formatCharge(binPowerMah));
+                }
+                power += binPowerMah;
             }
-            power += binPowerMah;
         }
         return power;
     }
diff --git a/core/java/com/android/internal/policy/SystemBarUtils.java b/core/java/com/android/internal/policy/SystemBarUtils.java
new file mode 100644
index 0000000..6bf1333
--- /dev/null
+++ b/core/java/com/android/internal/policy/SystemBarUtils.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 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.policy;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Insets;
+import android.util.RotationUtils;
+import android.view.DisplayCutout;
+import android.view.Surface;
+
+import com.android.internal.R;
+
+/**
+ * Utility functions for system bars used by both window manager and System UI.
+ *
+ * @hide
+ */
+public final class SystemBarUtils {
+
+    /**
+     * Gets the status bar height.
+     */
+    public static int getStatusBarHeight(Context context) {
+        return getStatusBarHeight(context.getResources(), context.getDisplay().getCutout());
+    }
+
+    /**
+     * Gets the status bar height with a specific display cutout.
+     */
+    public static int getStatusBarHeight(Resources res, DisplayCutout cutout) {
+        final int defaultSize = res.getDimensionPixelSize(R.dimen.status_bar_height);
+        final int safeInsetTop = cutout == null ? 0 : cutout.getSafeInsetTop();
+        final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top;
+        // The status bar height should be:
+        // Max(top cutout size, (status bar default height + waterfall top size))
+        return Math.max(safeInsetTop, defaultSize + waterfallInsetTop);
+    }
+
+    /**
+     * Gets the status bar height for a specific rotation.
+     */
+    public static int getStatusBarHeightForRotation(
+            Context context, @Surface.Rotation int targetRot) {
+        final int rotation = context.getDisplay().getRotation();
+        final DisplayCutout cutout = context.getDisplay().getCutout();
+
+        Insets insets = cutout == null ? Insets.NONE : Insets.of(cutout.getSafeInsets());
+        Insets waterfallInsets = cutout == null ? Insets.NONE : cutout.getWaterfallInsets();
+        // rotate insets to target rotation if needed.
+        if (rotation != targetRot) {
+            if (!insets.equals(Insets.NONE)) {
+                insets = RotationUtils.rotateInsets(
+                        insets, RotationUtils.deltaRotation(rotation, targetRot));
+            }
+            if (!waterfallInsets.equals(Insets.NONE)) {
+                waterfallInsets = RotationUtils.rotateInsets(
+                        waterfallInsets, RotationUtils.deltaRotation(rotation, targetRot));
+            }
+        }
+        final int defaultSize =
+                context.getResources().getDimensionPixelSize(R.dimen.status_bar_height);
+        // The status bar height should be:
+        // Max(top cutout size, (status bar default height + waterfall top size))
+        return Math.max(insets.top, defaultSize + waterfallInsets.top);
+    }
+
+    /**
+     * Gets the height of area above QQS where battery/time go in notification panel. The height
+     * equals to status bar height if status bar height is bigger than the
+     * {@link R.dimen#quick_qs_offset_height}.
+     */
+    public static int getQuickQsOffsetHeight(Context context) {
+        final int defaultSize = context.getResources().getDimensionPixelSize(
+                R.dimen.quick_qs_offset_height);
+        final int statusBarHeight = getStatusBarHeight(context);
+        // Equals to status bar height if status bar height is bigger.
+        return Math.max(defaultSize, statusBarHeight);
+    }
+}
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index 6f81b82..c750ead 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -202,7 +202,6 @@
     optional .com.android.server.wm.IdentifierProto resumed_activity = 24;
     repeated TaskProto tasks = 25 [deprecated=true];
     optional bool display_ready = 26;
-
     optional WindowStateProto input_method_target = 27;
     optional WindowStateProto input_method_input_target = 28;
     optional WindowStateProto input_method_control_target = 29;
@@ -212,6 +211,8 @@
 
     optional DisplayRotationProto display_rotation = 33;
     optional int32 ime_policy = 34;
+    optional bool is_sleeping = 36;
+    repeated string sleep_tokens = 37;
 }
 
 /* represents DisplayArea object */
@@ -364,6 +365,7 @@
     optional bool translucent = 30;
     optional bool pip_auto_enter_enabled = 31;
     optional bool in_size_compat_mode = 32;
+    optional float min_aspect_ratio = 33;
 }
 
 /* represents WindowToken */
diff --git a/core/res/OWNERS b/core/res/OWNERS
index 7a8da36..bd19208 100644
--- a/core/res/OWNERS
+++ b/core/res/OWNERS
@@ -25,3 +25,9 @@
 toddke@google.com
 tsuji@google.com
 yamasani@google.com
+
+# Multiuser
+per-file res/xml/config_user_types.xml = file:/MULTIUSER_OWNERS
+
+# Car
+per-file res/values/dimens_car.xml = file:/platform/packages/services/Car:/OWNERS
diff --git a/core/res/res/values-as/strings.xml b/core/res/res/values-as/strings.xml
index 8aafa0a..f9786ed 100644
--- a/core/res/res/values-as/strings.xml
+++ b/core/res/res/values-as/strings.xml
@@ -291,12 +291,12 @@
     <string name="notification_channel_retail_mode" msgid="3732239154256431213">"খুচুৰা ডেম\'"</string>
     <string name="notification_channel_usb" msgid="1528280969406244896">"ইউএছবি সংযোগ"</string>
     <string name="notification_channel_heavy_weight_app" msgid="17455756500828043">"এপ্ চলি আছে"</string>
-    <string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰি খৰচ কৰা এপসমূহ"</string>
+    <string name="notification_channel_foreground_service" msgid="7102189948158885178">"বেটাৰী খৰচ কৰা এপ্‌সমূহ"</string>
     <string name="notification_channel_accessibility_magnification" msgid="1707913872219798098">"বিবৰ্ধন"</string>
     <string name="notification_channel_accessibility_security_policy" msgid="1727787021725251912">"সাধ্য সুবিধাৰ ব্যৱহাৰ"</string>
-    <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
-    <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰি ব্যৱহাৰ কৰি আছে"</string>
-    <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string>
+    <string name="foreground_service_app_in_background" msgid="1439289699671273555">"<xliff:g id="APP_NAME">%1$s</xliff:g>এ বেটাৰী ব্যৱহাৰ কৰি আছে"</string>
+    <string name="foreground_service_apps_in_background" msgid="7340037176412387863">"<xliff:g id="NUMBER">%1$d</xliff:g>টা এপে বেটাৰী ব্যৱহাৰ কৰি আছে"</string>
+    <string name="foreground_service_tap_for_details" msgid="9078123626015586751">"বেটাৰী আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে সবিশেষ জানিবলৈ টিপক"</string>
     <string name="foreground_service_multiple_separator" msgid="5002287361849863168">"<xliff:g id="LEFT_SIDE">%1$s</xliff:g>, <xliff:g id="RIGHT_SIDE">%2$s</xliff:g>"</string>
     <string name="safeMode" msgid="8974401416068943888">"সুৰক্ষিত ম\'ড"</string>
     <string name="android_system_label" msgid="5974767339591067210">"Android ছিষ্টেম"</string>
@@ -389,7 +389,7 @@
     <string name="permlab_systemAlertWindow" msgid="5757218350944719065">"এই এপটো অইন এপৰ ওপৰত প্ৰদৰ্শিত হ\'ব পাৰে"</string>
     <string name="permdesc_systemAlertWindow" msgid="1145660714855738308">"এই এপ্‌টো অন্য এপৰ ওপৰত বা স্ক্ৰীনৰ অন্য অংশত প্ৰদৰ্শিত হ\'ব পাৰে। এই কাৰ্যই এপৰ স্বাভাৱিক ব্যৱহাৰত ব্যাঘাত জন্মাব পাৰে আৰু অন্য এপ্‌সমূহক স্ক্ৰীনত কেনেকৈ দেখা পোৱা যায় সেইটো সলনি কৰিব পাৰে।"</string>
     <string name="permlab_runInBackground" msgid="541863968571682785">"নেপথ্যত চলিব পাৰে"</string>
-    <string name="permdesc_runInBackground" msgid="4344539472115495141">"এই এপটো নেপথ্যত চলিব পাৰে। ইয়াৰ ফলত বেটাৰি সোনকালে শেষ হ\'ব পাৰে।"</string>
+    <string name="permdesc_runInBackground" msgid="4344539472115495141">"এই এপ্‌টো নেপথ্যত চলিব পাৰে। ইয়াৰ ফলত বেটাৰী সোনকালে শেষ হ’ব পাৰে।"</string>
     <string name="permlab_useDataInBackground" msgid="783415807623038947">"নেপথ্যত ডেটা ব্যৱহাৰ কৰিব পাৰে"</string>
     <string name="permdesc_useDataInBackground" msgid="1230753883865891987">"এই এপটোৱে নেপথ্যত ডেটা ব্যৱহাৰ কৰিব পাৰে। ইয়াৰ ফলত ডেটা বেছি খৰছ হ\'ব পাৰে।"</string>
     <string name="permlab_persistentActivity" msgid="464970041740567970">"এপক সদায়ে চলি থকা কৰক"</string>
@@ -1462,8 +1462,8 @@
     <string name="permdesc_requestInstallPackages" msgid="3969369278325313067">"পেকেজ ইনষ্টল কৰাৰ অনুৰোধ প্ৰেৰণ কৰিবলৈ এপটোক অনুমতি দিয়ে।"</string>
     <string name="permlab_requestDeletePackages" msgid="2541172829260106795">"পেকেজ মচাৰ অনুৰোধ কৰিব পাৰে"</string>
     <string name="permdesc_requestDeletePackages" msgid="6133633516423860381">"এপটোক পেকেজবোৰ মচাৰ অনুৰোধ কৰিবলৈ দিয়ে।"</string>
-    <string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"বেটাৰি অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ বিচাৰক"</string>
-    <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"কোনো এপক সেই এপটোৰ বাবে বেটাৰি অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ অনুমতি বিচাৰিবলৈ দিয়ে।"</string>
+    <string name="permlab_requestIgnoreBatteryOptimizations" msgid="7646611326036631439">"বেটাৰী অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ বিচাৰক"</string>
+    <string name="permdesc_requestIgnoreBatteryOptimizations" msgid="634260656917874356">"কোনো এপক সেই এপ্‌টোৰ বাবে বেটাৰী অপ্টিমাইজেশ্বন উপেক্ষা কৰিবলৈ অনুমতি বিচাৰিবলৈ দিয়ে।"</string>
     <string name="permlab_queryAllPackages" msgid="2928450604653281650">"আটাইবোৰ পেকেজত প্ৰশ্ন সোধক"</string>
     <string name="permdesc_queryAllPackages" msgid="5339069855520996010">"এপক আটাইবোৰ ইনষ্টল কৰি থোৱা পেকেজ চাবলৈ দিয়ে।"</string>
     <string name="tutorial_double_tap_to_zoom_message_short" msgid="1842872462124648678">"জুম নিয়ন্ত্ৰণ কৰিবলৈ দুবাৰ টিপক"</string>
@@ -2103,10 +2103,10 @@
     <string name="nas_upgrade_notification_learn_more_action" msgid="7011130656195423947">"অধিক জানক"</string>
     <string name="nas_upgrade_notification_learn_more_content" msgid="3735480566983530650">"Android 12ত Androidৰ অভিযোজিত জাননীক উন্নত জাননীৰ দ্বাৰা সলনি কৰা হৈছে। এই সুবিধাটোৱে পৰামৰ্শ দিয়া কাৰ্য আৰু প্ৰত্যুত্তৰ দেখুৱায় আৰু আপোনাৰ জাননীসমূহ শৃংখলাবদ্ধ কৰে।\n\nউন্নত জাননীয়ে সম্পৰ্কৰ নাম আৰু বাৰ্তাৰ দৰে ব্যক্তিগত তথ্যকে ধৰি জাননীৰ সমল এক্সেছ কৰিব পাৰে। এই সুবিধাটোৱে জাননী অগ্ৰাহ্য কৰিব অথবা জাননীৰ প্ৰতি সঁহাৰি জনাবও পাৰে, যেনে ফ’ন কলৰ উত্তৰ দিয়া আৰু অসুবিধা নিদিব সুবিধাটো নিয়ন্ত্ৰণ কৰা আদি।"</string>
     <string name="dynamic_mode_notification_channel_name" msgid="2986926422100223328">"ৰুটিন ম’ডৰ তথ্য জাননী"</string>
-    <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"চ্চাৰ্জ কৰাৰ সচৰাচৰ সময়ৰ আগতেই বেটাৰি শেষ হ’ব পাৰে"</string>
-    <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"বেটাৰিৰ খৰচ কমাবলৈ বেটাৰি সঞ্চয়কাৰী অন কৰা হৈছে"</string>
+    <string name="dynamic_mode_notification_title" msgid="9205715501274608016">"চাৰ্জ কৰাৰ সচৰাচৰ সময়ৰ আগতেই বেটাৰী শেষ হ’ব পাৰে"</string>
+    <string name="dynamic_mode_notification_summary" msgid="4141614604437372157">"বেটাৰীৰ খৰচ কমাবলৈ বেটাৰী সঞ্চয়কাৰী অন কৰা হৈছে"</string>
     <string name="battery_saver_notification_channel_name" msgid="3918243458067916913">"বেটাৰী সঞ্চয়কাৰী"</string>
-    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"বেটাৰি সঞ্চয়কাৰী অফ কৰা হ’ল"</string>
+    <string name="battery_saver_off_notification_title" msgid="7637255960468032515">"বেটাৰী সঞ্চয়কাৰী অফ কৰা হ’ল"</string>
     <string name="battery_saver_charged_notification_summary" product="default" msgid="5544457317418624367">"ফ\'নটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
     <string name="battery_saver_charged_notification_summary" product="tablet" msgid="4426317048139996888">"টেবলেটটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
     <string name="battery_saver_charged_notification_summary" product="device" msgid="1031562417867646649">"ডিভাইচটোত পর্যাপ্ত পৰিমাণে চার্জ আছে। সুবিধাবোৰ আৰু সীমাবদ্ধ কৰা নাই।"</string>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index ca549ae..f1e5888 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -27,8 +27,6 @@
     <dimen name="password_keyboard_spacebar_vertical_correction">2dip</dimen>
     <dimen name="preference_widget_width">72dp</dimen>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height">@dimen/status_bar_height_landscape</dimen>
     <!-- Height of area above QQS where battery/time go -->
     <dimen name="quick_qs_offset_height">48dp</dimen>
     <!-- Default height of an action bar. -->
diff --git a/core/res/res/values-te/strings.xml b/core/res/res/values-te/strings.xml
index 0cadb45..8c30ebc 100644
--- a/core/res/res/values-te/strings.xml
+++ b/core/res/res/values-te/strings.xml
@@ -430,7 +430,7 @@
     <string name="permdesc_readCalendar" product="tablet" msgid="515452384059803326">"ఈ యాప్ మీ టాబ్లెట్‌లో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్‌లన్నీ చదవగలదు మరియు మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string>
     <string name="permdesc_readCalendar" product="tv" msgid="5811726712981647628">"ఈ యాప్‌ మీ Android TV పరికరంలో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్‌లన్నీ చదవగలదు, మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string>
     <string name="permdesc_readCalendar" product="default" msgid="9118823807655829957">"ఈ యాప్ మీ ఫోన్‌లో నిల్వ చేసిన క్యాలెండర్ ఈవెంట్‌లన్నీ చదవగలదు మరియు మీ క్యాలెండర్ డేటాను షేర్ చేయగలదు లేదా సేవ్ చేయగలదు."</string>
-    <string name="permlab_writeCalendar" msgid="6422137308329578076">"యజమానికి తెలియకుండానే క్యాలెండర్ ఈవెంట్‌లను జోడించి లేదా సవరించి, అతిథులకు ఇమెయిల్ పంపడం"</string>
+    <string name="permlab_writeCalendar" msgid="6422137308329578076">"యజమానికి తెలియకుండానే క్యాలెండర్ ఈవెంట్‌లను జోడించి లేదా సవరించి, అతిథులకు ఈమెయిల్‌ పంపడం"</string>
     <string name="permdesc_writeCalendar" product="tablet" msgid="8722230940717092850">"ఈ యాప్ మీ టాబ్లెట్‌లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్‌లను పంపగలదు లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string>
     <string name="permdesc_writeCalendar" product="tv" msgid="951246749004952706">"ఈ యాప్ మీ Android TV పరికరంలో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్‌లను పంపగలదు లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string>
     <string name="permdesc_writeCalendar" product="default" msgid="5416380074475634233">"ఈ యాప్ మీ ఫోన్‌లో క్యాలెండర్ ఈవెంట్లను జోడించగలదు, తీసివేయగలదు లేదా మార్చగలదు. ఈ యాప్ క్యాలెండర్ ఓనర్ల నుండి వచ్చినట్లుగా మెసేజ్‌లను పంపగలదు, లేదా ఈవెంట్లను వాటి ఓనర్లకు తెలియకుండానే మార్చగలదు."</string>
@@ -929,7 +929,7 @@
     <string name="lockscreen_glogin_forgot_pattern" msgid="9218940117797602518">"ఖాతా అన్‌లాక్"</string>
     <string name="lockscreen_glogin_too_many_attempts" msgid="3775904917743034195">"చాలా ఎక్కువ ఆకృతి ప్రయత్నాలు చేశారు"</string>
     <string name="lockscreen_glogin_instructions" msgid="4695162942525531700">"అన్‌లాక్ చేయడానికి, మీ Google ఖాతాతో సైన్ ఇన్ చేయండి."</string>
-    <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"వినియోగదారు పేరు (ఇమెయిల్)"</string>
+    <string name="lockscreen_glogin_username_hint" msgid="6916101478673157045">"వినియోగదారు పేరు (ఈమెయిల్‌)"</string>
     <string name="lockscreen_glogin_password_hint" msgid="3031027901286812848">"పాస్‌వర్డ్"</string>
     <string name="lockscreen_glogin_submit_button" msgid="3590556636347843733">"సైన్ ఇన్ చేయి"</string>
     <string name="lockscreen_glogin_invalid_input" msgid="4369219936865697679">"వినియోగదారు పేరు లేదా పాస్‌వర్డ్ చెల్లదు."</string>
@@ -1668,7 +1668,7 @@
     <string name="kg_invalid_confirm_pin_hint" product="default" msgid="4705368340409816254">"పిన్‌ కోడ్‌లు సరిపోలలేదు"</string>
     <string name="kg_login_too_many_attempts" msgid="699292728290654121">"చాలా ఎక్కువ ఆకృతి ప్రయత్నాలు చేశారు"</string>
     <string name="kg_login_instructions" msgid="3619844310339066827">"అన్‌లాక్ చేయడానికి, మీ Google ఖాతాతో సైన్ ఇన్ చేయండి."</string>
-    <string name="kg_login_username_hint" msgid="1765453775467133251">"వినియోగదారు పేరు (ఇమెయిల్)"</string>
+    <string name="kg_login_username_hint" msgid="1765453775467133251">"వినియోగదారు పేరు (ఈమెయిల్‌)"</string>
     <string name="kg_login_password_hint" msgid="3330530727273164402">"పాస్‌వర్డ్"</string>
     <string name="kg_login_submit_button" msgid="893611277617096870">"సైన్ ఇన్ చేయి"</string>
     <string name="kg_login_invalid_input" msgid="8292367491901220210">"చెల్లని వినియోగదారు పేరు లేదా పాస్‌వర్డ్."</string>
@@ -1683,9 +1683,9 @@
     <string name="kg_failed_attempts_now_wiping" product="tablet" msgid="2299099385175083308">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. టాబ్లెట్ ఇప్పుడు ఫ్యాక్టరీ ఆటోమేటిక్‌కు రీసెట్ చేయబడుతుంది."</string>
     <string name="kg_failed_attempts_now_wiping" product="tv" msgid="5045460916106267585">"మీరు మీ Android TV పరికరాన్ని అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు విఫల ప్రయత్నాలు చేశారు. మీ Android TV పరికరం ఇప్పుడు ఫ్యాక్టరీ రీసెట్ చేయబడుతుంది."</string>
     <string name="kg_failed_attempts_now_wiping" product="default" msgid="5043730590446071189">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> చెల్లని ప్రయత్నాలు చేశారు. ఫోన్ ఇప్పుడు ఫ్యాక్టరీ ఆటోమేటిక్‌కు రీసెట్ చేయబడుతుంది."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత మీ Android TV పరికరాన్ని ఇమెయిల్ ఖాతా ద్వారా అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని కోరడం జరుగుతుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="7086799295109717623">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tv" msgid="4670840383567106114">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత మీ Android TV పరికరాన్ని ఈమెయిల్‌ ఖాతా ద్వారా అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని కోరడం జరుగుతుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="5270861875006378092">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> విఫల ప్రయత్నాల తర్వాత, ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సిందిగా మిమ్మల్ని అడుగుతారు.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="kg_text_message_separator" product="default" msgid="4503708889934976866">" — "</string>
     <string name="kg_reordering_delete_drop_target_text" msgid="2034358143731750914">"తీసివేయి"</string>
     <string name="safe_media_volume_warning" product="default" msgid="3751676824423049994">"వాల్యూమ్‌ను సిఫార్సు చేయబడిన స్థాయి కంటే ఎక్కువగా పెంచాలా?\n\nసుదీర్ఘ వ్యవధుల పాటు అధిక వాల్యూమ్‌లో వినడం వలన మీ వినికిడి శక్తి దెబ్బ తినవచ్చు."</string>
@@ -2051,7 +2051,7 @@
     <string name="autofill_save_type_payment_card" msgid="6555012156728690856">"చెల్లింపు కార్డ్"</string>
     <string name="autofill_save_type_generic_card" msgid="1019367283921448608">"కార్డ్"</string>
     <string name="autofill_save_type_username" msgid="1018816929884640882">"వినియోగదారు పేరు"</string>
-    <string name="autofill_save_type_email_address" msgid="1303262336895591924">"ఇమెయిల్ అడ్రస్‌"</string>
+    <string name="autofill_save_type_email_address" msgid="1303262336895591924">"ఈమెయిల్‌ అడ్రస్‌"</string>
     <string name="etws_primary_default_message_earthquake" msgid="8401079517718280669">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
     <string name="etws_primary_default_message_tsunami" msgid="5828171463387976279">"వెంటనే తీర ప్రాంతాలు మరియు నదీ పరీవాహక ప్రాంతాలను ఖాళీ చేసి మెట్ట ప్రాంతాలకు తరలి వెళ్లండి."</string>
     <string name="etws_primary_default_message_earthquake_and_tsunami" msgid="4888224011071875068">"ప్రశాంతంగా ఉండండి మరియు దగ్గర్లో తలదాచుకోండి."</string>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 3718d28..32db186 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -2326,10 +2326,6 @@
     <!-- Type of the ambient tap sensor per device posture (defined by WM Jetpack posture).
          Unspecified values use config_dozeTapSensor -->
     <string-array name="config_dozeTapSensorPostureMapping" translatable="false">
-        <item></item> <!-- UNKNOWN -->
-        <item></item> <!-- CLOSED -->
-        <item></item> <!-- HALF_OPENED -->
-        <item></item> <!-- OPENED -->
     </string-array>
 
     <!-- Type of the long press sensor. Empty if long press is not supported. -->
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index ab923d0..0706d8a 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -39,15 +39,21 @@
     <!-- Elevation of toast view -->
     <dimen name="toast_elevation">2dp</dimen>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height">@dimen/status_bar_height_portrait</dimen>
-    <!-- Height of the status bar in portrait. The height should be
-         Max((status bar content height + waterfall top size), top cutout size) -->
-    <dimen name="status_bar_height_portrait">24dp</dimen>
-    <!-- Height of the status bar in landscape. The height should be
-         Max((status bar content height + waterfall top size), top cutout size) -->
+    <!-- Height of the status bar.
+         Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
+         -->
+    <dimen name="status_bar_height">24dp</dimen>
+    <!-- Height of the status bar in portrait.
+         Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
+         -->
+    <dimen name="status_bar_height_portrait">@dimen/status_bar_height</dimen>
+    <!-- Height of the status bar in landscape.
+         Do not read this dimen directly. Use {@link SystemBarUtils#getStatusBarHeight} instead.
+         -->
     <dimen name="status_bar_height_landscape">@dimen/status_bar_height_portrait</dimen>
-    <!-- Height of area above QQS where battery/time go -->
+    <!-- Height of area above QQS where battery/time go.
+         Do not read this dimen directly. Use {@link SystemBarUtils#getQuickQsOffsetHeight} instead.
+         -->
     <dimen name="quick_qs_offset_height">48dp</dimen>
     <!-- Height of the bottom navigation / system bar. -->
     <dimen name="navigation_bar_height">48dp</dimen>
diff --git a/core/res/res/values/dimens_car.xml b/core/res/res/values/dimens_car.xml
index 36f1edb..c5dddb8 100644
--- a/core/res/res/values/dimens_car.xml
+++ b/core/res/res/values/dimens_car.xml
@@ -17,7 +17,7 @@
 -->
 <resources>
     <dimen name="car_large_avatar_size">96dp</dimen>
-    <dimen name="car_large_avatar_badge_size">32dp</dimen>
+    <dimen name="car_large_avatar_badge_size">24dp</dimen>
     <!-- Application Bar -->
     <dimen name="car_app_bar_height">80dp</dimen>
     <!-- Margin -->
diff --git a/core/res/res/values/public.xml b/core/res/res/values/public.xml
index 7d48904..1e30131 100644
--- a/core/res/res/values/public.xml
+++ b/core/res/res/values/public.xml
@@ -1235,7 +1235,6 @@
   <public type="attr" name="author" id="0x010102b4" />
   <public type="attr" name="autoStart" id="0x010102b5" />
 
-
 <!-- ===============================================================
      Resources added in version 8 of the platform (Eclair MR2).
      =============================================================== -->
@@ -3202,89 +3201,23 @@
 
   <!-- ===============================================================
     Resources added in version S-V2 of the platform
-
-    NOTE: add <public> elements within a <staging-public-group> like so:
-
-    <staging-public-group type="attr" first-id="0x01ff0000">
-        <public name="exampleAttr1" />
-        <public name="exampleAttr2" />
-    </staging-public-group>
-
-    To add a new <staging-public-group> block, find the id value for the
-    last <staging-public-group> block defined for thie API level, and
-    subtract 0x00010000 from it to get to the id of the new block.
-
-    For example, if the block closest to the end of this file has an id of
-    0x01ee0000, the id of the new block should be 0x01ed0000
-    (0x01ee0000 - 0x00010000 = 0x01ed0000).
     =============================================================== -->
   <eat-comment />
 
-  <staging-public-group type="attr" first-id="0x01ff0000">
+  <staging-public-group-final type="attr" first-id="0x01ff0000">
     <public name="shouldUseDefaultUnfoldTransition" />
-  </staging-public-group>
+  </staging-public-group-final>
 
-  <staging-public-group type="id" first-id="0x01fe0000">
+  <public type="attr" name="shouldUseDefaultUnfoldTransition" id="0x0101064c" />
+
+  <staging-public-group-final type="id" first-id="0x01fe0000">
     <public name="accessibilityActionDragStart" />
     <public name="accessibilityActionDragDrop" />
     <public name="accessibilityActionDragCancel" />
-  </staging-public-group>
+  </staging-public-group-final>
 
-  <staging-public-group type="style" first-id="0x01fd0000">
-  </staging-public-group>
-
-  <staging-public-group type="string" first-id="0x01fc0000">
-  </staging-public-group>
-
-  <staging-public-group type="dimen" first-id="0x01fb0000">
-  </staging-public-group>
-
-  <staging-public-group type="color" first-id="0x01fa0000">
-  </staging-public-group>
-
-  <staging-public-group type="array" first-id="0x01f90000">
-  </staging-public-group>
-
-  <staging-public-group type="drawable" first-id="0x01f80000">
-  </staging-public-group>
-
-  <staging-public-group type="layout" first-id="0x01f70000">
-  </staging-public-group>
-
-  <staging-public-group type="anim" first-id="0x01f60000">
-  </staging-public-group>
-
-  <staging-public-group type="animator" first-id="0x01f50000">
-  </staging-public-group>
-
-  <staging-public-group type="interpolator" first-id="0x01f40000">
-  </staging-public-group>
-
-  <staging-public-group type="mipmap" first-id="0x01f30000">
-  </staging-public-group>
-
-  <staging-public-group type="integer" first-id="0x01f20000">
-  </staging-public-group>
-
-  <staging-public-group type="transition" first-id="0x01f10000">
-  </staging-public-group>
-
-  <staging-public-group type="raw" first-id="0x01f00000">
-  </staging-public-group>
-
-  <staging-public-group type="bool" first-id="0x01ef0000">
-  </staging-public-group>
-
-  <staging-public-group type="fraction" first-id="0x01ee0000">
-  </staging-public-group>
-
-  <!-- ===============================================================
-       DO NOT ADD UN-GROUPED ITEMS HERE
-
-       Any new items (attrs, styles, ids, etc.) *must* be added in a
-       staging-public-group block, as the preceding comment explains.
-       Items added outside of a group may have their value recalculated
-       every time something new is added to this file.
-       =============================================================== -->
+  <public type="id" name="accessibilityActionDragStart" id="0x01020055" />
+  <public type="id" name="accessibilityActionDragDrop" id="0x01020056" />
+  <public type="id" name="accessibilityActionDragCancel" id="0x01020057" />
 
 </resources>
diff --git a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
index e95f6c2..130f552 100644
--- a/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/AmbientDisplayPowerCalculatorTest.java
@@ -38,26 +38,28 @@
 
     @Rule
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
-            .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 0, 10.0);
+            .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 0, 10.0)
+            .setNumDisplays(1);
 
     @Test
     public void testMeasuredEnergyBasedModel() {
         mStatsRule.initMeasuredEnergyStatsLocked();
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
 
-        stats.updateDisplayMeasuredEnergyStatsLocked(300_000_000, Display.STATE_ON, 0);
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{300_000_000},
+                new int[]{Display.STATE_ON}, 0);
 
         stats.noteScreenStateLocked(0, Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
                 30 * MINUTE_IN_MS);
 
-        stats.updateDisplayMeasuredEnergyStatsLocked(200_000_000, Display.STATE_DOZE,
-                30 * MINUTE_IN_MS);
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{200_000_000},
+                new int[]{Display.STATE_DOZE}, 30 * MINUTE_IN_MS);
 
         stats.noteScreenStateLocked(0, Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
                 120 * MINUTE_IN_MS);
 
-        stats.updateDisplayMeasuredEnergyStatsLocked(100_000_000, Display.STATE_OFF,
-                120 * MINUTE_IN_MS);
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{100_000_000},
+                new int[]{Display.STATE_OFF}, 120 * MINUTE_IN_MS);
 
         AmbientDisplayPowerCalculator calculator =
                 new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
@@ -75,6 +77,67 @@
     }
 
     @Test
+    public void testMeasuredEnergyBasedModel_multiDisplay() {
+        mStatsRule.initMeasuredEnergyStatsLocked()
+                .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 1, 20.0)
+                .setNumDisplays(2);
+        BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+
+
+        final int[] screenStates = new int[] {Display.STATE_OFF, Display.STATE_OFF};
+
+        stats.noteScreenStateLocked(0, screenStates[0], 0, 0, 0);
+        stats.noteScreenStateLocked(1, screenStates[1], 0, 0, 0);
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{300, 400}, screenStates, 0);
+
+        // Switch display0 to doze
+        screenStates[0] = Display.STATE_DOZE;
+        stats.noteScreenStateLocked(0, screenStates[0], 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
+                30 * MINUTE_IN_MS);
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{200, 300},
+                screenStates, 30 * MINUTE_IN_MS);
+
+        // Switch display1 to doze
+        screenStates[1] = Display.STATE_DOZE;
+        stats.noteScreenStateLocked(1, Display.STATE_DOZE, 90 * MINUTE_IN_MS, 90 * MINUTE_IN_MS,
+                90 * MINUTE_IN_MS);
+        // 100,000,000 uC should be attributed to display 0 doze here.
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{100_000_000, 700_000_000},
+                screenStates, 90 * MINUTE_IN_MS);
+
+        // Switch display0 to off
+        screenStates[0] = Display.STATE_OFF;
+        stats.noteScreenStateLocked(0, screenStates[0], 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
+                120 * MINUTE_IN_MS);
+        // 40,000,000 and 70,000,000 uC should be attributed to display 0 and 1 doze here.
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{40_000_000, 70_000_000},
+                screenStates, 120 * MINUTE_IN_MS);
+
+        // Switch display1 to off
+        screenStates[1] = Display.STATE_OFF;
+        stats.noteScreenStateLocked(1, screenStates[1], 150 * MINUTE_IN_MS, 150 * MINUTE_IN_MS,
+                150 * MINUTE_IN_MS);
+        stats.updateDisplayMeasuredEnergyStatsLocked(new long[]{100, 90_000_000}, screenStates,
+                150 * MINUTE_IN_MS);
+        // 90,000,000 uC should be attributed to display 1 doze here.
+
+        AmbientDisplayPowerCalculator calculator =
+                new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
+
+        mStatsRule.apply(calculator);
+
+        BatteryConsumer consumer = mStatsRule.getDeviceBatteryConsumer();
+        assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
+                .isEqualTo(120 * MINUTE_IN_MS);
+        // 100,000,000 + 40,000,000 + 70,000,000 + 90,000,000 uC / 1000 (micro-/milli-) / 3600
+        // (seconds/hour) = 27.777778 mAh
+        assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
+                .isWithin(PRECISION).of(83.33333);
+        assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+    }
+
+    @Test
     public void testPowerProfileBasedModel() {
         BatteryStatsImpl stats = mStatsRule.getBatteryStats();
 
@@ -96,4 +159,36 @@
         assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
                 .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
     }
+
+    @Test
+    public void testPowerProfileBasedModel_multiDisplay() {
+        mStatsRule.setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_AMBIENT, 1, 20.0)
+                .setNumDisplays(2);
+
+        BatteryStatsImpl stats = mStatsRule.getBatteryStats();
+
+        stats.noteScreenStateLocked(1, Display.STATE_OFF, 0, 0, 0);
+        stats.noteScreenStateLocked(0, Display.STATE_DOZE, 30 * MINUTE_IN_MS, 30 * MINUTE_IN_MS,
+                30 * MINUTE_IN_MS);
+        stats.noteScreenStateLocked(1, Display.STATE_DOZE, 90 * MINUTE_IN_MS, 90 * MINUTE_IN_MS,
+                90 * MINUTE_IN_MS);
+        stats.noteScreenStateLocked(0, Display.STATE_OFF, 120 * MINUTE_IN_MS, 120 * MINUTE_IN_MS,
+                120 * MINUTE_IN_MS);
+        stats.noteScreenStateLocked(1, Display.STATE_OFF, 150 * MINUTE_IN_MS, 150 * MINUTE_IN_MS,
+                150 * MINUTE_IN_MS);
+
+        AmbientDisplayPowerCalculator calculator =
+                new AmbientDisplayPowerCalculator(mStatsRule.getPowerProfile());
+
+        mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
+
+        BatteryConsumer consumer = mStatsRule.getDeviceBatteryConsumer();
+        // Duration should only be the union of
+        assertThat(consumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
+                .isEqualTo(120 * MINUTE_IN_MS);
+        assertThat(consumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
+                .isWithin(PRECISION).of(35.0);
+        assertThat(consumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+    }
 }
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
index 4adc09d..3e2885a 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryStatsNoteTest.java
@@ -998,7 +998,7 @@
         bi.initMeasuredEnergyStats(new String[]{"FOO", "BAR"});
 
         clocks.realtime = 0;
-        int screen = Display.STATE_OFF;
+        int[] screen = new int[]{Display.STATE_OFF};
         boolean battery = false;
 
         final int uid1 = 10500;
@@ -1008,35 +1008,35 @@
         long globalDoze = 0;
 
         // Case A: uid1 off, uid2 off, battery off, screen off
-        bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0);
+        bi.updateTimeBasesLocked(battery, screen[0], clocks.realtime * 1000, 0);
         bi.setOnBatteryInternal(battery);
-        bi.updateDisplayMeasuredEnergyStatsLocked(500_000, screen, clocks.realtime);
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{500_000}, screen, clocks.realtime);
         checkMeasuredCharge("A", uid1, blame1, uid2, blame2, globalDoze, bi);
 
         // Case B: uid1 off, uid2 off, battery ON,  screen off
         clocks.realtime += 17;
         battery = true;
-        bi.updateTimeBasesLocked(battery, screen, clocks.realtime*1000, 0);
+        bi.updateTimeBasesLocked(battery, screen[0], clocks.realtime * 1000, 0);
         bi.setOnBatteryInternal(battery);
         clocks.realtime += 19;
-        bi.updateDisplayMeasuredEnergyStatsLocked(510_000, screen, clocks.realtime);
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{510_000}, screen, clocks.realtime);
         checkMeasuredCharge("B", uid1, blame1, uid2, blame2, globalDoze, bi);
 
         // Case C: uid1 ON,  uid2 off, battery on,  screen off
         clocks.realtime += 18;
         setFgState(uid1, true, bi);
         clocks.realtime += 18;
-        bi.updateDisplayMeasuredEnergyStatsLocked(520_000, screen, clocks.realtime);
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{520_000}, screen, clocks.realtime);
         checkMeasuredCharge("C", uid1, blame1, uid2, blame2, globalDoze, bi);
 
         // Case D: uid1 on,  uid2 off, battery on,  screen ON
         clocks.realtime += 17;
-        screen = Display.STATE_ON;
-        bi.updateDisplayMeasuredEnergyStatsLocked(521_000, screen, clocks.realtime);
+        screen[0] = Display.STATE_ON;
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{521_000}, screen, clocks.realtime);
         blame1 += 0; // Screen had been off during the measurement period
         checkMeasuredCharge("D.1", uid1, blame1, uid2, blame2, globalDoze, bi);
         clocks.realtime += 101;
-        bi.updateDisplayMeasuredEnergyStatsLocked(530_000, screen, clocks.realtime);
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{530_000}, screen, clocks.realtime);
         blame1 += 530_000;
         checkMeasuredCharge("D.2", uid1, blame1, uid2, blame2, globalDoze, bi);
 
@@ -1044,33 +1044,33 @@
         clocks.realtime += 20;
         setFgState(uid2, true, bi);
         clocks.realtime += 40;
-        bi.updateDisplayMeasuredEnergyStatsLocked(540_000, screen, clocks.realtime);
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{540_000}, screen, clocks.realtime);
         // In the past 60ms, sum of fg is 20+40+40=100ms. uid1 is blamed for 60/100; uid2 for 40/100
         blame1 += 540_000 * (20 + 40) / (20 + 40 + 40);
-        blame2 += 540_000 * ( 0 + 40) / (20 + 40 + 40);
+        blame2 += 540_000 * (0 + 40) / (20 + 40 + 40);
         checkMeasuredCharge("E", uid1, blame1, uid2, blame2, globalDoze, bi);
 
         // Case F: uid1 on,  uid2 OFF, battery on,  screen on
         clocks.realtime += 40;
         setFgState(uid2, false, bi);
         clocks.realtime += 120;
-        bi.updateDisplayMeasuredEnergyStatsLocked(550_000, screen, clocks.realtime);
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{550_000}, screen, clocks.realtime);
         // In the past 160ms, sum f fg is 200ms. uid1 is blamed for 40+120 of it; uid2 for 40 of it.
         blame1 += 550_000 * (40 + 120) / (40 + 40 + 120);
-        blame2 += 550_000 * (40 + 0  ) / (40 + 40 + 120);
+        blame2 += 550_000 * (40 + 0) / (40 + 40 + 120);
         checkMeasuredCharge("F", uid1, blame1, uid2, blame2, globalDoze, bi);
 
         // Case G: uid1 on,  uid2 off,  battery on, screen DOZE
         clocks.realtime += 5;
-        screen = Display.STATE_DOZE;
-        bi.updateDisplayMeasuredEnergyStatsLocked(570_000, screen, clocks.realtime);
+        screen[0] = Display.STATE_DOZE;
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{570_000}, screen, clocks.realtime);
         blame1 += 570_000; // All of this pre-doze time is blamed on uid1.
         checkMeasuredCharge("G", uid1, blame1, uid2, blame2, globalDoze, bi);
 
         // Case H: uid1 on,  uid2 off,  battery on, screen ON
         clocks.realtime += 6;
-        screen = Display.STATE_ON;
-        bi.updateDisplayMeasuredEnergyStatsLocked(580_000, screen, clocks.realtime);
+        screen[0] = Display.STATE_ON;
+        bi.updateDisplayMeasuredEnergyStatsLocked(new long[]{580_000}, screen, clocks.realtime);
         blame1 += 0; // The screen had been doze during the energy period
         globalDoze += 580_000;
         checkMeasuredCharge("H", uid1, blame1, uid2, blame2, globalDoze, bi);
diff --git a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
index ab38f01..ac87806 100644
--- a/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
+++ b/core/tests/coretests/src/com/android/internal/os/BatteryUsageStatsRule.java
@@ -118,6 +118,12 @@
         return this;
     }
 
+    public BatteryUsageStatsRule setNumDisplays(int value) {
+        when(mPowerProfile.getNumDisplays()).thenReturn(value);
+        mBatteryStats.setDisplayCountLocked(value);
+        return this;
+    }
+
     /** Call only after setting the power profile information. */
     public BatteryUsageStatsRule initMeasuredEnergyStatsLocked() {
         return initMeasuredEnergyStatsLocked(new String[0]);
diff --git a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
index 73f4eb2..eee5d57 100644
--- a/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
+++ b/core/tests/coretests/src/com/android/internal/os/ScreenPowerCalculatorTest.java
@@ -42,11 +42,13 @@
     private static final int APP_UID2 = Process.FIRST_APPLICATION_UID + 43;
     private static final long MINUTE_IN_MS = 60 * 1000;
     private static final long MINUTE_IN_US = 60 * 1000 * 1000;
+    private static final long HOUR_IN_MS = 60 * MINUTE_IN_MS;
 
     @Rule
     public final BatteryUsageStatsRule mStatsRule = new BatteryUsageStatsRule()
             .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 0, 36.0)
-            .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 0, 48.0);
+            .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 0, 48.0)
+            .setNumDisplays(1);
 
     @Test
     public void testMeasuredEnergyBasedModel() {
@@ -54,12 +56,13 @@
         BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
 
         batteryStats.noteScreenStateLocked(0, Display.STATE_ON, 0, 0, 0);
-        batteryStats.updateDisplayMeasuredEnergyStatsLocked(0, Display.STATE_ON, 0);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{0},
+                new int[]{Display.STATE_ON}, 0);
         setProcState(APP_UID1, ActivityManager.PROCESS_STATE_TOP, true,
                 0, 0);
 
-        batteryStats.updateDisplayMeasuredEnergyStatsLocked(200_000_000, Display.STATE_ON,
-                15 * MINUTE_IN_MS);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{200_000_000},
+                new int[]{Display.STATE_ON}, 15 * MINUTE_IN_MS);
 
         setProcState(APP_UID1, ActivityManager.PROCESS_STATE_CACHED_EMPTY, false,
                 20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
@@ -67,16 +70,16 @@
         setProcState(APP_UID2, ActivityManager.PROCESS_STATE_TOP, true,
                 20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
 
-        batteryStats.updateDisplayMeasuredEnergyStatsLocked(300_000_000, Display.STATE_ON,
-                60 * MINUTE_IN_MS);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{300_000_000},
+                new int[]{Display.STATE_ON}, 60 * MINUTE_IN_MS);
 
         batteryStats.noteScreenStateLocked(0, Display.STATE_OFF,
                 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
         setProcState(APP_UID2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, false,
                 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
 
-        batteryStats.updateDisplayMeasuredEnergyStatsLocked(100_000_000, Display.STATE_DOZE,
-                120 * MINUTE_IN_MS);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{100_000_000},
+                new int[]{Display.STATE_DOZE}, 120 * MINUTE_IN_MS);
 
         mStatsRule.setTime(120 * MINUTE_IN_US, 120 * MINUTE_IN_US);
 
@@ -129,6 +132,104 @@
                 .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
     }
 
+
+    @Test
+    public void testMeasuredEnergyBasedModel_multiDisplay() {
+        mStatsRule.initMeasuredEnergyStatsLocked()
+                .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 1, 60.0)
+                .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 1, 100.0)
+                .setNumDisplays(2);
+
+        BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+        final int[] screenStates = new int[]{Display.STATE_ON, Display.STATE_OFF};
+
+        batteryStats.noteScreenStateLocked(0, screenStates[0], 0, 0, 0);
+        batteryStats.noteScreenStateLocked(1, screenStates[1], 0, 0, 0);
+        batteryStats.noteScreenBrightnessLocked(0, 255, 0, 0);
+        setProcState(APP_UID1, ActivityManager.PROCESS_STATE_TOP, true, 0, 0);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{300, 400}, screenStates, 0);
+
+        batteryStats.noteScreenBrightnessLocked(0, 100, 5 * MINUTE_IN_MS, 5 * MINUTE_IN_MS);
+        batteryStats.noteScreenBrightnessLocked(0, 200, 10 * MINUTE_IN_MS, 10 * MINUTE_IN_MS);
+
+        setProcState(APP_UID1, ActivityManager.PROCESS_STATE_CACHED_EMPTY, false,
+                20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
+        setProcState(APP_UID2, ActivityManager.PROCESS_STATE_TOP, true,
+                20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
+
+        screenStates[0] = Display.STATE_OFF;
+        screenStates[1] = Display.STATE_ON;
+        batteryStats.noteScreenStateLocked(0, screenStates[0],
+                80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+        batteryStats.noteScreenStateLocked(1, screenStates[1], 80 * MINUTE_IN_MS,
+                80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{600_000_000, 500},
+                screenStates, 80 * MINUTE_IN_MS);
+
+        batteryStats.noteScreenBrightnessLocked(1, 25, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+        batteryStats.noteScreenBrightnessLocked(1, 250, 86 * MINUTE_IN_MS, 86 * MINUTE_IN_MS);
+        batteryStats.noteScreenBrightnessLocked(1, 75, 98 * MINUTE_IN_MS, 98 * MINUTE_IN_MS);
+
+        screenStates[1] = Display.STATE_OFF;
+        batteryStats.noteScreenStateLocked(1, screenStates[1], 110 * MINUTE_IN_MS,
+                110 * MINUTE_IN_MS, 110 * MINUTE_IN_MS);
+        batteryStats.updateDisplayMeasuredEnergyStatsLocked(new long[]{700, 800_000_000},
+                screenStates, 110 * MINUTE_IN_MS);
+
+        setProcState(APP_UID2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, false,
+                110 * MINUTE_IN_MS, 110 * MINUTE_IN_MS);
+
+        mStatsRule.setTime(120 * MINUTE_IN_US, 120 * MINUTE_IN_US);
+
+        ScreenPowerCalculator calculator =
+                new ScreenPowerCalculator(mStatsRule.getPowerProfile());
+
+        mStatsRule.apply(calculator);
+
+        BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
+        assertThat(deviceConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(110 * MINUTE_IN_MS);
+        // (600000000 + 800000000) uAs * (1 mA / 1000 uA) * (1 h / 3600 s)  = 166.66666 mAh
+        assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(388.88888);
+        assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+
+        UidBatteryConsumer uid1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
+        assertThat(uid1.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(20 * MINUTE_IN_MS);
+
+        // Uid1 ran for 20 out of 80 min during the first Display update.
+        // It also ran for 5 out of 45 min during the second Display update:
+        // Uid1 charge = 20 / 80 * 600000000 mAs = 41.66666 mAh
+        assertThat(uid1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(41.66666);
+        assertThat(uid1.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+
+        UidBatteryConsumer uid2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
+        assertThat(uid2.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(90 * MINUTE_IN_MS);
+
+        // Uid2 ran for 60 out of 80 min during the first Display update.
+        // It also ran for all of the second Display update:
+        // Uid1 charge = 60 / 80 * 600000000 + 800000000 mAs = 347.22222 mAh
+        assertThat(uid2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(347.22222);
+        assertThat(uid2.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+
+        BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
+        assertThat(appsConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(110 * MINUTE_IN_MS);
+        assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(388.88888);
+        assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_MEASURED_ENERGY);
+
+    }
+
     @Test
     public void testPowerProfileBasedModel() {
         BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
@@ -197,6 +298,95 @@
                 .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
     }
 
+
+    @Test
+    public void testPowerProfileBasedModel_multiDisplay() {
+        mStatsRule.setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_ON, 1, 60.0)
+                .setAveragePowerForOrdinal(POWER_GROUP_DISPLAY_SCREEN_FULL, 1, 100.0)
+                .setNumDisplays(2);
+
+        BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
+
+        batteryStats.noteScreenStateLocked(0, Display.STATE_ON, 0, 0, 0);
+        batteryStats.noteScreenStateLocked(1, Display.STATE_OFF, 0, 0, 0);
+        batteryStats.noteScreenBrightnessLocked(0, 255, 0, 0);
+        setProcState(APP_UID1, ActivityManager.PROCESS_STATE_TOP, true,
+                0, 0);
+
+        batteryStats.noteScreenBrightnessLocked(0, 100, 5 * MINUTE_IN_MS, 5 * MINUTE_IN_MS);
+        batteryStats.noteScreenBrightnessLocked(0, 200, 10 * MINUTE_IN_MS, 10 * MINUTE_IN_MS);
+
+        setProcState(APP_UID1, ActivityManager.PROCESS_STATE_CACHED_EMPTY, false,
+                20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
+        setProcState(APP_UID2, ActivityManager.PROCESS_STATE_TOP, true,
+                20 * MINUTE_IN_MS, 20 * MINUTE_IN_MS);
+
+        batteryStats.noteScreenStateLocked(0, Display.STATE_OFF,
+                80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+        batteryStats.noteScreenStateLocked(1, Display.STATE_ON, 80 * MINUTE_IN_MS,
+                80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+        batteryStats.noteScreenBrightnessLocked(1, 20, 80 * MINUTE_IN_MS, 80 * MINUTE_IN_MS);
+
+        batteryStats.noteScreenBrightnessLocked(1, 250, 86 * MINUTE_IN_MS, 86 * MINUTE_IN_MS);
+        batteryStats.noteScreenBrightnessLocked(1, 75, 98 * MINUTE_IN_MS, 98 * MINUTE_IN_MS);
+        batteryStats.noteScreenStateLocked(1, Display.STATE_OFF, 110 * MINUTE_IN_MS,
+                110 * MINUTE_IN_MS, 110 * MINUTE_IN_MS);
+
+        setProcState(APP_UID2, ActivityManager.PROCESS_STATE_TOP_SLEEPING, false,
+                110 * MINUTE_IN_MS, 110 * MINUTE_IN_MS);
+
+        mStatsRule.setTime(120 * MINUTE_IN_US, 120 * MINUTE_IN_US);
+        ScreenPowerCalculator calculator =
+                new ScreenPowerCalculator(mStatsRule.getPowerProfile());
+
+        mStatsRule.apply(BatteryUsageStatsRule.POWER_PROFILE_MODEL_ONLY, calculator);
+
+        BatteryConsumer deviceConsumer = mStatsRule.getDeviceBatteryConsumer();
+        assertThat(deviceConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(110 * MINUTE_IN_MS);
+        // First display consumed 92 mAh.
+        // Second display ran for 0.5 hours at a base drain rate of 60 mA.
+        // 6 minutes (0.1 hours) spent in the first brightness level which drains an extra 10 mA.
+        // 12 minutes (0.2 hours) spent in the fifth brightness level which drains an extra 90 mA.
+        // 12 minutes (0.2 hours) spent in the second brightness level which drains an extra 30 mA.
+        // 92 + 60 * 0.5 + 10 * 0.1 + 90 * 0.2 + 30 * 0.2 = 147
+        assertThat(deviceConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(147);
+        assertThat(deviceConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+        UidBatteryConsumer uid1 = mStatsRule.getUidBatteryConsumer(APP_UID1);
+        assertThat(uid1.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(20 * MINUTE_IN_MS);
+
+        // Uid1 took 20 out of the total of 110 min of foreground activity
+        // Uid1 charge = 20 / 110 * 147.0 = 23.0 mAh
+        assertThat(uid1.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(26.72727);
+        assertThat(uid1.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+        UidBatteryConsumer uid2 = mStatsRule.getUidBatteryConsumer(APP_UID2);
+        assertThat(uid2.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(90 * MINUTE_IN_MS);
+
+        // Uid2 took 90 out of the total of 110 min of foreground activity
+        // Uid2 charge = 90 / 110 * 92.0 = 69.0 mAh
+        assertThat(uid2.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(120.272727);
+        assertThat(uid2.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+        BatteryConsumer appsConsumer = mStatsRule.getAppsBatteryConsumer();
+        assertThat(appsConsumer.getUsageDurationMillis(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(110 * MINUTE_IN_MS);
+        assertThat(appsConsumer.getConsumedPower(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isWithin(PRECISION).of(147);
+        assertThat(appsConsumer.getPowerModel(BatteryConsumer.POWER_COMPONENT_SCREEN))
+                .isEqualTo(BatteryConsumer.POWER_MODEL_POWER_PROFILE);
+
+    }
+
     private void setProcState(int uid, int procState, boolean resumed, long realtimeMs,
             long uptimeMs) {
         BatteryStatsImpl batteryStats = mStatsRule.getBatteryStats();
diff --git a/data/etc/services.core.protolog.json b/data/etc/services.core.protolog.json
index 9573607..8b37805 100644
--- a/data/etc/services.core.protolog.json
+++ b/data/etc/services.core.protolog.json
@@ -1141,6 +1141,12 @@
       "group": "WM_DEBUG_BOOT",
       "at": "com\/android\/server\/wm\/WindowManagerService.java"
     },
+    "-863438038": {
+      "message": "Aborting Transition: %d",
+      "level": "VERBOSE",
+      "group": "WM_DEBUG_WINDOW_TRANSITIONS",
+      "at": "com\/android\/server\/wm\/Transition.java"
+    },
     "-861859917": {
       "message": "Attempted to add window to a display that does not exist: %d. Aborting.",
       "level": "WARN",
@@ -1555,6 +1561,12 @@
       "group": "WM_DEBUG_ORIENTATION",
       "at": "com\/android\/server\/wm\/DisplayRotation.java"
     },
+    "-436553282": {
+      "message": "Remove sleep token: tag=%s, displayId=%d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_STATES",
+      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+    },
     "-415865166": {
       "message": "findFocusedWindow: Found new focus @ %s",
       "level": "VERBOSE",
@@ -1663,6 +1675,12 @@
       "group": "WM_DEBUG_ADD_REMOVE",
       "at": "com\/android\/server\/wm\/WindowState.java"
     },
+    "-317761482": {
+      "message": "Create sleep token: tag=%s, displayId=%d",
+      "level": "DEBUG",
+      "group": "WM_DEBUG_STATES",
+      "at": "com\/android\/server\/wm\/RootWindowContainer.java"
+    },
     "-317194205": {
       "message": "clearLockedTasks: %s",
       "level": "INFO",
diff --git a/libs/WindowManager/Shell/res/layout/split_decor.xml b/libs/WindowManager/Shell/res/layout/split_decor.xml
new file mode 100644
index 0000000..9ffa5e8
--- /dev/null
+++ b/libs/WindowManager/Shell/res/layout/split_decor.xml
@@ -0,0 +1,30 @@
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
+
+<FrameLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_height="match_parent"
+    android:layout_width="match_parent">
+
+    <ImageView android:id="@+id/split_resizing_icon"
+               android:layout_height="wrap_content"
+               android:layout_width="wrap_content"
+               android:layout_gravity="center"
+               android:padding="0dp"
+               android:visibility="gone"
+               android:background="@null"/>
+
+</FrameLayout>
diff --git a/libs/WindowManager/Shell/res/layout/split_outline.xml b/libs/WindowManager/Shell/res/layout/split_outline.xml
index 13a30f5..6cb9ebb 100644
--- a/libs/WindowManager/Shell/res/layout/split_outline.xml
+++ b/libs/WindowManager/Shell/res/layout/split_outline.xml
@@ -1,18 +1,19 @@
 <?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
+<!--
+  ~ Copyright (C) 2021 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.
+  -->
 <FrameLayout
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
diff --git a/libs/WindowManager/Shell/res/values-land/styles.xml b/libs/WindowManager/Shell/res/values-land/styles.xml
index 9eddac4..0ed9368 100644
--- a/libs/WindowManager/Shell/res/values-land/styles.xml
+++ b/libs/WindowManager/Shell/res/values-land/styles.xml
@@ -23,7 +23,7 @@
     </style>
 
     <style name="DockedDividerHandle">
-        <item name="android:layout_gravity">center_vertical</item>
+        <item name="android:layout_gravity">center</item>
         <item name="android:layout_width">48dp</item>
         <item name="android:layout_height">96dp</item>
     </style>
diff --git a/libs/WindowManager/Shell/res/values/styles.xml b/libs/WindowManager/Shell/res/values/styles.xml
index cb6d4de..7733201 100644
--- a/libs/WindowManager/Shell/res/values/styles.xml
+++ b/libs/WindowManager/Shell/res/values/styles.xml
@@ -43,7 +43,7 @@
     </style>
 
     <style name="DockedDividerHandle">
-        <item name="android:layout_gravity">center_horizontal</item>
+        <item name="android:layout_gravity">center</item>
         <item name="android:layout_width">96dp</item>
         <item name="android:layout_height">48dp</item>
     </style>
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
index 9113c79..e87b150 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/ShellCommandHandlerImpl.java
@@ -103,8 +103,6 @@
                 return runMoveToSideStage(args, pw);
             case "removeFromSideStage":
                 return runRemoveFromSideStage(args, pw);
-            case "setSideStageOutline":
-                return runSetSideStageOutline(args, pw);
             case "setSideStagePosition":
                 return runSetSideStagePosition(args, pw);
             case "setSideStageVisibility":
@@ -163,18 +161,6 @@
         return true;
     }
 
-    private boolean runSetSideStageOutline(String[] args, PrintWriter pw) {
-        if (args.length < 3) {
-            // First arguments are "WMShell" and command name.
-            pw.println("Error: whether to enable or disable side stage outline border should be"
-                    + " provided as arguments");
-            return false;
-        }
-        final boolean enable = new Boolean(args[2]);
-        mSplitScreenOptional.ifPresent(split -> split.setSideStageOutline(enable));
-        return true;
-    }
-
     private boolean runSetSideStagePosition(String[] args, PrintWriter pw) {
         if (args.length < 3) {
             // First arguments are "WMShell" and command name.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
index 6a252e0..c8449a3 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/apppairs/AppPair.java
@@ -131,7 +131,8 @@
         mSplitLayout = new SplitLayout(TAG + "SplitDivider",
                 mDisplayController.getDisplayContext(mRootTaskInfo.displayId),
                 mRootTaskInfo.configuration, this /* layoutChangeListener */,
-                mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer());
+                mParentContainerCallbacks, mDisplayImeController, mController.getTaskOrganizer(),
+                true /* applyDismissingParallax */);
         mDisplayInsetsController.addInsetsChangedListener(mRootTaskInfo.displayId, mSplitLayout);
 
         final WindowContainerToken token1 = task1.token;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
index 962aca1..7784665 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayLayout.java
@@ -48,9 +48,11 @@
 import android.view.InsetsSource;
 import android.view.InsetsState;
 import android.view.Surface;
-import android.view.WindowInsets;
+
+import androidx.annotation.VisibleForTesting;
 
 import com.android.internal.R;
+import com.android.internal.policy.SystemBarUtils;
 
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
@@ -198,12 +200,13 @@
         recalcInsets(res);
     }
 
-    private void recalcInsets(Resources res) {
+    @VisibleForTesting
+    void recalcInsets(Resources res) {
         computeNonDecorInsets(res, mRotation, mWidth, mHeight, mCutout, mInsetsState, mUiMode,
                 mNonDecorInsets, mHasNavigationBar);
         mStableInsets.set(mNonDecorInsets);
         if (mHasStatusBar) {
-            convertNonDecorInsetsToStableInsets(res, mStableInsets, mWidth, mHeight, mHasStatusBar);
+            convertNonDecorInsetsToStableInsets(res, mStableInsets, mCutout, mHasStatusBar);
         }
         mNavBarFrameHeight = getNavigationBarFrameHeight(res, mWidth > mHeight);
     }
@@ -323,12 +326,12 @@
     /**
      * Calculates the stable insets if we already have the non-decor insets.
      */
-    private static void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
-            int displayWidth, int displayHeight, boolean hasStatusBar) {
+    private void convertNonDecorInsetsToStableInsets(Resources res, Rect inOutInsets,
+            DisplayCutout cutout, boolean hasStatusBar) {
         if (!hasStatusBar) {
             return;
         }
-        int statusBarHeight = getStatusBarHeight(displayWidth > displayHeight, res);
+        int statusBarHeight = SystemBarUtils.getStatusBarHeight(res, cutout);
         inOutInsets.top = Math.max(inOutInsets.top, statusBarHeight);
     }
 
@@ -377,35 +380,6 @@
         }
     }
 
-    /**
-     * Calculates the stable insets without running a layout.
-     *
-     * @param displayRotation the current display rotation
-     * @param displayWidth the current display width
-     * @param displayHeight the current display height
-     * @param displayCutout the current display cutout
-     * @param outInsets the insets to return
-     */
-    static void computeStableInsets(Resources res, int displayRotation, int displayWidth,
-            int displayHeight, DisplayCutout displayCutout, InsetsState insetsState, int uiMode,
-            Rect outInsets, boolean hasNavigationBar, boolean hasStatusBar) {
-        outInsets.setEmpty();
-
-        // Navigation bar and status bar.
-        computeNonDecorInsets(res, displayRotation, displayWidth, displayHeight, displayCutout,
-                insetsState, uiMode, outInsets, hasNavigationBar);
-        convertNonDecorInsetsToStableInsets(res, outInsets, displayWidth, displayHeight,
-                hasStatusBar);
-    }
-
-    /** Retrieve the statusbar height from resources. */
-    static int getStatusBarHeight(boolean landscape, Resources res) {
-        return landscape ? res.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height_landscape)
-                : res.getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height_portrait);
-    }
-
     /** Calculate the DisplayCutout for a particular display size/rotation. */
     public static DisplayCutout calculateDisplayCutoutForRotation(
             DisplayCutout cutout, int rotation, int displayWidth, int displayHeight) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
index 55c5125..4b138e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/SurfaceUtils.java
@@ -23,16 +23,22 @@
  * Helpers for handling surface.
  */
 public class SurfaceUtils {
-    /** Creates a dim layer above indicated host surface. */
+    /** Creates a dim layer above host surface. */
     public static SurfaceControl makeDimLayer(SurfaceControl.Transaction t, SurfaceControl host,
             String name, SurfaceSession surfaceSession) {
-        SurfaceControl dimLayer = new SurfaceControl.Builder(surfaceSession)
+        final SurfaceControl dimLayer = makeColorLayer(host, name, surfaceSession);
+        t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
+        return dimLayer;
+    }
+
+    /** Creates a color layer for host surface. */
+    public static SurfaceControl makeColorLayer(SurfaceControl host, String name,
+            SurfaceSession surfaceSession) {
+        return new SurfaceControl.Builder(surfaceSession)
                 .setParent(host)
                 .setColorLayer()
                 .setName(name)
-                .setCallsite("SurfaceUtils.makeDimLayer")
+                .setCallsite("SurfaceUtils.makeColorLayer")
                 .build();
-        t.setLayer(dimLayer, Integer.MAX_VALUE).setColor(dimLayer, new float[]{0f, 0f, 0f});
-        return dimLayer;
     }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
index 6ea806b..4b125b1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/DividerView.java
@@ -19,6 +19,8 @@
 import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
 import static android.view.WindowManager.LayoutParams.FLAG_SLIPPERY;
 
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
 import android.animation.ObjectAnimator;
 import android.content.Context;
 import android.graphics.Rect;
@@ -57,6 +59,7 @@
     private final int mTouchSlop = ViewConfiguration.get(getContext()).getScaledTouchSlop();
 
     private SplitLayout mSplitLayout;
+    private SplitWindowManager mSplitWindowManager;
     private SurfaceControlViewHost mViewHost;
     private DividerHandleView mHandle;
     private View mBackground;
@@ -67,6 +70,7 @@
     private int mStartPos;
     private GestureDetector mDoubleTapDetector;
     private boolean mInteractive;
+    private boolean mSetTouchRegion = true;
 
     /**
      * Tracks divider bar visible bounds in screen-based coordination. Used to calculate with
@@ -93,6 +97,18 @@
                 }
             };
 
+    private AnimatorListenerAdapter mAnimatorListener = new AnimatorListenerAdapter() {
+        @Override
+        public void onAnimationEnd(Animator animation) {
+            mSetTouchRegion = true;
+        }
+
+        @Override
+        public void onAnimationCancel(Animator animation) {
+            mSetTouchRegion = true;
+        }
+    };
+
     public DividerView(@NonNull Context context) {
         super(context);
     }
@@ -114,9 +130,11 @@
     /** Sets up essential dependencies of the divider bar. */
     public void setup(
             SplitLayout layout,
+            SplitWindowManager splitWindowManager,
             SurfaceControlViewHost viewHost,
             InsetsState insetsState) {
         mSplitLayout = layout;
+        mSplitWindowManager = splitWindowManager;
         mViewHost = viewHost;
         mDividerBounds.set(layout.getDividerBounds());
         onInsetsChanged(insetsState, false /* animate */);
@@ -138,9 +156,11 @@
                         DIVIDER_HEIGHT_PROPERTY, mDividerBounds.height(), mTempRect.height());
                 animator.setInterpolator(InsetsController.RESIZE_INTERPOLATOR);
                 animator.setDuration(InsetsController.ANIMATION_DURATION_RESIZE);
+                animator.addListener(mAnimatorListener);
                 animator.start();
             } else {
                 DIVIDER_HEIGHT_PROPERTY.set(this, mTempRect.height());
+                mSetTouchRegion = true;
             }
             mDividerBounds.set(mTempRect);
         }
@@ -162,6 +182,17 @@
     }
 
     @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        if (mSetTouchRegion) {
+            mTempRect.set(mHandle.getLeft(), mHandle.getTop(), mHandle.getRight(),
+                    mHandle.getBottom());
+            mSplitWindowManager.setTouchRegion(mTempRect);
+            mSetTouchRegion = false;
+        }
+    }
+
+    @Override
     public boolean onTouch(View v, MotionEvent event) {
         if (mSplitLayout == null || !mInteractive) {
             return false;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
new file mode 100644
index 0000000..ad9ebb2
--- /dev/null
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitDecorManager.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2021 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.wm.shell.common.split;
+
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
+import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManagerPolicyConstants.SPLIT_DIVIDER_LAYER;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.content.res.Configuration;
+import android.graphics.Color;
+import android.graphics.PixelFormat;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Binder;
+import android.view.IWindow;
+import android.view.LayoutInflater;
+import android.view.SurfaceControl;
+import android.view.SurfaceControlViewHost;
+import android.view.SurfaceSession;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.WindowlessWindowManager;
+import android.widget.FrameLayout;
+import android.widget.ImageView;
+
+import com.android.launcher3.icons.IconProvider;
+import com.android.wm.shell.R;
+import com.android.wm.shell.common.SurfaceUtils;
+
+/**
+ * Handles split decor like showing resizing hint for a specific split.
+ */
+public class SplitDecorManager extends WindowlessWindowManager {
+    private static final String TAG = SplitDecorManager.class.getSimpleName();
+    private static final String RESIZING_BACKGROUND_SURFACE_NAME = "ResizingBackground";
+
+    private final IconProvider mIconProvider;
+    private final SurfaceSession mSurfaceSession;
+
+    private Drawable mIcon;
+    private ImageView mResizingIconView;
+    private SurfaceControlViewHost mViewHost;
+    private SurfaceControl mHostLeash;
+    private SurfaceControl mIconLeash;
+    private SurfaceControl mBackgroundLeash;
+
+    public SplitDecorManager(Configuration configuration, IconProvider iconProvider,
+            SurfaceSession surfaceSession) {
+        super(configuration, null /* rootSurface */, null /* hostInputToken */);
+        mIconProvider = iconProvider;
+        mSurfaceSession = surfaceSession;
+    }
+
+    @Override
+    protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
+        // Can't set position for the ViewRootImpl SC directly. Create a leash to manipulate later.
+        final SurfaceControl.Builder builder = new SurfaceControl.Builder(new SurfaceSession())
+                .setContainerLayer()
+                .setName(TAG)
+                .setHidden(true)
+                .setParent(mHostLeash)
+                .setCallsite("SplitDecorManager#attachToParentSurface");
+        mIconLeash = builder.build();
+        b.setParent(mIconLeash);
+    }
+
+    /** Inflates split decor surface on the root surface. */
+    public void inflate(Context context, SurfaceControl rootLeash, Rect rootBounds) {
+        if (mIconLeash != null && mViewHost != null) {
+            return;
+        }
+
+        context = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY,
+                null /* options */);
+        mHostLeash = rootLeash;
+        mViewHost = new SurfaceControlViewHost(context, context.getDisplay(), this);
+
+        final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(context)
+                .inflate(R.layout.split_decor, null);
+        mResizingIconView = rootLayout.findViewById(R.id.split_resizing_icon);
+
+        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY,
+                FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
+        lp.width = rootBounds.width();
+        lp.height = rootBounds.height();
+        lp.token = new Binder();
+        lp.setTitle(TAG);
+        lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
+        // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports
+        //  TRUSTED_OVERLAY for windowless window without input channel.
+        mViewHost.setView(rootLayout, lp);
+    }
+
+    /** Releases the surfaces for split decor. */
+    public void release(SurfaceControl.Transaction t) {
+        if (mViewHost != null) {
+            mViewHost.release();
+            mViewHost = null;
+        }
+        if (mIconLeash != null) {
+            t.remove(mIconLeash);
+            mIconLeash = null;
+        }
+        if (mBackgroundLeash != null) {
+            t.remove(mBackgroundLeash);
+            mBackgroundLeash = null;
+        }
+        mHostLeash = null;
+        mIcon = null;
+        mResizingIconView = null;
+    }
+
+    /** Showing resizing hint. */
+    public void onResizing(ActivityManager.RunningTaskInfo resizingTask, Rect newBounds,
+            SurfaceControl.Transaction t) {
+        if (mResizingIconView == null) {
+            return;
+        }
+
+        if (mIcon == null) {
+            // TODO: add fade-in animation.
+            mBackgroundLeash = SurfaceUtils.makeColorLayer(mHostLeash,
+                    RESIZING_BACKGROUND_SURFACE_NAME, mSurfaceSession);
+            t.setColor(mBackgroundLeash, getResizingBackgroundColor(resizingTask))
+                    .setLayer(mBackgroundLeash, SPLIT_DIVIDER_LAYER - 1)
+                    .show(mBackgroundLeash);
+
+            mIcon = mIconProvider.getIcon(resizingTask.topActivityInfo);
+            mResizingIconView.setImageDrawable(mIcon);
+            mResizingIconView.setVisibility(View.VISIBLE);
+
+            WindowManager.LayoutParams lp =
+                    (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
+            lp.width = mIcon.getIntrinsicWidth();
+            lp.height = mIcon.getIntrinsicHeight();
+            mViewHost.relayout(lp);
+            t.show(mIconLeash).setLayer(mIconLeash, SPLIT_DIVIDER_LAYER);
+        }
+
+        t.setPosition(mIconLeash,
+                newBounds.width() / 2 - mIcon.getIntrinsicWidth() / 2,
+                newBounds.height() / 2 - mIcon.getIntrinsicWidth() / 2);
+    }
+
+    /** Stops showing resizing hint. */
+    public void onResized(Rect newBounds, SurfaceControl.Transaction t) {
+        if (mResizingIconView == null) {
+            return;
+        }
+
+        if (mIcon != null) {
+            mResizingIconView.setVisibility(View.GONE);
+            mResizingIconView.setImageDrawable(null);
+            t.remove(mBackgroundLeash).hide(mIconLeash);
+            mIcon = null;
+            mBackgroundLeash = null;
+        }
+    }
+
+    private static float[] getResizingBackgroundColor(ActivityManager.RunningTaskInfo taskInfo) {
+        final int taskBgColor = taskInfo.taskDescription.getBackgroundColor();
+        return Color.valueOf(taskBgColor == -1 ? Color.WHITE : taskBgColor).getComponents();
+    }
+}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
index 5b3ce2d..625bcee 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitLayout.java
@@ -40,8 +40,10 @@
 import android.content.res.Resources;
 import android.graphics.Point;
 import android.graphics.Rect;
+import android.view.Display;
 import android.view.InsetsSourceControl;
 import android.view.InsetsState;
+import android.view.RoundedCorner;
 import android.view.SurfaceControl;
 import android.view.WindowInsets;
 import android.view.WindowManager;
@@ -53,6 +55,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.DividerSnapAlgorithm;
 import com.android.internal.policy.DockedDividerUtils;
+import com.android.wm.shell.R;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.animation.Interpolators;
 import com.android.wm.shell.common.DisplayImeController;
@@ -103,7 +106,7 @@
     private final SplitWindowManager mSplitWindowManager;
     private final DisplayImeController mDisplayImeController;
     private final ImePositionProcessor mImePositionProcessor;
-    private final DismissingParallaxPolicy mDismissingParallaxPolicy;
+    private final DismissingEffectPolicy mDismissingEffectPolicy;
     private final ShellTaskOrganizer mTaskOrganizer;
     private final InsetsState mInsetsState = new InsetsState();
 
@@ -119,7 +122,8 @@
     public SplitLayout(String windowName, Context context, Configuration configuration,
             SplitLayoutHandler splitLayoutHandler,
             SplitWindowManager.ParentContainerCallbacks parentContainerCallbacks,
-            DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer) {
+            DisplayImeController displayImeController, ShellTaskOrganizer taskOrganizer,
+            boolean applyDismissingParallax) {
         mContext = context.createConfigurationContext(configuration);
         mOrientation = configuration.orientation;
         mRotation = configuration.windowConfiguration.getRotation();
@@ -129,20 +133,35 @@
                 parentContainerCallbacks);
         mTaskOrganizer = taskOrganizer;
         mImePositionProcessor = new ImePositionProcessor(mContext.getDisplayId());
-        mDismissingParallaxPolicy = new DismissingParallaxPolicy();
+        mDismissingEffectPolicy = new DismissingEffectPolicy(applyDismissingParallax);
 
         final Resources resources = context.getResources();
-        mDividerWindowWidth = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.docked_stack_divider_thickness);
-        mDividerInsets = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.docked_stack_divider_insets);
-        mDividerSize = mDividerWindowWidth - mDividerInsets * 2;
+        mDividerSize = resources.getDimensionPixelSize(R.dimen.split_divider_bar_width);
+        mDividerInsets = getDividerInsets(resources, context.getDisplay());
+        mDividerWindowWidth = mDividerSize + 2 * mDividerInsets;
 
         mRootBounds.set(configuration.windowConfiguration.getBounds());
         mDividerSnapAlgorithm = getSnapAlgorithm(mContext, mRootBounds);
         resetDividerPosition();
     }
 
+    private int getDividerInsets(Resources resources, Display display) {
+        final int dividerInset = resources.getDimensionPixelSize(
+                com.android.internal.R.dimen.docked_stack_divider_insets);
+
+        int radius = 0;
+        RoundedCorner corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_LEFT);
+        radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+        corner = display.getRoundedCorner(RoundedCorner.POSITION_TOP_RIGHT);
+        radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+        corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_RIGHT);
+        radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+        corner = display.getRoundedCorner(RoundedCorner.POSITION_BOTTOM_LEFT);
+        radius = corner != null ? Math.max(radius, corner.getRadius()) : radius;
+
+        return Math.max(dividerInset, radius);
+    }
+
     /** Gets bounds of the primary split. */
     public Rect getBounds1() {
         return new Rect(mBounds1);
@@ -247,7 +266,7 @@
         }
         DockedDividerUtils.sanitizeStackBounds(mBounds1, true /** topLeft */);
         DockedDividerUtils.sanitizeStackBounds(mBounds2, false /** topLeft */);
-        mDismissingParallaxPolicy.applyDividerPosition(position, isLandscape);
+        mDismissingEffectPolicy.applyDividerPosition(position, isLandscape);
     }
 
     /** Inflates {@link DividerView} on the root surface. */
@@ -290,7 +309,6 @@
      */
     void updateDivideBounds(int position) {
         updateBounds(position);
-        mSplitWindowManager.setResizingSplits(true);
         mSplitLayoutHandler.onLayoutSizeChanging(this);
     }
 
@@ -298,13 +316,11 @@
         mDividePosition = position;
         updateBounds(mDividePosition);
         mSplitLayoutHandler.onLayoutSizeChanged(this);
-        mSplitWindowManager.setResizingSplits(false);
     }
 
     /** Resets divider position. */
     public void resetDividerPosition() {
         mDividePosition = mDividerSnapAlgorithm.getMiddleTarget().position;
-        mSplitWindowManager.setResizingSplits(false);
         updateBounds(mDividePosition);
         mWinToken1 = null;
         mWinToken2 = null;
@@ -360,8 +376,8 @@
     @VisibleForTesting
     void flingDividePosition(int from, int to, @Nullable Runnable flingFinishedCallback) {
         if (from == to) {
-            // No animation run, it should stop resizing here.
-            mSplitWindowManager.setResizingSplits(false);
+            // No animation run, still callback to stop resizing.
+            mSplitLayoutHandler.onLayoutSizeChanged(this);
             return;
         }
         ValueAnimator animator = ValueAnimator
@@ -425,7 +441,7 @@
             return;
         }
 
-        mDismissingParallaxPolicy.adjustDismissingSurface(t, leash1, leash2, dimLayer1, dimLayer2);
+        mDismissingEffectPolicy.adjustDismissingSurface(t, leash1, leash2, dimLayer1, dimLayer2);
     }
 
     /** Apply recorded task layout to the {@link WindowContainerTransaction}. */
@@ -543,7 +559,10 @@
      * Calculates and applies proper dismissing parallax offset and dimming value to hint users
      * dismissing gesture.
      */
-    private class DismissingParallaxPolicy {
+    private class DismissingEffectPolicy {
+        /** Indicates whether to offset splitting bounds to hint dismissing progress or not. */
+        private final boolean mApplyParallax;
+
         // The current dismissing side.
         int mDismissingSide = DOCKED_INVALID;
 
@@ -553,6 +572,10 @@
         // The dimming value to hint the dismissing side and progress.
         float mDismissingDimValue = 0.0f;
 
+        DismissingEffectPolicy(boolean applyDismissingParallax) {
+            mApplyParallax = applyDismissingParallax;
+        }
+
         /**
          * Applies a parallax to the task to hint dismissing progress.
          *
@@ -565,11 +588,11 @@
             mDismissingDimValue = 0;
 
             int totalDismissingDistance = 0;
-            if (position <= mDividerSnapAlgorithm.getFirstSplitTarget().position) {
+            if (position < mDividerSnapAlgorithm.getFirstSplitTarget().position) {
                 mDismissingSide = isLandscape ? DOCKED_LEFT : DOCKED_TOP;
                 totalDismissingDistance = mDividerSnapAlgorithm.getDismissStartTarget().position
                         - mDividerSnapAlgorithm.getFirstSplitTarget().position;
-            } else if (position >= mDividerSnapAlgorithm.getLastSplitTarget().position) {
+            } else if (position > mDividerSnapAlgorithm.getLastSplitTarget().position) {
                 mDismissingSide = isLandscape ? DOCKED_RIGHT : DOCKED_BOTTOM;
                 totalDismissingDistance = mDividerSnapAlgorithm.getLastSplitTarget().position
                         - mDividerSnapAlgorithm.getDismissEndTarget().position;
@@ -627,12 +650,14 @@
                     return false;
             }
 
-            t.setPosition(targetLeash,
-                    mTempRect.left + mDismissingParallaxOffset.x,
-                    mTempRect.top + mDismissingParallaxOffset.y);
-            // Transform the screen-based split bounds to surface-based crop bounds.
-            mTempRect.offsetTo(-mDismissingParallaxOffset.x, -mDismissingParallaxOffset.y);
-            t.setWindowCrop(targetLeash, mTempRect);
+            if (mApplyParallax) {
+                t.setPosition(targetLeash,
+                        mTempRect.left + mDismissingParallaxOffset.x,
+                        mTempRect.top + mDismissingParallaxOffset.y);
+                // Transform the screen-based split bounds to surface-based crop bounds.
+                mTempRect.offsetTo(-mDismissingParallaxOffset.x, -mDismissingParallaxOffset.y);
+                t.setWindowCrop(targetLeash, mTempRect);
+            }
             t.setAlpha(targetDimLayer, mDismissingDimValue)
                     .setVisibility(targetDimLayer, mDismissingDimValue > 0.001f);
             return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
index 47dceb3..4903f9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/common/split/SplitWindowManager.java
@@ -25,16 +25,12 @@
 import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
 import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
 
-import android.app.ActivityTaskManager;
 import android.content.Context;
 import android.content.res.Configuration;
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.os.Binder;
-import android.os.IBinder;
-import android.os.RemoteException;
-import android.util.Slog;
 import android.view.IWindow;
 import android.view.InsetsState;
 import android.view.LayoutInflater;
@@ -44,6 +40,7 @@
 import android.view.WindowManager;
 import android.view.WindowlessWindowManager;
 
+import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
 
 import com.android.wm.shell.R;
@@ -59,7 +56,6 @@
     private Context mContext;
     private SurfaceControlViewHost mViewHost;
     private SurfaceControl mLeash;
-    private boolean mResizingSplits;
     private DividerView mDividerView;
 
     public interface ParentContainerCallbacks {
@@ -75,9 +71,10 @@
         mWindowName = windowName;
     }
 
-    @Override
-    public void setTouchRegion(IBinder window, Region region) {
-        super.setTouchRegion(window, region);
+    void setTouchRegion(@NonNull Rect region) {
+        if (mViewHost != null) {
+            setTouchRegion(mViewHost.getWindowToken().asBinder(), new Region(region));
+        }
     }
 
     @Override
@@ -126,7 +123,7 @@
         lp.setTitle(mWindowName);
         lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
         mViewHost.setView(mDividerView, lp);
-        mDividerView.setup(splitLayout, mViewHost, insetsState);
+        mDividerView.setup(splitLayout, this, mViewHost, insetsState);
     }
 
     /**
@@ -154,16 +151,6 @@
         mDividerView.setInteractive(interactive);
     }
 
-    void setResizingSplits(boolean resizing) {
-        if (resizing == mResizingSplits) return;
-        try {
-            ActivityTaskManager.getService().setSplitScreenResizing(resizing);
-            mResizingSplits = resizing;
-        } catch (RemoteException e) {
-            Slog.w(TAG, "Error calling setSplitScreenResizing", e);
-        }
-    }
-
     /**
      * Gets {@link SurfaceControl} of the surface holding divider view. @return {@code null} if not
      * feasible.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
index 75a1dde..3f7d78d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizer.java
@@ -39,7 +39,7 @@
 import androidx.annotation.NonNull;
 import androidx.annotation.VisibleForTesting;
 
-import com.android.internal.R;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
@@ -307,12 +307,9 @@
         t.apply();
     }
 
-    private int getStatusBarHeight() {
-        final boolean isLandscape =
-                mIsDefaultPortrait ? isDisplaySizeFlipped() : !isDisplaySizeFlipped();
-        return mContext.getResources().getDimensionPixelSize(
-                isLandscape ? R.dimen.status_bar_height_landscape
-                        : R.dimen.status_bar_height_portrait);
+    @VisibleForTesting
+    int getStatusBarHeight() {
+        return SystemBarUtils.getStatusBarHeight(mContext);
     }
 
     void dump(@NonNull PrintWriter pw) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
index 38079af..90074371 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedController.java
@@ -689,6 +689,8 @@
         pw.println(mUserId);
         pw.print(innerPrefix + "isShortcutEnabled=");
         pw.println(isShortcutEnabled());
+        pw.print(innerPrefix + "mIsSwipeToNotificationEnabled=");
+        pw.println(mIsSwipeToNotificationEnabled);
 
         if (mBackgroundPanelOrganizer != null) {
             mBackgroundPanelOrganizer.dump(pw);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
index ff333c8c..2cb7d1b 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/onehanded/OneHandedSettingsUtil.java
@@ -244,6 +244,8 @@
         pw.println(TAG);
         pw.print(innerPrefix + "isOneHandedModeEnable=");
         pw.println(getSettingsOneHandedModeEnabled(resolver, userId));
+        pw.print(innerPrefix + "isSwipeToNotificationEnabled=");
+        pw.println(getSettingsSwipeToNotificationEnabled(resolver, userId));
         pw.print(innerPrefix + "oneHandedTimeOut=");
         pw.println(getSettingsOneHandedModeTimeout(resolver, userId));
         pw.print(innerPrefix + "tapsAppToExit=");
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
index 9686776..b6e5804 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTaskOrganizer.java
@@ -282,6 +282,7 @@
         mMainExecutor.execute(() -> {
             mTaskOrganizer.addListenerForType(this, TASK_LISTENER_TYPE_PIP);
         });
+        mPipTransitionController.setPipOrganizer(this);
         displayController.addDisplayWindowListener(this);
     }
 
@@ -349,6 +350,10 @@
         }
     }
 
+    public ActivityManager.RunningTaskInfo getTaskInfo() {
+        return mTaskInfo;
+    }
+
     public SurfaceControl getSurfaceControl() {
         return mLeash;
     }
@@ -716,6 +721,9 @@
             mOnDisplayIdChangeCallback.accept(Display.DEFAULT_DISPLAY);
         }
 
+        if (Transitions.ENABLE_SHELL_TRANSITIONS) {
+            mPipTransitionController.forceFinishTransition();
+        }
         final PipAnimationController.PipTransitionAnimator<?> animator =
                 mPipAnimationController.getCurrentAnimator();
         if (animator != null) {
@@ -1284,13 +1292,17 @@
         }
         Rect baseBounds = direction == TRANSITION_DIRECTION_SNAP_AFTER_RESIZE
                 ? mPipBoundsState.getBounds() : currentBounds;
+        final boolean existingAnimatorRunning = mPipAnimationController.getCurrentAnimator() != null
+                && mPipAnimationController.getCurrentAnimator().isRunning();
         final PipAnimationController.PipTransitionAnimator<?> animator = mPipAnimationController
                 .getAnimator(mTaskInfo, mLeash, baseBounds, currentBounds, destinationBounds,
                         sourceHintRect, direction, startingAngle, rotationDelta);
         animator.setTransitionDirection(direction)
-                .setPipAnimationCallback(mPipAnimationCallback)
                 .setPipTransactionHandler(mPipTransactionHandler)
                 .setDuration(durationMs);
+        if (!existingAnimatorRunning) {
+            animator.setPipAnimationCallback(mPipAnimationCallback);
+        }
         if (isInPipDirection(direction)) {
             // Similar to auto-enter-pip transition, we use content overlay when there is no
             // source rect hint to enter PiP use bounds animation.
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 6fec1fb..b31e6e0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -32,17 +32,18 @@
 import static com.android.wm.shell.transition.Transitions.TRANSIT_EXIT_PIP;
 import static com.android.wm.shell.transition.Transitions.TRANSIT_REMOVE_PIP;
 
+import android.app.ActivityManager;
 import android.app.TaskInfo;
 import android.content.Context;
 import android.graphics.Matrix;
 import android.graphics.Rect;
 import android.os.IBinder;
+import android.util.Log;
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.window.TransitionInfo;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
-import android.window.WindowContainerTransactionCallback;
 
 import androidx.annotation.NonNull;
 import androidx.annotation.Nullable;
@@ -57,11 +58,14 @@
  */
 public class PipTransition extends PipTransitionController {
 
+    private static final String TAG = PipTransition.class.getSimpleName();
+
     private final PipTransitionState mPipTransitionState;
     private final int mEnterExitAnimationDuration;
     private @PipAnimationController.AnimationType int mOneShotAnimationType = ANIM_TYPE_BOUNDS;
     private Transitions.TransitionFinishCallback mFinishCallback;
     private Rect mExitDestinationBounds = new Rect();
+    private IBinder mExitTransition = null;
 
     public PipTransition(Context context,
             PipBoundsState pipBoundsState,
@@ -96,7 +100,7 @@
     public void startTransition(Rect destinationBounds, WindowContainerTransaction out) {
         if (destinationBounds != null) {
             mExitDestinationBounds.set(destinationBounds);
-            mTransitions.startTransition(TRANSIT_EXIT_PIP, out, this);
+            mExitTransition = mTransitions.startTransition(TRANSIT_EXIT_PIP, out, this);
         } else {
             mTransitions.startTransition(TRANSIT_REMOVE_PIP, out, this);
         }
@@ -109,17 +113,34 @@
             @android.annotation.NonNull SurfaceControl.Transaction finishTransaction,
             @android.annotation.NonNull Transitions.TransitionFinishCallback finishCallback) {
 
-        if (info.getType() == TRANSIT_EXIT_PIP && info.getChanges().size() == 1) {
-            final TransitionInfo.Change change = info.getChanges().get(0);
-            mFinishCallback = finishCallback;
-            startTransaction.apply();
-            boolean success = startExpandAnimation(change.getTaskInfo(), change.getLeash(),
-                    new Rect(mExitDestinationBounds));
-            mExitDestinationBounds.setEmpty();
-            return success;
+        if (mExitTransition == transition || info.getType() == TRANSIT_EXIT_PIP) {
+            mExitTransition = null;
+            if (info.getChanges().size() == 1) {
+                if (mFinishCallback != null) {
+                    mFinishCallback.onTransitionFinished(null, null);
+                    mFinishCallback = null;
+                    throw new RuntimeException("Previous callback not called, aborting exit PIP.");
+                }
+
+                final TransitionInfo.Change change = info.getChanges().get(0);
+                mFinishCallback = finishCallback;
+                startTransaction.apply();
+                boolean success = startExpandAnimation(change.getTaskInfo(), change.getLeash(),
+                        new Rect(mExitDestinationBounds));
+                mExitDestinationBounds.setEmpty();
+                return success;
+            } else {
+                Log.e(TAG, "Got an exit-pip transition with unexpected change-list");
+            }
         }
 
         if (info.getType() == TRANSIT_REMOVE_PIP) {
+            if (mFinishCallback != null) {
+                mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
+                mFinishCallback = null;
+                throw new RuntimeException("Previous callback not called, aborting remove PIP.");
+            }
+
             startTransaction.apply();
             finishTransaction.setWindowCrop(info.getChanges().get(0).getLeash(),
                     mPipBoundsState.getDisplayBounds());
@@ -150,6 +171,12 @@
             return false;
         }
 
+        if (mFinishCallback != null) {
+            mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
+            mFinishCallback = null;
+            throw new RuntimeException("Previous callback not called, aborting entering PIP.");
+        }
+
         // Show the wallpaper if there is a wallpaper change.
         if (wallpaper != null) {
             startTransaction.show(wallpaper.getLeash());
@@ -183,26 +210,58 @@
     }
 
     @Override
+    public void onTransitionMerged(@NonNull IBinder transition) {
+        if (transition != mExitTransition) {
+            return;
+        }
+        // This means an expand happened before enter-pip finished and we are now "merging" a
+        // no-op transition that happens to match our exit-pip.
+        boolean cancelled = false;
+        if (mPipAnimationController.getCurrentAnimator() != null) {
+            mPipAnimationController.getCurrentAnimator().cancel();
+            cancelled = true;
+        }
+        // Unset exitTransition AFTER cancel so that finishResize knows we are merging.
+        mExitTransition = null;
+        if (!cancelled) return;
+        final ActivityManager.RunningTaskInfo taskInfo = mPipOrganizer.getTaskInfo();
+        if (taskInfo != null) {
+            startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
+                    new Rect(mExitDestinationBounds));
+        }
+        mExitDestinationBounds.setEmpty();
+    }
+
+    @Override
     public void onFinishResize(TaskInfo taskInfo, Rect destinationBounds,
             @PipAnimationController.TransitionDirection int direction,
-            SurfaceControl.Transaction tx) {
+            @Nullable SurfaceControl.Transaction tx) {
 
         if (isInPipDirection(direction)) {
             mPipTransitionState.setTransitionState(PipTransitionState.ENTERED_PIP);
         }
-        WindowContainerTransaction wct = new WindowContainerTransaction();
-        prepareFinishResizeTransaction(taskInfo, destinationBounds,
-                direction, tx, wct);
-        mFinishCallback.onTransitionFinished(wct, new WindowContainerTransactionCallback() {
-            @Override
-            public void onTransactionReady(int id, @NonNull SurfaceControl.Transaction t) {
-                t.merge(tx);
-                t.apply();
+        // If there is an expected exit transition, then the exit will be "merged" into this
+        // transition so don't fire the finish-callback in that case.
+        if (mExitTransition == null && mFinishCallback != null) {
+            WindowContainerTransaction wct = new WindowContainerTransaction();
+            prepareFinishResizeTransaction(taskInfo, destinationBounds,
+                    direction, wct);
+            if (tx != null) {
+                wct.setBoundsChangeTransaction(taskInfo.token, tx);
             }
-        });
+            mFinishCallback.onTransitionFinished(wct, null /* callback */);
+            mFinishCallback = null;
+        }
         finishResizeForMenu(destinationBounds);
     }
 
+    @Override
+    public void forceFinishTransition() {
+        if (mFinishCallback == null) return;
+        mFinishCallback.onTransitionFinished(null /* wct */, null /* callback */);
+        mFinishCallback = null;
+    }
+
     private boolean startExpandAnimation(final TaskInfo taskInfo, final SurfaceControl leash,
             final Rect destinationBounds) {
         PipAnimationController.PipTransitionAnimator animator =
@@ -243,9 +302,8 @@
             startTransaction.merge(tx);
             startTransaction.apply();
             mPipBoundsState.setBounds(destinationBounds);
-            onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, tx);
+            onFinishResize(taskInfo, destinationBounds, TRANSITION_DIRECTION_TO_PIP, null /* tx */);
             sendOnPipTransitionFinished(TRANSITION_DIRECTION_TO_PIP);
-            mFinishCallback = null;
             mPipTransitionState.setInSwipePipToHomeTransition(false);
             return true;
         }
@@ -292,7 +350,6 @@
 
     private void prepareFinishResizeTransaction(TaskInfo taskInfo, Rect destinationBounds,
             @PipAnimationController.TransitionDirection int direction,
-            SurfaceControl.Transaction tx,
             WindowContainerTransaction wct) {
         Rect taskBounds = null;
         if (isInPipDirection(direction)) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
index dbf603c..376f329 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransitionController.java
@@ -49,6 +49,7 @@
     protected final Transitions mTransitions;
     private final Handler mMainHandler;
     private final List<PipTransitionCallback> mPipTransitionCallbacks = new ArrayList<>();
+    protected PipTaskOrganizer mPipOrganizer;
 
     protected final PipAnimationController.PipAnimationCallback mPipAnimationCallback =
             new PipAnimationController.PipAnimationCallback() {
@@ -103,6 +104,13 @@
         // Default implementation does nothing.
     }
 
+    /**
+     * Called when the transition animation can't continue (eg. task is removed during
+     * animation)
+     */
+    public void forceFinishTransition() {
+    }
+
     public PipTransitionController(PipBoundsState pipBoundsState,
             PipMenuController pipMenuController, PipBoundsAlgorithm pipBoundsAlgorithm,
             PipAnimationController pipAnimationController, Transitions transitions,
@@ -119,6 +127,10 @@
         }
     }
 
+    void setPipOrganizer(PipTaskOrganizer pto) {
+        mPipOrganizer = pto;
+    }
+
     /**
      * Registers {@link PipTransitionCallback} to receive transition callbacks.
      */
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
index a47a152..6440ef0 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/MainStage.java
@@ -19,11 +19,13 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 
 import android.annotation.Nullable;
+import android.content.Context;
 import android.graphics.Rect;
 import android.view.SurfaceSession;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
@@ -37,11 +39,11 @@
 
     private boolean mIsActive = false;
 
-    MainStage(ShellTaskOrganizer taskOrganizer, int displayId,
+    MainStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession,
+            SurfaceSession surfaceSession, IconProvider iconProvider,
             @Nullable StageTaskUnfoldController stageTaskUnfoldController) {
-        super(taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
+        super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession, iconProvider,
                 stageTaskUnfoldController);
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java
deleted file mode 100644
index a459c8d..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineManager.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * Copyright (C) 2021 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.wm.shell.splitscreen;
-
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
-import static android.view.WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_NO_MOVE_ANIMATION;
-import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
-import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
-
-import android.annotation.Nullable;
-import android.content.Context;
-import android.content.res.Configuration;
-import android.graphics.PixelFormat;
-import android.graphics.Rect;
-import android.os.Binder;
-import android.view.IWindow;
-import android.view.InsetsSource;
-import android.view.InsetsState;
-import android.view.LayoutInflater;
-import android.view.SurfaceControl;
-import android.view.SurfaceControlViewHost;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.WindowManager;
-import android.view.WindowlessWindowManager;
-import android.widget.FrameLayout;
-
-import com.android.wm.shell.R;
-
-/**
- * Handles drawing outline of the bounds of provided root surface. The outline will be drown with
- * the consideration of display insets like status bar, navigation bar and display cutout.
- */
-class OutlineManager extends WindowlessWindowManager {
-    private static final String WINDOW_NAME = "SplitOutlineLayer";
-    private final Context mContext;
-    private final Rect mRootBounds = new Rect();
-    private final Rect mTempRect = new Rect();
-    private final Rect mLastOutlineBounds = new Rect();
-    private final InsetsState mInsetsState = new InsetsState();
-    private final int mExpandedTaskBarHeight;
-    private OutlineView mOutlineView;
-    private SurfaceControlViewHost mViewHost;
-    private SurfaceControl mHostLeash;
-    private SurfaceControl mLeash;
-
-    OutlineManager(Context context, Configuration configuration) {
-        super(configuration, null /* rootSurface */, null /* hostInputToken */);
-        mContext = context.createWindowContext(context.getDisplay(), TYPE_APPLICATION_OVERLAY,
-                null /* options */);
-        mExpandedTaskBarHeight = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.taskbar_frame_height);
-    }
-
-    @Override
-    protected void attachToParentSurface(IWindow window, SurfaceControl.Builder b) {
-        b.setParent(mHostLeash);
-    }
-
-    void inflate(SurfaceControl rootLeash, Rect rootBounds) {
-        if (mLeash != null || mViewHost != null) return;
-
-        mHostLeash = rootLeash;
-        mRootBounds.set(rootBounds);
-        mViewHost = new SurfaceControlViewHost(mContext, mContext.getDisplay(), this);
-
-        final FrameLayout rootLayout = (FrameLayout) LayoutInflater.from(mContext)
-                .inflate(R.layout.split_outline, null);
-        mOutlineView = rootLayout.findViewById(R.id.split_outline);
-
-        final WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
-                0 /* width */, 0 /* height */, TYPE_APPLICATION_OVERLAY,
-                FLAG_NOT_FOCUSABLE | FLAG_NOT_TOUCHABLE, PixelFormat.TRANSLUCENT);
-        lp.width = mRootBounds.width();
-        lp.height = mRootBounds.height();
-        lp.token = new Binder();
-        lp.setTitle(WINDOW_NAME);
-        lp.privateFlags |= PRIVATE_FLAG_NO_MOVE_ANIMATION | PRIVATE_FLAG_TRUSTED_OVERLAY;
-        // TODO(b/189839391): Set INPUT_FEATURE_NO_INPUT_CHANNEL after WM supports
-        //  TRUSTED_OVERLAY for windowless window without input channel.
-        mViewHost.setView(rootLayout, lp);
-        mLeash = getSurfaceControl(mViewHost.getWindowToken());
-
-        drawOutline();
-    }
-
-    void release() {
-        if (mViewHost != null) {
-            mViewHost.release();
-            mViewHost = null;
-        }
-        mRootBounds.setEmpty();
-        mLastOutlineBounds.setEmpty();
-        mOutlineView = null;
-        mHostLeash = null;
-        mLeash = null;
-    }
-
-    @Nullable
-    SurfaceControl getOutlineLeash() {
-        return mLeash;
-    }
-
-    void setVisibility(boolean visible) {
-        if (mOutlineView != null) {
-            mOutlineView.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
-        }
-    }
-
-    void setRootBounds(Rect rootBounds) {
-        if (mViewHost == null || mViewHost.getView() == null) {
-            return;
-        }
-
-        if (!mRootBounds.equals(rootBounds)) {
-            WindowManager.LayoutParams lp =
-                    (WindowManager.LayoutParams) mViewHost.getView().getLayoutParams();
-            lp.width = rootBounds.width();
-            lp.height = rootBounds.height();
-            mViewHost.relayout(lp);
-            mRootBounds.set(rootBounds);
-            drawOutline();
-        }
-    }
-
-    void onInsetsChanged(InsetsState insetsState) {
-        if (!mInsetsState.equals(insetsState)) {
-            mInsetsState.set(insetsState);
-            drawOutline();
-        }
-    }
-
-    private void computeOutlineBounds(Rect rootBounds, InsetsState insetsState, Rect outBounds) {
-        outBounds.set(rootBounds);
-        final InsetsSource taskBarInsetsSource =
-                insetsState.getSource(InsetsState.ITYPE_EXTRA_NAVIGATION_BAR);
-        // Only insets the divider bar with task bar when it's expanded so that the rounded corners
-        // will be drawn against task bar.
-        if (taskBarInsetsSource.getFrame().height() >= mExpandedTaskBarHeight) {
-            outBounds.inset(taskBarInsetsSource.calculateVisibleInsets(outBounds));
-        }
-
-        // Offset the coordinate from screen based to surface based.
-        outBounds.offset(-rootBounds.left, -rootBounds.top);
-    }
-
-    void drawOutline() {
-        if (mOutlineView == null) {
-            return;
-        }
-
-        computeOutlineBounds(mRootBounds, mInsetsState, mTempRect);
-        if (mTempRect.equals(mLastOutlineBounds)) {
-            return;
-        }
-
-        ViewGroup.MarginLayoutParams lp =
-                (ViewGroup.MarginLayoutParams) mOutlineView.getLayoutParams();
-        lp.leftMargin = mTempRect.left;
-        lp.topMargin = mTempRect.top;
-        lp.width = mTempRect.width();
-        lp.height = mTempRect.height();
-        mOutlineView.setLayoutParams(lp);
-        mLastOutlineBounds.set(mTempRect);
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java
deleted file mode 100644
index 94dd9b2..0000000
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/OutlineView.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (C) 2021 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.wm.shell.splitscreen;
-
-import static android.view.RoundedCorner.POSITION_BOTTOM_LEFT;
-import static android.view.RoundedCorner.POSITION_BOTTOM_RIGHT;
-import static android.view.RoundedCorner.POSITION_TOP_LEFT;
-import static android.view.RoundedCorner.POSITION_TOP_RIGHT;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.util.AttributeSet;
-import android.view.RoundedCorner;
-import android.view.View;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-
-import com.android.internal.R;
-
-/** View for drawing split outline. */
-public class OutlineView extends View {
-    private final Paint mPaint = new Paint();
-    private final Path mPath = new Path();
-    private final float[] mRadii = new float[8];
-
-    public OutlineView(@NonNull Context context, @Nullable AttributeSet attrs) {
-        super(context, attrs);
-        mPaint.setStyle(Paint.Style.STROKE);
-        mPaint.setStrokeWidth(
-                getResources().getDimension(R.dimen.accessibility_focus_highlight_stroke_width));
-        mPaint.setColor(getResources().getColor(R.color.system_accent1_100, null));
-    }
-
-    @Override
-    protected void onAttachedToWindow() {
-        // TODO(b/200850654): match the screen corners with the actual display decor.
-        mRadii[0] = mRadii[1] = getCornerRadius(POSITION_TOP_LEFT);
-        mRadii[2] = mRadii[3] = getCornerRadius(POSITION_TOP_RIGHT);
-        mRadii[4] = mRadii[5] = getCornerRadius(POSITION_BOTTOM_RIGHT);
-        mRadii[6] = mRadii[7] = getCornerRadius(POSITION_BOTTOM_LEFT);
-    }
-
-    private int getCornerRadius(@RoundedCorner.Position int position) {
-        final RoundedCorner roundedCorner = getDisplay().getRoundedCorner(position);
-        return roundedCorner == null ? 0 : roundedCorner.getRadius();
-    }
-
-    @Override
-    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
-        if (changed) {
-            mPath.reset();
-            mPath.addRoundRect(0, 0, getWidth(), getHeight(), mRadii, Path.Direction.CW);
-        }
-    }
-
-    @Override
-    protected void onDraw(Canvas canvas) {
-        canvas.drawPath(mPath, mPaint);
-    }
-
-    @Override
-    public boolean hasOverlappingRendering() {
-        return false;
-    }
-}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
index dc8fb9f..51104e4 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SideStage.java
@@ -16,20 +16,16 @@
 
 package com.android.wm.shell.splitscreen;
 
-import android.annotation.CallSuper;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
 import android.content.Context;
 import android.graphics.Rect;
-import android.view.InsetsSourceControl;
-import android.view.InsetsState;
-import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
-import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
 /**
@@ -38,19 +34,15 @@
  *
  * @see StageCoordinator
  */
-class SideStage extends StageTaskListener implements
-        DisplayInsetsController.OnInsetsChangedListener {
+class SideStage extends StageTaskListener {
     private static final String TAG = SideStage.class.getSimpleName();
-    private final Context mContext;
-    private OutlineManager mOutlineManager;
 
     SideStage(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession,
+            SurfaceSession surfaceSession, IconProvider iconProvider,
             @Nullable StageTaskUnfoldController stageTaskUnfoldController) {
-        super(taskOrganizer, displayId, callbacks, syncQueue, surfaceSession,
+        super(context, taskOrganizer, displayId, callbacks, syncQueue, surfaceSession, iconProvider,
                 stageTaskUnfoldController);
-        mContext = context;
     }
 
     void addTask(ActivityManager.RunningTaskInfo task, Rect rootBounds,
@@ -83,62 +75,4 @@
         wct.reparent(task.token, newParent, false /* onTop */);
         return true;
     }
-
-    @Nullable
-    public SurfaceControl getOutlineLeash() {
-        return mOutlineManager.getOutlineLeash();
-    }
-
-    @Override
-    @CallSuper
-    public void onTaskAppeared(ActivityManager.RunningTaskInfo taskInfo, SurfaceControl leash) {
-        super.onTaskAppeared(taskInfo, leash);
-        if (isRootTask(taskInfo)) {
-            mOutlineManager = new OutlineManager(mContext, taskInfo.configuration);
-            enableOutline(true);
-        }
-    }
-
-    @Override
-    @CallSuper
-    public void onTaskInfoChanged(ActivityManager.RunningTaskInfo taskInfo) {
-        super.onTaskInfoChanged(taskInfo);
-        if (isRootTask(taskInfo)) {
-            mOutlineManager.setRootBounds(taskInfo.configuration.windowConfiguration.getBounds());
-        }
-    }
-
-    private boolean isRootTask(ActivityManager.RunningTaskInfo taskInfo) {
-        return mRootTaskInfo != null && mRootTaskInfo.taskId == taskInfo.taskId;
-    }
-
-    void enableOutline(boolean enable) {
-        if (mOutlineManager == null) {
-            return;
-        }
-
-        if (enable) {
-            if (mRootTaskInfo != null) {
-                mOutlineManager.inflate(mRootLeash,
-                        mRootTaskInfo.configuration.windowConfiguration.getBounds());
-            }
-        } else {
-            mOutlineManager.release();
-        }
-    }
-
-    void setOutlineVisibility(boolean visible) {
-        mOutlineManager.setVisibility(visible);
-    }
-
-    @Override
-    public void insetsChanged(InsetsState insetsState) {
-        mOutlineManager.onInsetsChanged(insetsState);
-    }
-
-    @Override
-    public void insetsControlChanged(InsetsState insetsState,
-            InsetsSourceControl[] activeControls) {
-        insetsChanged(insetsState);
-    }
 }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
index ec71fbe..36f1406 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/SplitScreenController.java
@@ -54,6 +54,7 @@
 
 import com.android.internal.logging.InstanceId;
 import com.android.internal.util.FrameworkStatsLog;
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayImeController;
@@ -78,6 +79,7 @@
 /**
  * Class manages split-screen multitasking mode and implements the main interface
  * {@link SplitScreen}.
+ *
  * @see StageCoordinator
  */
 // TODO(b/198577848): Implement split screen flicker test to consolidate CUJ of split screen.
@@ -96,6 +98,7 @@
     private final Transitions mTransitions;
     private final TransactionPool mTransactionPool;
     private final SplitscreenEventLogger mLogger;
+    private final IconProvider mIconProvider;
     private final Provider<Optional<StageTaskUnfoldController>> mUnfoldControllerProvider;
 
     private StageCoordinator mStageCoordinator;
@@ -105,7 +108,7 @@
             RootTaskDisplayAreaOrganizer rootTDAOrganizer,
             ShellExecutor mainExecutor, DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController,
-            Transitions transitions, TransactionPool transactionPool,
+            Transitions transitions, TransactionPool transactionPool, IconProvider iconProvider,
             Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
         mTaskOrganizer = shellTaskOrganizer;
         mSyncQueue = syncQueue;
@@ -118,6 +121,7 @@
         mTransactionPool = transactionPool;
         mUnfoldControllerProvider = unfoldControllerProvider;
         mLogger = new SplitscreenEventLogger();
+        mIconProvider = iconProvider;
     }
 
     public SplitScreen asSplitScreen() {
@@ -140,7 +144,7 @@
             mStageCoordinator = new StageCoordinator(mContext, DEFAULT_DISPLAY, mSyncQueue,
                     mRootTDAOrganizer, mTaskOrganizer, mDisplayImeController,
                     mDisplayInsetsController, mTransitions, mTransactionPool, mLogger,
-                    mUnfoldControllerProvider);
+                    mIconProvider, mUnfoldControllerProvider);
         }
     }
 
@@ -165,10 +169,6 @@
         return mStageCoordinator.removeFromSideStage(taskId);
     }
 
-    public void setSideStageOutline(boolean enable) {
-        mStageCoordinator.setSideStageOutline(enable);
-    }
-
     public void setSideStagePosition(@SplitPosition int sideStagePosition) {
         mStageCoordinator.setSideStagePosition(sideStagePosition, null /* wct */);
     }
@@ -215,10 +215,12 @@
         options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */);
 
         try {
+            final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+            mStageCoordinator.prepareEvictChildTasks(position, evictWct);
             final int result =
                     ActivityTaskManager.getService().startActivityFromRecents(taskId, options);
             if (result == START_SUCCESS || result == START_TASK_TO_FRONT) {
-                mStageCoordinator.evictOccludedChildren(position);
+                mSyncQueue.queue(evictWct);
             }
         } catch (RemoteException e) {
             Slog.e(TAG, "Failed to launch task", e);
@@ -229,13 +231,15 @@
             @SplitScreen.StageType int stage, @SplitPosition int position,
             @Nullable Bundle options, UserHandle user) {
         options = mStageCoordinator.resolveStartStage(stage, position, options, null /* wct */);
+        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+        mStageCoordinator.prepareEvictChildTasks(position, evictWct);
 
         try {
             LauncherApps launcherApps =
                     mContext.getSystemService(LauncherApps.class);
             launcherApps.startShortcut(packageName, shortcutId, null /* sourceBounds */,
                     options, user);
-            mStageCoordinator.evictOccludedChildren(position);
+            mSyncQueue.queue(evictWct);
         } catch (ActivityNotFoundException e) {
             Slog.e(TAG, "Failed to launch shortcut", e);
         }
@@ -255,6 +259,9 @@
     private void startIntentLegacy(PendingIntent intent, Intent fillInIntent,
             @SplitScreen.StageType int stage, @SplitPosition int position,
             @Nullable Bundle options) {
+        final WindowContainerTransaction evictWct = new WindowContainerTransaction();
+        mStageCoordinator.prepareEvictChildTasks(position, evictWct);
+
         LegacyTransitions.ILegacyTransition transition = new LegacyTransitions.ILegacyTransition() {
             @Override
             public void onAnimationStart(int transit, RemoteAnimationTarget[] apps,
@@ -280,12 +287,11 @@
                     }
                 }
 
-                // Launching a new app into a specific split evicts tasks previously in the same
-                // split.
-                mStageCoordinator.evictOccludedChildren(position);
+                mSyncQueue.queue(evictWct);
             }
         };
-        WindowContainerTransaction wct = new WindowContainerTransaction();
+
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
         options = mStageCoordinator.resolveStartStage(stage, position, options, wct);
         wct.sendPendingIntent(intent, fillInIntent, options);
         mSyncQueue.queue(transition, WindowManager.TRANSIT_OPEN, wct);
@@ -313,9 +319,7 @@
         }
         transaction.apply();
         transaction.close();
-        return new RemoteAnimationTarget[]{
-                mStageCoordinator.getDividerBarLegacyTarget(),
-                mStageCoordinator.getOutlineLegacyTarget()};
+        return new RemoteAnimationTarget[]{mStageCoordinator.getDividerBarLegacyTarget()};
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 0cff18e..3b62afc 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -80,6 +80,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.InstanceId;
 import com.android.internal.protolog.common.ProtoLog;
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.DisplayImeController;
@@ -151,10 +152,12 @@
     /** Whether the device is supporting legacy split or not. */
     private boolean mUseLegacySplit;
 
-    @SplitScreen.StageType private int mDismissTop = NO_DISMISS;
+    @SplitScreen.StageType
+    private int mDismissTop = NO_DISMISS;
 
     /** The target stage to dismiss to when unlock after folded. */
-    @SplitScreen.StageType private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
+    @SplitScreen.StageType
+    private int mTopStageAfterFoldDismiss = STAGE_TYPE_UNDEFINED;
 
     private final Runnable mOnTransitionAnimationComplete = () -> {
         // If still playing, let it finish.
@@ -169,22 +172,23 @@
 
     private final SplitWindowManager.ParentContainerCallbacks mParentContainerCallbacks =
             new SplitWindowManager.ParentContainerCallbacks() {
-        @Override
-        public void attachToParentSurface(SurfaceControl.Builder b) {
-            mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b);
-        }
+                @Override
+                public void attachToParentSurface(SurfaceControl.Builder b) {
+                    mRootTDAOrganizer.attachToDisplayArea(mDisplayId, b);
+                }
 
-        @Override
-        public void onLeashReady(SurfaceControl leash) {
-            mSyncQueue.runInSync(t -> applyDividerVisibility(t));
-        }
-    };
+                @Override
+                public void onLeashReady(SurfaceControl leash) {
+                    mSyncQueue.runInSync(t -> applyDividerVisibility(t));
+                }
+            };
 
     StageCoordinator(Context context, int displayId, SyncTransactionQueue syncQueue,
             RootTaskDisplayAreaOrganizer rootTDAOrganizer, ShellTaskOrganizer taskOrganizer,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController, Transitions transitions,
             TransactionPool transactionPool, SplitscreenEventLogger logger,
+            IconProvider iconProvider,
             Provider<Optional<StageTaskUnfoldController>> unfoldControllerProvider) {
         mContext = context;
         mDisplayId = displayId;
@@ -196,11 +200,13 @@
         mSideUnfoldController = unfoldControllerProvider.get().orElse(null);
 
         mMainStage = new MainStage(
+                mContext,
                 mTaskOrganizer,
                 mDisplayId,
                 mMainStageListener,
                 mSyncQueue,
                 mSurfaceSession,
+                iconProvider,
                 mMainUnfoldController);
         mSideStage = new SideStage(
                 mContext,
@@ -209,10 +215,10 @@
                 mSideStageListener,
                 mSyncQueue,
                 mSurfaceSession,
+                iconProvider,
                 mSideUnfoldController);
         mDisplayImeController = displayImeController;
         mDisplayInsetsController = displayInsetsController;
-        mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSideStage);
         mRootTDAOrganizer.registerListener(displayId, this);
         final DeviceStateManager deviceStateManager =
                 mContext.getSystemService(DeviceStateManager.class);
@@ -284,10 +290,6 @@
         return result;
     }
 
-    void setSideStageOutline(boolean enable) {
-        mSideStage.enableOutline(enable);
-    }
-
     /** Starts 2 tasks in one transition. */
     void startTasks(int mainTaskId, @Nullable Bundle mainOptions, int sideTaskId,
             @Nullable Bundle sideOptions, @SplitPosition int sidePosition,
@@ -394,10 +396,16 @@
                 TRANSIT_SPLIT_SCREEN_OPEN_TO_SIDE, wct, remoteTransition, this);
     }
 
-    void evictOccludedChildren(@SplitPosition int position) {
-        final WindowContainerTransaction wct = new WindowContainerTransaction();
-        (position == mSideStagePosition ? mSideStage : mMainStage).evictOccludedChildren(wct);
-        mTaskOrganizer.applyTransaction(wct);
+    /**
+     * Collects all the current child tasks of a specific split and prepares transaction to evict
+     * them to display.
+     */
+    void prepareEvictChildTasks(@SplitPosition int position, WindowContainerTransaction wct) {
+        if (position == mSideStagePosition) {
+            mSideStage.evictAllChildren(wct);
+        } else {
+            mMainStage.evictAllChildren(wct);
+        }
     }
 
     Bundle resolveStartStage(@SplitScreen.StageType int stage,
@@ -691,9 +699,10 @@
 
         if (bothStageInvisible) {
             if (mExitSplitScreenOnHide
-            // Don't dismiss staged split when both stages are not visible due to sleeping display,
-            // like the cases keyguard showing or screen off.
-            || (!mMainStage.mRootTaskInfo.isSleeping && !mSideStage.mRootTaskInfo.isSleeping)) {
+                    // Don't dismiss staged split when both stages are not visible due to sleeping
+                    // display, like the cases keyguard showing or screen off.
+                    || (!mMainStage.mRootTaskInfo.isSleeping
+                    && !mSideStage.mRootTaskInfo.isSleeping)) {
                 exitSplitScreen(null /* childrenToTop */,
                         SPLITSCREEN_UICHANGED__EXIT_REASON__RETURN_HOME);
             }
@@ -713,7 +722,6 @@
                 t.setVisibility(mSideStage.mRootLeash, bothStageVisible)
                         .setVisibility(mMainStage.mRootLeash, bothStageVisible);
                 applyDividerVisibility(t);
-                applyOutlineVisibility(t);
             }
         });
     }
@@ -735,19 +743,6 @@
         }
     }
 
-    private void applyOutlineVisibility(SurfaceControl.Transaction t) {
-        final SurfaceControl outlineLeash = mSideStage.getOutlineLeash();
-        if (outlineLeash == null) {
-            return;
-        }
-
-        if (mDividerVisible) {
-            t.show(outlineLeash).setLayer(outlineLeash, SPLIT_DIVIDER_LAYER);
-        } else {
-            t.hide(outlineLeash);
-        }
-    }
-
     private void onStageHasChildrenChanged(StageListenerImpl stageListener) {
         final boolean hasChildren = stageListener.mHasChildren;
         final boolean isSideStage = stageListener == mSideStageListener;
@@ -811,8 +806,11 @@
 
     @Override
     public void onLayoutSizeChanging(SplitLayout layout) {
-        mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
-        mSideStage.setOutlineVisibility(false);
+        mSyncQueue.runInSync(t -> {
+            updateSurfaceBounds(layout, t);
+            mMainStage.onResizing(getMainStageBounds(), t);
+            mSideStage.onResizing(getSideStageBounds(), t);
+        });
     }
 
     @Override
@@ -821,8 +819,11 @@
         updateWindowBounds(layout, wct);
         updateUnfoldBounds();
         mSyncQueue.queue(wct);
-        mSyncQueue.runInSync(t -> updateSurfaceBounds(layout, t));
-        mSideStage.setOutlineVisibility(true);
+        mSyncQueue.runInSync(t -> {
+            updateSurfaceBounds(layout, t);
+            mMainStage.onResized(getMainStageBounds(), t);
+            mSideStage.onResized(getSideStageBounds(), t);
+        });
         mLogger.logResize(mSplitLayout.getDividerPositionAsFraction());
     }
 
@@ -887,7 +888,7 @@
         if (mSplitLayout == null) {
             mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
                     mDisplayAreaInfo.configuration, this, mParentContainerCallbacks,
-                    mDisplayImeController, mTaskOrganizer);
+                    mDisplayImeController, mTaskOrganizer, false /* applyDismissingParallax */);
             mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
 
             if (mMainUnfoldController != null && mSideUnfoldController != null) {
@@ -1210,18 +1211,6 @@
                 null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER);
     }
 
-    RemoteAnimationTarget getOutlineLegacyTarget() {
-        final Rect bounds = mSideStage.mRootTaskInfo.configuration.windowConfiguration.getBounds();
-        // Leverage TYPE_DOCK_DIVIDER type when wrapping outline remote animation target in order to
-        // distinguish as a split auxiliary target in Launcher.
-        return new RemoteAnimationTarget(-1 /* taskId */, -1 /* mode */,
-                mSideStage.getOutlineLeash(), false /* isTranslucent */, null /* clipRect */,
-                null /* contentInsets */, Integer.MAX_VALUE /* prefixOrderIndex */,
-                new android.graphics.Point(0, 0) /* position */, bounds, bounds,
-                new WindowConfiguration(), true, null /* startLeash */, null /* startBounds */,
-                null /* taskInfo */, false /* allowEnterPip */, TYPE_DOCK_DIVIDER);
-    }
-
     @Override
     public void dump(@NonNull PrintWriter pw, String prefix) {
         final String innerPrefix = prefix + "  ";
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
index 071badf..5100c56 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageTaskListener.java
@@ -26,6 +26,7 @@
 import android.annotation.CallSuper;
 import android.annotation.Nullable;
 import android.app.ActivityManager;
+import android.content.Context;
 import android.graphics.Point;
 import android.graphics.Rect;
 import android.util.SparseArray;
@@ -35,9 +36,11 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.common.SurfaceUtils;
 import com.android.wm.shell.common.SyncTransactionQueue;
+import com.android.wm.shell.common.split.SplitDecorManager;
 
 import java.io.PrintWriter;
 
@@ -72,25 +75,31 @@
         void onNoLongerSupportMultiWindow();
     }
 
+    private final Context mContext;
     private final StageListenerCallbacks mCallbacks;
     private final SurfaceSession mSurfaceSession;
-    protected final SyncTransactionQueue mSyncQueue;
+    private final SyncTransactionQueue mSyncQueue;
+    private final IconProvider mIconProvider;
 
     protected ActivityManager.RunningTaskInfo mRootTaskInfo;
     protected SurfaceControl mRootLeash;
     protected SurfaceControl mDimLayer;
     protected SparseArray<ActivityManager.RunningTaskInfo> mChildrenTaskInfo = new SparseArray<>();
     private final SparseArray<SurfaceControl> mChildrenLeashes = new SparseArray<>();
+    // TODO(b/204308910): Extracts SplitDecorManager related code to common package.
+    private SplitDecorManager mSplitDecorManager;
 
     private final StageTaskUnfoldController mStageTaskUnfoldController;
 
-    StageTaskListener(ShellTaskOrganizer taskOrganizer, int displayId,
+    StageTaskListener(Context context, ShellTaskOrganizer taskOrganizer, int displayId,
             StageListenerCallbacks callbacks, SyncTransactionQueue syncQueue,
-            SurfaceSession surfaceSession,
+            SurfaceSession surfaceSession, IconProvider iconProvider,
             @Nullable StageTaskUnfoldController stageTaskUnfoldController) {
+        mContext = context;
         mCallbacks = callbacks;
         mSyncQueue = syncQueue;
         mSurfaceSession = surfaceSession;
+        mIconProvider = iconProvider;
         mStageTaskUnfoldController = stageTaskUnfoldController;
         taskOrganizer.createRootTask(displayId, WINDOWING_MODE_MULTI_WINDOW, this);
     }
@@ -142,13 +151,14 @@
         if (mRootTaskInfo == null && !taskInfo.hasParentTask()) {
             mRootLeash = leash;
             mRootTaskInfo = taskInfo;
+            mSplitDecorManager = new SplitDecorManager(
+                    mRootTaskInfo.configuration,
+                    mIconProvider,
+                    mSurfaceSession);
             mCallbacks.onRootTaskAppeared();
             sendStatusChanged();
-            mSyncQueue.runInSync(t -> {
-                t.hide(mRootLeash);
-                mDimLayer =
-                        SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession);
-            });
+            mSyncQueue.runInSync(t -> mDimLayer =
+                    SurfaceUtils.makeDimLayer(t, mRootLeash, "Dim layer", mSurfaceSession));
         } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
             final int taskId = taskInfo.taskId;
             mChildrenLeashes.put(taskId, leash);
@@ -179,6 +189,17 @@
             return;
         }
         if (mRootTaskInfo.taskId == taskInfo.taskId) {
+            // Inflates split decor view only when the root task is visible.
+            if (mRootTaskInfo.isVisible != taskInfo.isVisible) {
+                mSyncQueue.runInSync(t -> {
+                    if (taskInfo.isVisible) {
+                        mSplitDecorManager.inflate(mContext, mRootLeash,
+                                taskInfo.configuration.windowConfiguration.getBounds());
+                    } else {
+                        mSplitDecorManager.release(t);
+                    }
+                });
+            }
             mRootTaskInfo = taskInfo;
         } else if (taskInfo.parentTaskId == mRootTaskInfo.taskId) {
             mChildrenTaskInfo.put(taskInfo.taskId, taskInfo);
@@ -205,8 +226,11 @@
         final int taskId = taskInfo.taskId;
         if (mRootTaskInfo.taskId == taskId) {
             mCallbacks.onRootTaskVanished();
-            mSyncQueue.runInSync(t -> t.remove(mDimLayer));
             mRootTaskInfo = null;
+            mSyncQueue.runInSync(t -> {
+                t.remove(mDimLayer);
+                mSplitDecorManager.release(t);
+            });
         } else if (mChildrenTaskInfo.contains(taskId)) {
             mChildrenTaskInfo.remove(taskId);
             mChildrenLeashes.remove(taskId);
@@ -237,6 +261,18 @@
         }
     }
 
+    void onResizing(Rect newBounds, SurfaceControl.Transaction t) {
+        if (mSplitDecorManager != null && mRootTaskInfo != null) {
+            mSplitDecorManager.onResizing(mRootTaskInfo, newBounds, t);
+        }
+    }
+
+    void onResized(Rect newBounds, SurfaceControl.Transaction t) {
+        if (mSplitDecorManager != null) {
+            mSplitDecorManager.onResized(newBounds, t);
+        }
+    }
+
     void setBounds(Rect bounds, WindowContainerTransaction wct) {
         wct.setBounds(mRootTaskInfo.token, bounds);
     }
@@ -248,12 +284,11 @@
         wct.reorder(mChildrenTaskInfo.get(taskId).token, onTop /* onTop */);
     }
 
-    void evictOccludedChildren(WindowContainerTransaction wct) {
+    /** Collects all the current child tasks and prepares transaction to evict them to display. */
+    void evictAllChildren(WindowContainerTransaction wct) {
         for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
             final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
-            if (!taskInfo.isVisible) {
-                wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
-            }
+            wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
         }
     }
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
index 574e379..60a6cd7 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/stagesplit/StageCoordinator.java
@@ -882,7 +882,7 @@
         if (mSplitLayout == null) {
             mSplitLayout = new SplitLayout(TAG + "SplitDivider", mContext,
                     mDisplayAreaInfo.configuration, this, mParentContainerCallbacks,
-                    mDisplayImeController, mTaskOrganizer);
+                    mDisplayImeController, mTaskOrganizer, true /* applyDismissingParallax */);
             mDisplayInsetsController.addInsetsChangedListener(mDisplayId, mSplitLayout);
 
             if (mMainUnfoldController != null && mSideUnfoldController != null) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
index 8df7cbb..b191cab 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenContentDrawer.java
@@ -110,9 +110,9 @@
     @VisibleForTesting
     final ColorCache mColorCache;
 
-    SplashscreenContentDrawer(Context context, TransactionPool pool) {
+    SplashscreenContentDrawer(Context context, IconProvider iconProvider, TransactionPool pool) {
         mContext = context;
-        mIconProvider = new IconProvider(context);
+        mIconProvider = iconProvider;
         mTransactionPool = pool;
 
         // Initialize Splashscreen worker thread
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
index 38122ff..e2a72bd 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/SplashscreenIconDrawableFactory.java
@@ -314,7 +314,7 @@
 
         @Override
         public void stopAnimation() {
-            if (mIconAnimator != null) {
+            if (mIconAnimator != null && mIconAnimator.isRunning()) {
                 mIconAnimator.end();
             }
         }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
index 979bf00..bd48696 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawer.java
@@ -61,6 +61,7 @@
 
 import com.android.internal.R;
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
 import com.android.wm.shell.common.annotations.ShellSplashscreenThread;
@@ -123,11 +124,11 @@
      * @param splashScreenExecutor The thread used to control add and remove starting window.
      */
     public StartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
-            TransactionPool pool) {
+            IconProvider iconProvider, TransactionPool pool) {
         mContext = context;
         mDisplayManager = mContext.getSystemService(DisplayManager.class);
         mSplashScreenExecutor = splashScreenExecutor;
-        mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, pool);
+        mSplashscreenContentDrawer = new SplashscreenContentDrawer(mContext, iconProvider, pool);
         mSplashScreenExecutor.execute(() -> mChoreographer = Choreographer.getInstance());
         mWindowManagerGlobal = WindowManagerGlobal.getInstance();
         mDisplayManager.getDisplay(DEFAULT_DISPLAY);
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
index 99644f9..a86e07a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/StartingWindowController.java
@@ -43,6 +43,7 @@
 
 import com.android.internal.annotations.GuardedBy;
 import com.android.internal.util.function.TriConsumer;
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.RemoteCallable;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
@@ -85,9 +86,11 @@
     private final SparseIntArray mTaskBackgroundColors = new SparseIntArray();
 
     public StartingWindowController(Context context, ShellExecutor splashScreenExecutor,
-            StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) {
+            StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, IconProvider iconProvider,
+            TransactionPool pool) {
         mContext = context;
-        mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor, pool);
+        mStartingSurfaceDrawer = new StartingSurfaceDrawer(context, splashScreenExecutor,
+                iconProvider, pool);
         mStartingWindowTypeAlgorithm = startingWindowTypeAlgorithm;
         mSplashScreenExecutor = splashScreenExecutor;
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
index 663d647..7abda99 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultTransitionHandler.java
@@ -70,6 +70,7 @@
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
 import android.window.TransitionInfo;
+import android.window.TransitionMetrics;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerToken;
 import android.window.WindowContainerTransaction;
@@ -362,6 +363,7 @@
             }
         }
         startTransaction.apply();
+        TransitionMetrics.getInstance().reportAnimationStart(transition);
         // run finish now in-case there are no animations
         onAnimFinish.run();
         return true;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 2720157..c369831 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -44,6 +44,7 @@
 import android.window.RemoteTransition;
 import android.window.TransitionFilter;
 import android.window.TransitionInfo;
+import android.window.TransitionMetrics;
 import android.window.TransitionRequestInfo;
 import android.window.WindowContainerTransaction;
 import android.window.WindowContainerTransactionCallback;
@@ -192,6 +193,8 @@
     public void register(ShellTaskOrganizer taskOrganizer) {
         if (mPlayerImpl == null) return;
         taskOrganizer.registerTransitionPlayer(mPlayerImpl);
+        // Pre-load the instance.
+        TransitionMetrics.getInstance();
     }
 
     /**
diff --git a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
index c07f0eb..c4be785 100644
--- a/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
+++ b/libs/WindowManager/Shell/tests/flicker/src/com/android/wm/shell/flicker/CommonAssertions.kt
@@ -78,7 +78,7 @@
     assertLayersEnd {
         val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
         visibleRegion(primaryComponent)
-            .coversExactly(getPrimaryRegion(dividerRegion, rotation))
+            .overlaps(getPrimaryRegion(dividerRegion, rotation))
     }
 }
 
@@ -89,7 +89,7 @@
     assertLayersEnd {
         val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
         visibleRegion(primaryComponent)
-            .coversExactly(getPrimaryRegion(dividerRegion, rotation))
+            .overlaps(getPrimaryRegion(dividerRegion, rotation))
     }
 }
 
@@ -100,7 +100,7 @@
     assertLayersEnd {
         val dividerRegion = layer(APP_PAIR_SPLIT_DIVIDER_COMPONENT).visibleRegion.region
         visibleRegion(secondaryComponent)
-            .coversExactly(getSecondaryRegion(dividerRegion, rotation))
+            .overlaps(getSecondaryRegion(dividerRegion, rotation))
     }
 }
 
@@ -111,7 +111,7 @@
     assertLayersEnd {
         val dividerRegion = layer(DOCKED_STACK_DIVIDER_COMPONENT).visibleRegion.region
         visibleRegion(secondaryComponent)
-            .coversExactly(getSecondaryRegion(dividerRegion, rotation))
+            .overlaps(getSecondaryRegion(dividerRegion, rotation))
     }
 }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
index 88e754c..0ffa5b3 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayLayoutTest.java
@@ -21,9 +21,14 @@
 import static android.view.Surface.ROTATION_270;
 import static android.view.Surface.ROTATION_90;
 
+import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession;
+
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
 
 import android.content.res.Configuration;
 import android.content.res.Resources;
@@ -35,8 +40,12 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.R;
+import com.android.internal.policy.SystemBarUtils;
 
+import org.junit.After;
+import org.junit.Before;
 import org.junit.Test;
+import org.mockito.MockitoSession;
 
 /**
  * Tests for {@link DisplayLayout}.
@@ -46,29 +55,48 @@
  */
 @SmallTest
 public class DisplayLayoutTest {
+    private MockitoSession mMockitoSession;
+
+    @Before
+    public void setup() {
+        mMockitoSession = mockitoSession()
+                .initMocks(this)
+                .mockStatic(SystemBarUtils.class)
+                .startMocking();
+    }
+
+    @After
+    public void tearDown() {
+        mMockitoSession.finishMocking();
+    }
 
     @Test
     public void testInsets() {
-        Resources res = createResources(40, 50, false, 30, 40);
+        Resources res = createResources(40, 50, false);
         // Test empty display, no bars or anything
         DisplayInfo info = createDisplayInfo(1000, 1500, 0, ROTATION_0);
         DisplayLayout dl = new DisplayLayout(info, res, false, false);
+        when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(40);
+        dl.recalcInsets(res);
         assertEquals(new Rect(0, 0, 0, 0), dl.stableInsets());
         assertEquals(new Rect(0, 0, 0, 0), dl.nonDecorInsets());
 
         // Test with bars
         dl = new DisplayLayout(info, res, true, true);
+        dl.recalcInsets(res);
         assertEquals(new Rect(0, 40, 0, 50), dl.stableInsets());
         assertEquals(new Rect(0, 0, 0, 50), dl.nonDecorInsets());
 
         // Test just cutout
         info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
         dl = new DisplayLayout(info, res, false, false);
+        dl.recalcInsets(res);
         assertEquals(new Rect(0, 60, 0, 0), dl.stableInsets());
         assertEquals(new Rect(0, 60, 0, 0), dl.nonDecorInsets());
 
         // Test with bars and cutout
         dl = new DisplayLayout(info, res, true, true);
+        dl.recalcInsets(res);
         assertEquals(new Rect(0, 60, 0, 50), dl.stableInsets());
         assertEquals(new Rect(0, 60, 0, 50), dl.nonDecorInsets());
     }
@@ -76,27 +104,30 @@
     @Test
     public void testRotate() {
         // Basic rotate utility
-        Resources res = createResources(40, 50, false, 30, 40);
+        Resources res = createResources(40, 50, false);
         DisplayInfo info = createDisplayInfo(1000, 1500, 60, ROTATION_0);
         DisplayLayout dl = new DisplayLayout(info, res, true, true);
+        when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(40);
+        dl.recalcInsets(res);
         assertEquals(new Rect(0, 60, 0, 50), dl.stableInsets());
         assertEquals(new Rect(0, 60, 0, 50), dl.nonDecorInsets());
 
         // Rotate to 90
+        when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(30);
         dl.rotateTo(res, ROTATION_90);
         assertEquals(new Rect(60, 30, 0, 40), dl.stableInsets());
         assertEquals(new Rect(60, 0, 0, 40), dl.nonDecorInsets());
 
         // Rotate with moving navbar
-        res = createResources(40, 50, true, 30, 40);
+        res = createResources(40, 50, true);
         dl = new DisplayLayout(info, res, true, true);
+        when(SystemBarUtils.getStatusBarHeight(eq(res), any())).thenReturn(30);
         dl.rotateTo(res, ROTATION_270);
         assertEquals(new Rect(40, 30, 60, 0), dl.stableInsets());
         assertEquals(new Rect(40, 0, 60, 0), dl.nonDecorInsets());
     }
 
-    private Resources createResources(
-            int navLand, int navPort, boolean navMoves, int statusLand, int statusPort) {
+    private Resources createResources(int navLand, int navPort, boolean navMoves) {
         Configuration cfg = new Configuration();
         cfg.uiMode = UI_MODE_TYPE_NORMAL;
         Resources res = mock(Resources.class);
@@ -108,8 +139,6 @@
         doReturn(navPort).when(res).getDimensionPixelSize(R.dimen.navigation_bar_height);
         doReturn(navLand).when(res).getDimensionPixelSize(R.dimen.navigation_bar_width);
         doReturn(navMoves).when(res).getBoolean(R.bool.config_navBarCanMove);
-        doReturn(statusLand).when(res).getDimensionPixelSize(R.dimen.status_bar_height_landscape);
-        doReturn(statusPort).when(res).getDimensionPixelSize(R.dimen.status_bar_height_portrait);
         doReturn(cfg).when(res).getConfiguration();
         return res;
     }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
index b4caeb5..73eebad 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/split/SplitLayoutTests.java
@@ -68,7 +68,8 @@
                 mSplitLayoutHandler,
                 mCallbacks,
                 mDisplayImeController,
-                mTaskOrganizer));
+                mTaskOrganizer,
+                false /* applyDismissingParallax */));
     }
 
     @Test
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
index 3c124ba..078e2b6 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/hidedisplaycutout/HideDisplayCutoutOrganizerTest.java
@@ -48,7 +48,6 @@
 import androidx.test.InstrumentationRegistry;
 import androidx.test.filters.SmallTest;
 
-import com.android.internal.R;
 import com.android.wm.shell.common.DisplayController;
 import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.ShellExecutor;
@@ -124,6 +123,7 @@
 
     @Test
     public void testEnableHideDisplayCutout() {
+        doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
         mOrganizer.enableHideDisplayCutout();
 
         verify(mOrganizer).registerOrganizer(DisplayAreaOrganizer.FEATURE_HIDE_DISPLAY_CUTOUT);
@@ -154,8 +154,7 @@
         doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
         doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
                 .getDisplayCutoutInsetsOfNaturalOrientation();
-        mContext.getOrCreateTestableResources().addOverride(
-                R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
+        doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
         doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation();
         mOrganizer.enableHideDisplayCutout();
 
@@ -173,8 +172,7 @@
         doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
         doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
                 .getDisplayCutoutInsetsOfNaturalOrientation();
-        mContext.getOrCreateTestableResources().addOverride(
-                R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape);
+        doReturn(mFakeStatusBarHeightLandscape).when(mOrganizer).getStatusBarHeight();
         doReturn(Surface.ROTATION_90).when(mDisplayLayout).rotation();
         mOrganizer.enableHideDisplayCutout();
 
@@ -192,8 +190,7 @@
         doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
         doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
                 .getDisplayCutoutInsetsOfNaturalOrientation();
-        mContext.getOrCreateTestableResources().addOverride(
-                R.dimen.status_bar_height_landscape, mFakeStatusBarHeightLandscape);
+        doReturn(mFakeStatusBarHeightLandscape).when(mOrganizer).getStatusBarHeight();
         doReturn(Surface.ROTATION_270).when(mDisplayLayout).rotation();
         mOrganizer.enableHideDisplayCutout();
 
@@ -211,8 +208,7 @@
         doReturn(mFakeDefaultBounds).when(mOrganizer).getDisplayBoundsOfNaturalOrientation();
         doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
                 .getDisplayCutoutInsetsOfNaturalOrientation();
-        mContext.getOrCreateTestableResources().addOverride(
-                R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
+        doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
         mOrganizer.enableHideDisplayCutout();
 
         // disable hide display cutout
@@ -230,8 +226,7 @@
         doReturn(200).when(mDisplayLayout).height();
         doReturn(mFakeDefaultCutoutInsets).when(mOrganizer)
                 .getDisplayCutoutInsetsOfNaturalOrientation();
-        mContext.getOrCreateTestableResources().addOverride(
-                R.dimen.status_bar_height_portrait, mFakeStatusBarHeightPortrait);
+        doReturn(mFakeStatusBarHeightPortrait).when(mOrganizer).getStatusBarHeight();
         doReturn(Surface.ROTATION_0).when(mDisplayLayout).rotation();
         mOrganizer.enableHideDisplayCutout();
         assertThat(mOrganizer.mCurrentDisplayBounds).isEqualTo(new Rect(0, 15, 100, 200));
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
index 2bcc45e..c972067 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/MainStageTests.java
@@ -25,10 +25,13 @@
 import android.view.SurfaceSession;
 import android.window.WindowContainerTransaction;
 
+import androidx.test.annotation.UiThreadTest;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
@@ -41,22 +44,24 @@
 /** Tests for {@link MainStage} */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public class MainStageTests {
+public class MainStageTests extends ShellTestCase {
     @Mock private ShellTaskOrganizer mTaskOrganizer;
     @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
     @Mock private SyncTransactionQueue mSyncQueue;
     @Mock private ActivityManager.RunningTaskInfo mRootTaskInfo;
     @Mock private SurfaceControl mRootLeash;
+    @Mock private IconProvider mIconProvider;
     private WindowContainerTransaction mWct = new WindowContainerTransaction();
     private SurfaceSession mSurfaceSession = new SurfaceSession();
     private MainStage mMainStage;
 
     @Before
+    @UiThreadTest
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mRootTaskInfo = new TestRunningTaskInfoBuilder().build();
-        mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks, mSyncQueue,
-                mSurfaceSession, null);
+        mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
+                mSyncQueue, mSurfaceSession, mIconProvider, null);
         mMainStage.onTaskAppeared(mRootTaskInfo, mRootLeash);
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
index 838aa81..1857faa 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SideStageTests.java
@@ -33,6 +33,7 @@
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
@@ -54,6 +55,7 @@
     @Mock private SyncTransactionQueue mSyncQueue;
     @Mock private ActivityManager.RunningTaskInfo mRootTask;
     @Mock private SurfaceControl mRootLeash;
+    @Mock private IconProvider mIconProvider;
     @Spy private WindowContainerTransaction mWct;
     private SurfaceSession mSurfaceSession = new SurfaceSession();
     private SideStage mSideStage;
@@ -64,7 +66,7 @@
         MockitoAnnotations.initMocks(this);
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mCallbacks,
-                mSyncQueue, mSurfaceSession, null);
+                mSyncQueue, mSurfaceSession, mIconProvider, null);
         mSideStage.onTaskAppeared(mRootTask, mRootLeash);
     }
 
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
index 05496b0..d5dee82 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/SplitTransitionTests.java
@@ -55,6 +55,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.RootTaskDisplayAreaOrganizer;
 import com.android.wm.shell.ShellTaskOrganizer;
 import com.android.wm.shell.ShellTestCase;
@@ -89,6 +90,7 @@
     @Mock private Transitions mTransitions;
     @Mock private SurfaceSession mSurfaceSession;
     @Mock private SplitscreenEventLogger mLogger;
+    @Mock private IconProvider mIconProvider;
     private SplitLayout mSplitLayout;
     private MainStage mMainStage;
     private SideStage mSideStage;
@@ -107,11 +109,13 @@
         doReturn(mockExecutor).when(mTransitions).getAnimExecutor();
         doReturn(mock(SurfaceControl.Transaction.class)).when(mTransactionPool).acquire();
         mSplitLayout = SplitTestUtils.createMockSplitLayout();
-        mMainStage = new MainStage(mTaskOrganizer, DEFAULT_DISPLAY, mock(
-                StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession, null);
+        mMainStage = new MainStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
+                StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+                mIconProvider, null);
         mMainStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
         mSideStage = new SideStage(mContext, mTaskOrganizer, DEFAULT_DISPLAY, mock(
-                StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession, null);
+                StageTaskListener.StageListenerCallbacks.class), mSyncQueue, mSurfaceSession,
+                mIconProvider, null);
         mSideStage.onTaskAppeared(new TestRunningTaskInfoBuilder().build(), createMockSurface());
         mStageCoordinator = new SplitTestUtils.TestStageCoordinator(mContext, DEFAULT_DISPLAY,
                 mSyncQueue, mRootTDAOrganizer, mTaskOrganizer, mMainStage, mSideStage,
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
index a5746a4..53d5076 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/splitscreen/StageTaskListenerTests.java
@@ -21,6 +21,8 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assume.assumeFalse;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.clearInvocations;
@@ -31,11 +33,15 @@
 import android.os.SystemProperties;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
+import android.window.WindowContainerTransaction;
 
+import androidx.test.annotation.UiThreadTest;
 import androidx.test.ext.junit.runners.AndroidJUnit4;
 import androidx.test.filters.SmallTest;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.ShellTaskOrganizer;
+import com.android.wm.shell.ShellTestCase;
 import com.android.wm.shell.TestRunningTaskInfoBuilder;
 import com.android.wm.shell.common.SyncTransactionQueue;
 
@@ -50,33 +56,43 @@
 /**
  * Tests for {@link StageTaskListener}
  * Build/Install/Run:
- *  atest WMShellUnitTests:StageTaskListenerTests
+ * atest WMShellUnitTests:StageTaskListenerTests
  */
 @SmallTest
 @RunWith(AndroidJUnit4.class)
-public final class StageTaskListenerTests {
+public final class StageTaskListenerTests extends ShellTestCase {
     private static final boolean ENABLE_SHELL_TRANSITIONS =
             SystemProperties.getBoolean("persist.debug.shell_transit", false);
 
-    @Mock private ShellTaskOrganizer mTaskOrganizer;
-    @Mock private StageTaskListener.StageListenerCallbacks mCallbacks;
-    @Mock private SyncTransactionQueue mSyncQueue;
-    @Mock private StageTaskUnfoldController mStageTaskUnfoldController;
-    @Captor private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
+    @Mock
+    private ShellTaskOrganizer mTaskOrganizer;
+    @Mock
+    private StageTaskListener.StageListenerCallbacks mCallbacks;
+    @Mock
+    private SyncTransactionQueue mSyncQueue;
+    @Mock
+    private IconProvider mIconProvider;
+    @Mock
+    private StageTaskUnfoldController mStageTaskUnfoldController;
+    @Captor
+    private ArgumentCaptor<SyncTransactionQueue.TransactionRunnable> mRunnableCaptor;
     private SurfaceSession mSurfaceSession = new SurfaceSession();
     private SurfaceControl mSurfaceControl;
     private ActivityManager.RunningTaskInfo mRootTask;
     private StageTaskListener mStageTaskListener;
 
     @Before
+    @UiThreadTest
     public void setup() {
         MockitoAnnotations.initMocks(this);
         mStageTaskListener = new StageTaskListener(
+                mContext,
                 mTaskOrganizer,
                 DEFAULT_DISPLAY,
                 mCallbacks,
                 mSyncQueue,
                 mSurfaceSession,
+                mIconProvider,
                 mStageTaskUnfoldController);
         mRootTask = new TestRunningTaskInfoBuilder().build();
         mRootTask.parentTaskId = INVALID_TASK_ID;
@@ -167,4 +183,18 @@
         mStageTaskListener.onTaskInfoChanged(childTask);
         verify(mCallbacks).onNoLongerSupportMultiWindow();
     }
+
+    @Test
+    public void testEvictAllChildren() {
+        final WindowContainerTransaction wct = new WindowContainerTransaction();
+        mStageTaskListener.evictAllChildren(wct);
+        assertTrue(wct.isEmpty());
+
+        final ActivityManager.RunningTaskInfo childTask =
+                new TestRunningTaskInfoBuilder().setParentTaskId(mRootTask.taskId).build();
+        mStageTaskListener.onTaskAppeared(childTask, mSurfaceControl);
+
+        mStageTaskListener.evictAllChildren(wct);
+        assertFalse(wct.isEmpty());
+    }
 }
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
index e5a8aa0..b866bf9 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/startingsurface/StartingSurfaceDrawerTests.java
@@ -69,6 +69,7 @@
 import androidx.test.filters.SmallTest;
 import androidx.test.platform.app.InstrumentationRegistry;
 
+import com.android.launcher3.icons.IconProvider;
 import com.android.wm.shell.common.HandlerExecutor;
 import com.android.wm.shell.common.ShellExecutor;
 import com.android.wm.shell.common.TransactionPool;
@@ -93,6 +94,8 @@
     @Mock
     private WindowManager mMockWindowManager;
     @Mock
+    private IconProvider mIconProvider;
+    @Mock
     private TransactionPool mTransactionPool;
 
     private final Handler mTestHandler = new Handler(Looper.getMainLooper());
@@ -105,8 +108,8 @@
         int mAddWindowForTask = 0;
 
         TestStartingSurfaceDrawer(Context context, ShellExecutor splashScreenExecutor,
-                TransactionPool pool) {
-            super(context, splashScreenExecutor, pool);
+                IconProvider iconProvider, TransactionPool pool) {
+            super(context, splashScreenExecutor, iconProvider, pool);
         }
 
         @Override
@@ -156,7 +159,8 @@
         doNothing().when(mMockWindowManager).addView(any(), any());
         mTestExecutor = new HandlerExecutor(mTestHandler);
         mStartingSurfaceDrawer = spy(
-                new TestStartingSurfaceDrawer(mTestContext, mTestExecutor, mTransactionPool));
+                new TestStartingSurfaceDrawer(mTestContext, mTestExecutor, mIconProvider,
+                        mTransactionPool));
     }
 
     @Test
diff --git a/media/java/android/media/IMediaRouterService.aidl b/media/java/android/media/IMediaRouterService.aidl
index 48289ec..25b582d 100644
--- a/media/java/android/media/IMediaRouterService.aidl
+++ b/media/java/android/media/IMediaRouterService.aidl
@@ -39,6 +39,7 @@
     MediaRouterClientState getState(IMediaRouterClient client);
     boolean isPlaybackActive(IMediaRouterClient client);
 
+    void setBluetoothA2dpOn(IMediaRouterClient client, boolean on);
     void setDiscoveryRequest(IMediaRouterClient client, int routeTypes, boolean activeScan);
     void setSelectedRoute(IMediaRouterClient client, String routeId, boolean explicit);
     void requestSetVolume(IMediaRouterClient client, String routeId, int volume);
diff --git a/media/java/android/media/MediaFormat.java b/media/java/android/media/MediaFormat.java
index 028ae2b3..0847be3 100644
--- a/media/java/android/media/MediaFormat.java
+++ b/media/java/android/media/MediaFormat.java
@@ -693,7 +693,7 @@
      * <p>This key is only used during decoding.
      */
     public static final String KEY_MAX_OUTPUT_CHANNEL_COUNT =
-            "max-output-channel_count";
+            "max-output-channel-count";
 
     /**
      * A key describing the number of frames to trim from the start of the decoded audio stream.
diff --git a/media/java/android/media/MediaRouter.java b/media/java/android/media/MediaRouter.java
index 345d9b2..748ae52 100644
--- a/media/java/android/media/MediaRouter.java
+++ b/media/java/android/media/MediaRouter.java
@@ -1087,7 +1087,8 @@
                 && (types & ROUTE_TYPE_LIVE_AUDIO) != 0
                 && (route.isBluetooth() || route.isDefault())) {
             try {
-                sStatic.mAudioService.setBluetoothA2dpOn(route.isBluetooth());
+                sStatic.mMediaRouterService.setBluetoothA2dpOn(sStatic.mClient,
+                        route.isBluetooth());
             } catch (RemoteException e) {
                 Log.e(TAG, "Error changing Bluetooth A2DP state", e);
             }
diff --git a/packages/SettingsLib/res/values-as/strings.xml b/packages/SettingsLib/res/values-as/strings.xml
index eafa87b..75f7c5e5 100644
--- a/packages/SettingsLib/res/values-as/strings.xml
+++ b/packages/SettingsLib/res/values-as/strings.xml
@@ -73,14 +73,14 @@
     <string name="bluetooth_connected_no_a2dp" msgid="8566874395813947092">"সংযোগ কৰা হ’ল (মিডিয়া নাই)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_map" msgid="3381860077002724689">"সংযোগ কৰা হ’ল (বাৰ্তাত প্ৰৱেশাধিকাৰ নাই)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
     <string name="bluetooth_connected_no_headset_no_a2dp" msgid="2893204819854215433">"সংযোগ কৰা হ’ল (কোনো ফ\'ন বা মিডিয়া নাই)<xliff:g id="ACTIVE_DEVICE">%1$s</xliff:g>"</string>
-    <string name="bluetooth_connected_battery_level" msgid="5410325759372259950">"সংযোগ কৰা হ’ল, বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"সংযোগ কৰা হ’ল (ফ\'ন নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"সংযোগ কৰা হ’ল (মিডিয়া নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"সংযোগ কৰা হ’ল (কোনো ফ\'ন বা মিডিয়া নাই), বেটাৰিৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
-    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"সক্ৰিয়, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি"</string>
-    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"সক্ৰিয়, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰি, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰি"</string>
+    <string name="bluetooth_connected_battery_level" msgid="5410325759372259950">"সংযোগ কৰা হ’ল, বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_battery_level" msgid="2661863370509206428">"সংযোগ কৰা হ’ল (ফ\'ন নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_a2dp_battery_level" msgid="6499078454894324287">"সংযোগ কৰা হ’ল (মিডিয়া নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_connected_no_headset_no_a2dp_battery_level" msgid="8477440576953067242">"সংযোগ কৰা হ’ল (কোনো ফ\'ন বা মিডিয়া নাই), বেটাৰীৰ স্তৰ <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g><xliff:g id="ACTIVE_DEVICE">%2$s</xliff:g>"</string>
+    <string name="bluetooth_active_battery_level" msgid="3450745316700494425">"সক্ৰিয়, <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
+    <string name="bluetooth_active_battery_level_untethered" msgid="2706188607604205362">"সক্ৰিয়, L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰী, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string>
     <string name="bluetooth_battery_level" msgid="2893696778200201555">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী"</string>
-    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰি, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰি"</string>
+    <string name="bluetooth_battery_level_untethered" msgid="4002282355111504349">"L: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_0">%1$s</xliff:g> বেটাৰী, R: <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE_1">%2$s</xliff:g> বেটাৰী"</string>
     <string name="bluetooth_active_no_battery_level" msgid="4155462233006205630">"সক্ৰিয়"</string>
     <string name="bluetooth_profile_a2dp" msgid="4632426382762851724">"মিডিয়াৰ অডিঅ’"</string>
     <string name="bluetooth_profile_headset" msgid="5395952236133499331">"ফ\'ন কলসমূহ"</string>
@@ -130,8 +130,8 @@
     <string name="bluetooth_talkback_bluetooth" msgid="1143241359781999989">"ব্লুটুথ"</string>
     <string name="bluetooth_hearingaid_left_pairing_message" msgid="8561855779703533591">"বাওঁফালৰ শ্ৰৱণ যন্ত্ৰটো যোৰ পতোৱা হৈছে…"</string>
     <string name="bluetooth_hearingaid_right_pairing_message" msgid="2655347721696331048">"সোঁফালৰ শ্ৰৱণ যন্ত্ৰটো যোৰ পতোৱা হৈছে…"</string>
-    <string name="bluetooth_hearingaid_left_battery_level" msgid="7375621694748104876">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰি বাকী আছে"</string>
-    <string name="bluetooth_hearingaid_right_battery_level" msgid="1850094448499089312">"সোঁ - বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="bluetooth_hearingaid_left_battery_level" msgid="7375621694748104876">"<xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g> বেটাৰী বাকী আছে"</string>
+    <string name="bluetooth_hearingaid_right_battery_level" msgid="1850094448499089312">"সোঁ - বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="accessibility_wifi_off" msgid="1195445715254137155">"ৱাই-ফাই অফ হৈ আছে।"</string>
     <string name="accessibility_no_wifi" msgid="5297119459491085771">"ৱাইফাই সংযোগ বিচ্ছিন্ন হৈ আছে।"</string>
     <string name="accessibility_wifi_one_bar" msgid="6025652717281815212">"ৱাই-ফাই এদাল দণ্ড।"</string>
@@ -289,7 +289,7 @@
     <string name="wifi_unmetered_label" msgid="6174142840934095093">"নিৰিখ অনিৰ্দিষ্ট"</string>
     <string name="select_logd_size_title" msgid="1604578195914595173">"লগাৰৰ বাফাৰৰ আকাৰ"</string>
     <string name="select_logd_size_dialog_title" msgid="2105401994681013578">"প্ৰতিটো লগ বাফাৰত ল\'গাৰৰ আকাৰ বাছনি কৰক"</string>
-    <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"লগাৰৰ স্থায়ী সঞ্চয়াগাৰৰ বস্তুবোৰ মচিবনে?"</string>
+    <string name="dev_logpersist_clear_warning_title" msgid="8631859265777337991">"লগাৰৰ স্থায়ী ষ্ট’ৰেজৰ বস্তুবোৰ মচিবনে?"</string>
     <string name="dev_logpersist_clear_warning_message" msgid="6447590867594287413">"পাৰ্ছিছটেণ্ট লগাৰ ব্যৱহাৰ কৰ নিৰীক্ষণ নকৰাৰ সময়ত, আমি আপোনাৰ ডিভাইচত থকা লগাৰ ডেটা নিৱাসীক মচা দৰকাৰ।"</string>
     <string name="select_logpersist_title" msgid="447071974007104196">"ডিভাইচটোত লগাৰৰ ডেটা নিৰবচ্ছিন্নভাৱে সঞ্চয় কৰক"</string>
     <string name="select_logpersist_dialog_title" msgid="7745193591195485594">"ডিভাইচত স্থায়ীভাৱে সঞ্চয় কৰিবলৈ লগ বাফাৰবোৰ বাছনি কৰক"</string>
@@ -375,7 +375,7 @@
     <string name="show_notification_channel_warnings" msgid="3448282400127597331">"জাননী চ্চেনেলৰ সকীয়নিসমূহ দেখুৱাওক"</string>
     <string name="show_notification_channel_warnings_summary" msgid="68031143745094339">"কোনো এপে বৈধ চ্চেনেল নোহোৱাকৈ কোনো জাননী প\'ষ্ট কৰিলে স্ক্ৰীনত সকীয়নি প্ৰদৰ্শন হয়"</string>
     <string name="force_allow_on_external" msgid="9187902444231637880">"বাহ্যিক সঞ্চয়াগাৰত এপক বলেৰে অনুমতি দিয়ক"</string>
-    <string name="force_allow_on_external_summary" msgid="8525425782530728238">"মেনিফেষ্টৰ মান যিয়েই নহওক, বাহ্যিক সঞ্চয়াগাৰত লিখিবলৈ যিকোনো এপক উপযুক্ত কৰি তোলে"</string>
+    <string name="force_allow_on_external_summary" msgid="8525425782530728238">"মেনিফেষ্টৰ মান যিয়েই নহওক, বাহ্যিক ষ্ট’ৰেজত লিখিবলৈ যিকোনো এপক উপযুক্ত কৰি তোলে"</string>
     <string name="force_resizable_activities" msgid="7143612144399959606">"বলেৰে কাৰ্যকলাপসমূহৰ আকাৰ সলনি কৰিব পৰা কৰক"</string>
     <string name="force_resizable_activities_summary" msgid="2490382056981583062">"মেনিফেষ্টৰ মান যিয়েই নহওক, মাল্টি-ৱিণ্ডৰ বাবে সকলো কাৰ্যকলাপৰ আকাৰ সলনি কৰিব পৰা কৰক।"</string>
     <string name="enable_freeform_support" msgid="7599125687603914253">"ফ্ৰিফৰ্ম ৱিণ্ড\'জ সক্ষম কৰক"</string>
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
index fe92e26..7beb824 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/CachedBluetoothDevice.java
@@ -106,6 +106,7 @@
     private boolean mIsA2dpProfileConnectedFail = false;
     private boolean mIsHeadsetProfileConnectedFail = false;
     private boolean mIsHearingAidProfileConnectedFail = false;
+    private boolean mUnpairing = false;
     // Group second device for Hearing Aid
     private CachedBluetoothDevice mSubDevice;
     @VisibleForTesting
@@ -402,6 +403,7 @@
         if (state != BluetoothDevice.BOND_NONE) {
             final BluetoothDevice dev = mDevice;
             if (dev != null) {
+                mUnpairing = true;
                 final boolean successful = dev.removeBond();
                 if (successful) {
                     releaseLruCache();
@@ -1243,4 +1245,8 @@
     void releaseLruCache() {
         mDrawableCache.evictAll();
     }
+
+    boolean getUnpairing() {
+        return mUnpairing;
+    }
 }
diff --git a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
index 20ece69..818f5ca 100644
--- a/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
+++ b/packages/SettingsLib/src/com/android/settingslib/bluetooth/HearingAidDeviceManager.java
@@ -180,6 +180,9 @@
                 break;
             case BluetoothProfile.STATE_DISCONNECTED:
                 mainDevice = findMainDevice(cachedDevice);
+                if (cachedDevice.getUnpairing()) {
+                    return true;
+                }
                 if (mainDevice != null) {
                     // When main device exists, receiving sub device disconnection
                     // To update main device UI
diff --git a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
index 274696b..468aa05 100644
--- a/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
+++ b/packages/SettingsLib/src/com/android/settingslib/drawable/UserIconDrawable.java
@@ -183,6 +183,20 @@
         return setBadge(badge);
     }
 
+    /**
+     * Sets the managed badge to this user icon if the device has a device owner.
+     */
+    public UserIconDrawable setBadgeIfManagedDevice(Context context) {
+        Drawable badge = null;
+        boolean deviceOwnerExists = context.getSystemService(DevicePolicyManager.class)
+                .getDeviceOwnerComponentOnAnyUser() != null;
+        if (deviceOwnerExists) {
+            badge = getDrawableForDisplayDensity(
+                    context, com.android.internal.R.drawable.ic_corp_badge_case);
+        }
+        return setBadge(badge);
+    }
+
     public void setBadgeRadius(float radius) {
         mBadgeRadius = radius;
         onBoundsChange(getBounds());
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
index c2b3608..669a054 100644
--- a/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/DialogLaunchAnimator.kt
@@ -21,11 +21,16 @@
 import android.graphics.Color
 import android.os.Looper
 import android.util.Log
+import android.view.GhostView
 import android.view.Gravity
 import android.view.View
 import android.view.ViewGroup
-import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.OnPreDrawListener
+import android.view.WindowInsets
 import android.view.WindowManager
+import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR
+import android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+import android.view.WindowManagerPolicyConstants
 import android.widget.FrameLayout
 
 private const val TAG = "DialogLaunchAnimator"
@@ -221,10 +226,12 @@
     private var isDismissing = false
 
     private var dismissRequested = false
-    private var drawHostDialog = false
     var ignoreNextCallToHide = false
     var exitAnimationDisabled = false
 
+    private var isTouchSurfaceGhostDrawn = false
+    private var isOriginalDialogViewLaidOut = false
+
     fun start() {
         // Show the host (fullscreen) dialog, to which we will add the stolen dialog view.
         hostDialog.show()
@@ -252,19 +259,76 @@
             WindowManager.LayoutParams.MATCH_PARENT
         )
 
-        // Prevent the host dialog from drawing until the animation starts.
-        hostDialogRoot.viewTreeObserver.addOnPreDrawListener(
-            object : ViewTreeObserver.OnPreDrawListener {
-                override fun onPreDraw(): Boolean {
-                    if (drawHostDialog) {
-                        hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this)
-                        return true
-                    }
+        // If we are using gesture navigation, then we can overlay the navigation/task bars with
+        // the host dialog.
+        val navigationMode = context.resources.getInteger(
+            com.android.internal.R.integer.config_navBarInteractionMode)
+        if (navigationMode == WindowManagerPolicyConstants.NAV_BAR_MODE_GESTURAL) {
+            window.attributes.fitInsetsTypes = window.attributes.fitInsetsTypes and
+                WindowInsets.Type.navigationBars().inv()
+            window.addFlags(FLAG_LAYOUT_IN_SCREEN or FLAG_LAYOUT_INSET_DECOR)
+            window.setDecorFitsSystemWindows(false)
+        }
 
-                    return false
-                }
+        // Disable the dim. We will enable it once we start the animation.
+        window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+        // Add a temporary touch surface ghost as soon as the window is ready to draw. This
+        // temporary ghost will be drawn together with the touch surface, but in the host dialog
+        // window. Once it is drawn, we will make the touch surface invisible, and then start the
+        // animation. We do all this synchronization to avoid flicker that would occur if we made
+        // the touch surface invisible too early (before its ghost is drawn), leading to one or more
+        // frames with a hole instead of the touch surface (or its ghost).
+        hostDialogRoot.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+            override fun onPreDraw(): Boolean {
+                hostDialogRoot.viewTreeObserver.removeOnPreDrawListener(this)
+                addTemporaryTouchSurfaceGhost()
+                return true
             }
-        )
+        })
+        hostDialogRoot.invalidate()
+    }
+
+    private fun addTemporaryTouchSurfaceGhost() {
+        // Create a ghost of the touch surface (which will make the touch surface invisible) and add
+        // it to the host dialog. We will wait for this ghost to be drawn before starting the
+        // animation.
+        val ghost = GhostView.addGhost(touchSurface, hostDialogRoot)
+
+        // The ghost of the touch surface was just created, so the touch surface was made invisible.
+        // We make it visible again until the ghost is actually drawn.
+        touchSurface.visibility = View.VISIBLE
+
+        // Wait for the ghost to be drawn before continuing.
+        ghost.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+            override fun onPreDraw(): Boolean {
+                ghost.viewTreeObserver.removeOnPreDrawListener(this)
+                onTouchSurfaceGhostDrawn()
+                return true
+            }
+        })
+        ghost.invalidate()
+    }
+
+    private fun onTouchSurfaceGhostDrawn() {
+        // Make the touch surface invisible and make sure that it stays invisible as long as the
+        // dialog is shown or animating.
+        touchSurface.visibility = View.INVISIBLE
+        if (touchSurface is LaunchableView) {
+            touchSurface.setShouldBlockVisibilityChanges(true)
+        }
+
+        // Add a pre draw listener to (maybe) start the animation once the touch surface is
+        // actually invisible.
+        touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+            override fun onPreDraw(): Boolean {
+                touchSurface.viewTreeObserver.removeOnPreDrawListener(this)
+                isTouchSurfaceGhostDrawn = true
+                maybeStartLaunchAnimation()
+                return true
+            }
+        })
+        touchSurface.invalidate()
     }
 
     /** Get the content view of [originalDialog] and pass it to [then]. */
@@ -276,7 +340,7 @@
             ?: throw IllegalStateException("Dialog does not have any android.R.id.content view")
 
         androidContent.viewTreeObserver.addOnPreDrawListener(
-            object : ViewTreeObserver.OnPreDrawListener {
+            object : OnPreDrawListener {
                 override fun onPreDraw(): Boolean {
                     if (androidContent.childCount == 1) {
                         androidContent.viewTreeObserver.removeOnPreDrawListener(this)
@@ -354,32 +418,47 @@
                 oldBottom: Int
             ) {
                 dialogView.removeOnLayoutChangeListener(this)
-                startAnimation(
-                    isLaunching = true,
-                    onLaunchAnimationStart = { drawHostDialog = true },
-                    onLaunchAnimationEnd = {
-                        touchSurface.setTag(R.id.launch_animation_running, null)
 
-                        // We hide the touch surface when the dialog is showing. We will make this
-                        // view visible again when dismissing the dialog.
-                        // TODO(b/193634619): Provide an easy way for views to check if they should
-                        // be hidden because of a dialog launch so that they don't override this
-                        // visibility when updating/refreshing itself.
-                        touchSurface.visibility = View.INVISIBLE
-
-                        isLaunching = false
-
-                        // dismiss was called during the animation, dismiss again now to actually
-                        // dismiss.
-                        if (dismissRequested) {
-                            hostDialog.dismiss()
-                        }
-                    }
-                )
+                isOriginalDialogViewLaidOut = true
+                maybeStartLaunchAnimation()
             }
         })
     }
 
+    private fun maybeStartLaunchAnimation() {
+        if (!isTouchSurfaceGhostDrawn || !isOriginalDialogViewLaidOut) {
+            return
+        }
+
+        // Show the background dim.
+        hostDialog.window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
+
+        startAnimation(
+            isLaunching = true,
+            onLaunchAnimationStart = {
+                // Remove the temporary ghost. Another ghost (that ghosts only the touch surface
+                // content, and not its background) will be added right after this and will be
+                // animated.
+                GhostView.removeGhost(touchSurface)
+            },
+            onLaunchAnimationEnd = {
+                touchSurface.setTag(R.id.launch_animation_running, null)
+
+                // We hide the touch surface when the dialog is showing. We will make this
+                // view visible again when dismissing the dialog.
+                touchSurface.visibility = View.INVISIBLE
+
+                isLaunching = false
+
+                // dismiss was called during the animation, dismiss again now to actually
+                // dismiss.
+                if (dismissRequested) {
+                    hostDialog.dismiss()
+                }
+            }
+        )
+    }
+
     private fun onHostDialogDismissed(actualDismiss: () -> Unit) {
         if (Looper.myLooper() != Looper.getMainLooper()) {
             context.mainExecutor.execute { onHostDialogDismissed(actualDismiss) }
@@ -417,6 +496,11 @@
         if (!shouldAnimateDialogIntoView()) {
             Log.i(TAG, "Skipping animation of dialog into the touch surface")
 
+            // Make sure we allow the touch surface to change its visibility again.
+            if (touchSurface is LaunchableView) {
+                touchSurface.setShouldBlockVisibilityChanges(false)
+            }
+
             // If the view is invisible it's probably because of us, so we make it visible again.
             if (touchSurface.visibility == View.INVISIBLE) {
                 touchSurface.visibility = View.VISIBLE
@@ -434,10 +518,33 @@
                 hostDialog.window.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND)
             },
             onLaunchAnimationEnd = {
+                // Make sure we allow the touch surface to change its visibility again.
+                if (touchSurface is LaunchableView) {
+                    touchSurface.setShouldBlockVisibilityChanges(false)
+                }
+
                 touchSurface.visibility = View.VISIBLE
                 originalDialogView!!.visibility = View.INVISIBLE
-                dismissDialogs(true /* instantDismiss */)
-                onDialogDismissed(this@DialogLaunchAnimation)
+
+                // The animated ghost was just removed. We create a temporary ghost that will be
+                // removed only once we draw the touch surface, to avoid flickering that would
+                // happen when removing the ghost too early (before the touch surface is drawn).
+                GhostView.addGhost(touchSurface, hostDialogRoot)
+
+                touchSurface.viewTreeObserver.addOnPreDrawListener(object : OnPreDrawListener {
+                    override fun onPreDraw(): Boolean {
+                        touchSurface.viewTreeObserver.removeOnPreDrawListener(this)
+
+                        // Now that the touch surface was drawn, we can remove the temporary ghost
+                        // and instantly dismiss the dialog.
+                        GhostView.removeGhost(touchSurface)
+                        dismissDialogs(true /* instantDismiss */)
+                        onDialogDismissed(this@DialogLaunchAnimation)
+
+                        return true
+                    }
+                })
+                touchSurface.invalidate()
             }
         )
     }
@@ -472,10 +579,13 @@
             }
 
             override fun onLaunchAnimationStart(isExpandingFullyAbove: Boolean) {
+                // During launch, onLaunchAnimationStart will be used to remove the temporary touch
+                // surface ghost so it is important to call this before calling
+                // onLaunchAnimationStart on the controller (which will create its own ghost).
+                onLaunchAnimationStart()
+
                 startViewController.onLaunchAnimationStart(isExpandingFullyAbove)
                 endViewController.onLaunchAnimationStart(isExpandingFullyAbove)
-
-                onLaunchAnimationStart()
             }
 
             override fun onLaunchAnimationEnd(isExpandingFullyAbove: Boolean) {
diff --git a/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
new file mode 100644
index 0000000..80a3eb8
--- /dev/null
+++ b/packages/SystemUI/animation/src/com/android/systemui/animation/LaunchableView.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 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.animation
+
+/** A view that can expand/launch into an app or a dialog. */
+interface LaunchableView {
+    /**
+     * Set whether this view should block/prevent all visibility changes. This ensures that this
+     * view remains invisible during the launch animation given that it is ghosted and already drawn
+     * somewhere else.
+     *
+     * Note that when this is set to true, both the [normal][android.view.View.setVisibility] and
+     * [transition][android.view.View.setTransitionVisibility] visibility changes must be blocked.
+     */
+    fun setShouldBlockVisibilityChanges(block: Boolean)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index 989010e..a16f5cd 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -123,18 +123,18 @@
 
     /** Interface for launching Intents, which can differ on the lockscreen */
     interface IntentStarter {
-        default void startFromAction(SmartspaceAction action, View v) {
+        default void startFromAction(SmartspaceAction action, View v, boolean showOnLockscreen) {
             if (action.getIntent() != null) {
-                startIntent(v, action.getIntent());
+                startIntent(v, action.getIntent(), showOnLockscreen);
             } else if (action.getPendingIntent() != null) {
-                startPendingIntent(action.getPendingIntent());
+                startPendingIntent(action.getPendingIntent(), showOnLockscreen);
             }
         }
 
         /** Start the intent */
-        void startIntent(View v, Intent i);
+        void startIntent(View v, Intent i, boolean showOnLockscreen);
 
         /** Start the PendingIntent */
-        void startPendingIntent(PendingIntent pi);
+        void startPendingIntent(PendingIntent pi, boolean showOnLockscreen);
     }
 }
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
index 757dc2e..b83ea4a 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/qs/QS.java
@@ -55,13 +55,14 @@
 
     /**
      * Asks QS to update its presentation, according to {@code NotificationPanelViewController}.
-     *
      * @param qsExpansionFraction How much each UI element in QS should be expanded (QQS to QS.)
      * @param panelExpansionFraction Whats the expansion of the whole shade.
      * @param headerTranslation How much we should vertically translate QS.
+     * @param squishinessFraction Fraction that affects tile height. 0 when collapsed,
+     *                            1 when expanded.
      */
     void setQsExpansion(float qsExpansionFraction, float panelExpansionFraction,
-            float headerTranslation);
+            float headerTranslation, float squishinessFraction);
     void setHeaderListening(boolean listening);
     void notifyCustomizeChanged();
     void setContainerController(QSContainerController controller);
diff --git a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
index 883f4de..94fdbae 100644
--- a/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
+++ b/packages/SystemUI/plugin/src/com/android/systemui/plugins/statusbar/NotificationMenuRowPlugin.java
@@ -183,12 +183,6 @@
     public boolean canBeDismissed();
 
     /**
-     * Informs the menu whether dismiss gestures are left-to-right or right-to-left.
-     */
-    default void setDismissRtl(boolean dismissRtl) {
-    }
-
-    /**
      * Determines whether the menu should remain open given its current state, or snap closed.
      * @return true if the menu should remain open, false otherwise.
      */
diff --git a/packages/SystemUI/proguard.flags b/packages/SystemUI/proguard.flags
index 4adb546..6114728 100644
--- a/packages/SystemUI/proguard.flags
+++ b/packages/SystemUI/proguard.flags
@@ -37,9 +37,6 @@
 -keep class com.android.systemui.fragments.FragmentService$FragmentCreator {
     *;
 }
--keep class com.android.systemui.util.InjectionInflationController$ViewInstanceCreator {
-    *;
-}
 -keep class androidx.core.app.CoreComponentFactory
 
 -keep public class * extends com.android.systemui.SystemUI {
diff --git a/packages/SystemUI/res-keyguard/drawable/face_auth_wallpaper.png b/packages/SystemUI/res-keyguard/drawable/face_auth_wallpaper.png
deleted file mode 100644
index b907f4e..0000000
--- a/packages/SystemUI/res-keyguard/drawable/face_auth_wallpaper.png
+++ /dev/null
Binary files differ
diff --git a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
index 7f0f68f..c58e2e3 100644
--- a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
+++ b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
@@ -37,7 +37,7 @@
         android:id="@+id/locked_fp"
         android:state_middle="true"
         android:state_single="false"
-        android:drawable="@drawable/ic_fingerprint" />
+        android:drawable="@drawable/ic_kg_fingerprint" />
 
     <item
         android:id="@+id/unlocked"
diff --git a/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml b/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml
index d816b3a..17765b5 100644
--- a/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml
+++ b/packages/SystemUI/res-keyguard/values-sw600dp-land/dimens.xml
@@ -23,6 +23,6 @@
     <dimen name="widget_big_font_size">88dp</dimen>
 
     <dimen name="qs_header_system_icons_area_height">0dp</dimen>
-    <dimen name="qs_panel_padding_top">0dp</dimen>
+    <dimen name="qs_panel_padding_top">@dimen/qqs_layout_margin_top</dimen>
 
 </resources>
\ No newline at end of file
diff --git a/packages/SystemUI/res-product/values-te/strings.xml b/packages/SystemUI/res-product/values-te/strings.xml
index 1773f90..511e095 100644
--- a/packages/SystemUI/res-product/values-te/strings.xml
+++ b/packages/SystemUI/res-product/values-te/strings.xml
@@ -38,8 +38,8 @@
     <string name="kg_failed_attempts_almost_at_erase_profile" product="default" msgid="3280816298678433681">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="tablet" msgid="4417100487251371559">"మీరు టాబ్లెట్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
     <string name="kg_failed_attempts_now_erasing_profile" product="default" msgid="4682221342671290678">"మీరు ఫోన్‌ను అన్‌లాక్ చేయడానికి <xliff:g id="NUMBER">%d</xliff:g> సార్లు తప్పు ప్రయత్నాలు చేశారు. కార్యాలయ ప్రొఫైల్ తీసివేయబడుతుంది, దీని వలన ప్రొఫైల్ డేటా మొత్తం తొలగించబడుతుంది."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఇమెయిల్ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
-    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఇమెయిల్ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="tablet" msgid="1860049973474855672">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ టాబ్లెట్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
+    <string name="kg_failed_attempts_almost_at_login" product="default" msgid="44112553371516141">"మీరు మీ అన్‌లాక్ నమూనాను <xliff:g id="NUMBER_0">%1$d</xliff:g> సార్లు తప్పుగా గీసారు. మరో <xliff:g id="NUMBER_1">%2$d</xliff:g> ప్రయత్నాలలో విఫలమైతే, మీరు ఈమెయిల్‌ ఖాతాను ఉపయోగించి మీ ఫోన్‌ను అన్‌లాక్ చేయాల్సి వస్తుంది.\n\n <xliff:g id="NUMBER_2">%3$d</xliff:g> సెకన్లలో మళ్లీ ప్రయత్నించండి."</string>
     <string name="global_action_lock_message" product="default" msgid="7092460751050168771">"మరిన్ని ఆప్షన్‌ల కోసం మీ ఫోన్‌ను అన్‌లాక్ చేయండి"</string>
     <string name="global_action_lock_message" product="tablet" msgid="1024230056230539493">"మరిన్ని ఆప్షన్‌ల కోసం మీ టాబ్లెట్‌ను అన్‌లాక్ చేయండి"</string>
     <string name="global_action_lock_message" product="device" msgid="3165224897120346096">"మరిన్ని ఆప్షన్‌ల కోసం మీ పరికరాన్ని అన్‌లాక్ చేయండి"</string>
diff --git a/packages/SystemUI/res/drawable/ic_fingerprint.xml b/packages/SystemUI/res/drawable/ic_kg_fingerprint.xml
similarity index 100%
rename from packages/SystemUI/res/drawable/ic_fingerprint.xml
rename to packages/SystemUI/res/drawable/ic_kg_fingerprint.xml
diff --git a/packages/SystemUI/res/drawable/internet_dialog_background.xml b/packages/SystemUI/res/drawable/internet_dialog_background.xml
deleted file mode 100644
index 3ceb0f6..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_background.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
-    <shape android:shape="rectangle">
-        <corners android:radius="8dp" />
-        <solid android:color="?android:attr/colorBackground" />
-    </shape>
-</inset>
diff --git a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml b/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml
deleted file mode 100644
index 14672ef..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_rounded_top_corner_background.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright (C) 2021 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.
--->
-<inset xmlns:android="http://schemas.android.com/apk/res/android">
-    <shape android:shape="rectangle">
-        <corners
-            android:topLeftRadius="@dimen/internet_dialog_corner_radius"
-            android:topRightRadius="@dimen/internet_dialog_corner_radius"
-            android:bottomLeftRadius="@dimen/internet_dialog_corner_radius"
-            android:bottomRightRadius="@dimen/internet_dialog_corner_radius"/>
-        <solid android:color="?android:attr/colorBackground" />
-    </shape>
-</inset>
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index c1d7308b..f4faa62 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -20,8 +20,7 @@
     xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
     android:id="@+id/internet_connectivity_dialog"
     android:layout_width="@dimen/large_dialog_width"
-    android:layout_height="@dimen/internet_dialog_list_max_height"
-    android:background="@drawable/internet_dialog_rounded_top_corner_background"
+    android:layout_height="wrap_content"
     android:orientation="vertical">
 
     <LinearLayout
@@ -323,6 +322,46 @@
                 </FrameLayout>
             </LinearLayout>
 
+            <LinearLayout
+                android:id="@+id/wifi_scan_notify_layout"
+                style="@style/InternetDialog.Network"
+                android:orientation="vertical"
+                android:layout_height="wrap_content"
+                android:paddingBottom="4dp"
+                android:clickable="false"
+                android:focusable="false">
+
+                <LinearLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:minWidth="56dp"
+                    android:gravity="start|top"
+                    android:orientation="horizontal"
+                    android:paddingEnd="12dp"
+                    android:paddingTop="16dp"
+                    android:paddingBottom="4dp">
+                    <ImageView
+                        android:src="@drawable/ic_info_outline"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:tint="?android:attr/textColorTertiary"/>
+                </LinearLayout>
+
+                <LinearLayout
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:orientation="vertical">
+                    <TextView
+                        android:id="@+id/wifi_scan_notify_text"
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
+                        android:paddingTop="16dp"
+                        android:paddingBottom="8dp"
+                        android:textColor="?android:attr/textColorSecondary"
+                        android:clickable="true"/>
+                </LinearLayout>
+            </LinearLayout>
+
             <FrameLayout
                 android:id="@+id/done_layout"
                 android:layout_width="67dp"
diff --git a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
index 6b14c96..10a2f4c 100644
--- a/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
+++ b/packages/SystemUI/res/layout/quick_status_bar_expanded_header.xml
@@ -63,7 +63,7 @@
                 android:id="@+id/qqs_footer_actions"
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:layout_marginTop="16dp"
+                android:layout_marginTop="@dimen/qqs_layout_margin_top"
                 android:layout_marginStart="@dimen/qs_footer_margin"
                 android:layout_marginEnd="@dimen/qs_footer_margin"
                 />
diff --git a/packages/SystemUI/res/layout/super_notification_shade.xml b/packages/SystemUI/res/layout/super_notification_shade.xml
index e02a1767..b28cb2f 100644
--- a/packages/SystemUI/res/layout/super_notification_shade.xml
+++ b/packages/SystemUI/res/layout/super_notification_shade.xml
@@ -81,6 +81,7 @@
 
     <!-- Keyguard messages -->
     <LinearLayout
+        android:id="@+id/keyguard_message_area_container"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
         android:orientation="vertical"
diff --git a/packages/SystemUI/res/values-af/strings.xml b/packages/SystemUI/res/values-af/strings.xml
index ddb6b8f..0873a4f 100644
--- a/packages/SystemUI/res/values-af/strings.xml
+++ b/packages/SystemUI/res/values-af/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-fi sal vir nou nie outomaties koppel nie"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Sien alles"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ontkoppel Ethernet om netwerke te wissel"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Om toestelervaring te verbeter, kan programme en dienste steeds enige tyd na wi‑fi-netwerke soek, selfs wanneer wi‑fi af is. Jy kan dit in Wi-fi-opsporing-instellings verander. "<annotation id="link">"Verander"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kies gebruiker"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-am/strings.xml b/packages/SystemUI/res/values-am/strings.xml
index d56c3fd..579b5d2 100644
--- a/packages/SystemUI/res/values-am/strings.xml
+++ b/packages/SystemUI/res/values-am/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wifi ለአሁን በራስ-ሰር አይገናኝም"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ሁሉንም ይመልከቱ"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"አውታረ መረቦችን ለመቀየር፣ የኢተርኔት ግንኙነት ያቋርጡ"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"የመሣሪያ ተሞክሮን ለማሻሻል፣ መተግበሪያዎች እና አገልግሎቶች አሁንም በማንኛውም ጊዜ የWi-Fi አውታረ መረቦችን መቃኘት ይችላሉ፣ Wi-Fi ጠፍቶ ቢሆንም እንኳ። ይህንን በ Wi‑Fi ቅኝት ቅንብሮች ውስጥ መቀየር ይችላሉ። "<annotation id="link">"ቀይር"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ተጠቃሚን ይምረጡ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ar/strings.xml b/packages/SystemUI/res/values-ar/strings.xml
index 4f66356..5875d2b 100644
--- a/packages/SystemUI/res/values-ar/strings.xml
+++ b/packages/SystemUI/res/values-ar/strings.xml
@@ -1203,5 +1203,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"‏لن يتم الاتصال بشبكة Wi-Fi تلقائيًا في الوقت الحالي."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"عرض الكل"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"للتبديل بين الشبكات، يجب فصل إيثرنت."</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"‏لتحسين تجربتك على الجهاز، يظل بإمكان التطبيقات والخدمات البحث عن شبكات Wi‑Fi في أي وقت، حتى عند إيقاف شبكة Wi‑Fi. وبإمكانك تغيير هذا الخيار في إعدادات البحث عن شبكات Wi-Fi. "<annotation id="link">"تغيير"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"اختيار المستخدم"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-as/strings.xml b/packages/SystemUI/res/values-as/strings.xml
index 3015ccd..d6d2900 100644
--- a/packages/SystemUI/res/values-as/strings.xml
+++ b/packages/SystemUI/res/values-as/strings.xml
@@ -24,19 +24,19 @@
     <string name="status_bar_no_notifications_title" msgid="7812479124981107507">"কোনো জাননী নাই"</string>
     <string name="status_bar_ongoing_events_title" msgid="3986169317496615446">"চলিত"</string>
     <string name="status_bar_latest_events_title" msgid="202755896454005436">"জাননীসমূহ"</string>
-    <string name="battery_low_title" msgid="6891106956328275225">"বেটাৰি অতি সোনকালে শেষ হ\'ব পাৰে"</string>
+    <string name="battery_low_title" msgid="6891106956328275225">"বেটাৰী অতি সোনকালে শেষ হ\'ব পাৰে"</string>
     <string name="battery_low_percent_format" msgid="4276661262843170964">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে"</string>
     <string name="battery_low_percent_format_hybrid" msgid="3985614339605686167">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> অৱশিষ্ট আছে, আপোনাৰ ব্যৱহাৰক ভিত্তি কৰি প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
     <string name="battery_low_percent_format_hybrid_short" msgid="5917433188456218857">"<xliff:g id="PERCENTAGE">%1$s</xliff:g> অৱশিষ্ট আছে, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী"</string>
-    <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে। বেটাৰি সঞ্চয়কাৰী অন হৈ আছে।"</string>
+    <string name="battery_low_percent_format_saver_started" msgid="4968468824040940688">"<xliff:g id="PERCENTAGE">%s</xliff:g> বাকী আছে। বেটাৰী সঞ্চয়কাৰী অন হৈ আছে।"</string>
     <string name="invalid_charger" msgid="4370074072117767416">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি। আপোনাৰ ডিভাইচৰ লগত পোৱা চ্চাৰ্জাৰটো ব্যৱহাৰ কৰক।"</string>
     <string name="invalid_charger_title" msgid="938685362320735167">"ইউএছবি জৰিয়তে চ্চাৰ্জ কৰিব নোৱাৰি"</string>
     <string name="invalid_charger_text" msgid="2339310107232691577">"আপোনাৰ ডিভাইচৰ লগত পোৱা চ্চাৰ্জাৰটো ব্যৱহাৰ কৰক।"</string>
     <string name="battery_low_why" msgid="2056750982959359863">"ছেটিং"</string>
-    <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"বেটাৰি সঞ্চয়কাৰী অন কৰেনে?"</string>
+    <string name="battery_saver_confirmation_title" msgid="1234998463717398453">"বেটাৰী সঞ্চয়কাৰী অন কৰেনে?"</string>
     <string name="battery_saver_confirmation_title_generic" msgid="2299231884234959849">"বেটাৰী সঞ্চয়কাৰীৰ বিষয়ে"</string>
     <string name="battery_saver_confirmation_ok" msgid="5042136476802816494">"অন কৰক"</string>
-    <string name="battery_saver_start_action" msgid="4553256017945469937">"বেটাৰি সঞ্চয়কাৰী অন কৰক"</string>
+    <string name="battery_saver_start_action" msgid="4553256017945469937">"বেটাৰী সঞ্চয়কাৰী অন কৰক"</string>
     <string name="status_bar_settings_settings_button" msgid="534331565185171556">"ছেটিং"</string>
     <string name="status_bar_settings_wifi_button" msgid="7243072479837270946">"ৱাই-ফাই"</string>
     <string name="status_bar_settings_auto_rotation" msgid="8329080442278431708">"স্বয়ং-ঘূৰ্ণন স্ক্ৰীন"</string>
@@ -193,11 +193,11 @@
     <string name="accessibility_compatibility_zoom_example" msgid="2617218726091234073">"স্ক্ৰীনৰ আকাৰ ডাঙৰ কৰিবলৈ জুম কৰক।"</string>
     <string name="accessibility_bluetooth_connected" msgid="4745196874551115205">"ব্লুটুথ সংযোগ হ’ল।"</string>
     <string name="accessibility_bluetooth_disconnected" msgid="7195823280221275929">"ব্লুটুথ সংযোগ বিচ্ছিন্ন কৰা হ’ল।"</string>
-    <string name="accessibility_no_battery" msgid="3789287732041910804">"বেটাৰি শেষ"</string>
-    <string name="accessibility_battery_one_bar" msgid="8868347318237585329">"বেটাৰিৰ এডাল দণ্ড।"</string>
-    <string name="accessibility_battery_two_bars" msgid="7895789999668425551">"বেটাৰিৰ দুডাল দণ্ড।"</string>
-    <string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰিৰ তিনিডাল দণ্ড।"</string>
-    <string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰি পূৰাকৈ চ্চাৰ্জ হৈছে।"</string>
+    <string name="accessibility_no_battery" msgid="3789287732041910804">"বেটাৰী শেষ"</string>
+    <string name="accessibility_battery_one_bar" msgid="8868347318237585329">"বেটাৰীৰ এডাল দণ্ড।"</string>
+    <string name="accessibility_battery_two_bars" msgid="7895789999668425551">"বেটাৰীৰ দুডাল দণ্ড।"</string>
+    <string name="accessibility_battery_three_bars" msgid="118341923832368291">"বেটাৰীৰ তিনিডাল দণ্ড।"</string>
+    <string name="accessibility_battery_full" msgid="1480463938961288494">"বেটাৰী পূৰাকৈ চাৰ্জ হৈছে।"</string>
     <string name="accessibility_battery_unknown" msgid="1807789554617976440">"বেটাৰীৰ চাৰ্জৰ শতাংশ অজ্ঞাত।"</string>
     <string name="accessibility_wifi_name" msgid="4863440268606851734">"<xliff:g id="WIFI">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
     <string name="accessibility_bluetooth_name" msgid="7300973230214067678">"<xliff:g id="BLUETOOTH">%s</xliff:g>ৰ লগত সংযোগ কৰা হ’ল।"</string>
@@ -229,10 +229,10 @@
     <string name="accessibility_airplane_mode" msgid="1899529214045998505">"এয়াৰপ্লে’ন ম’ড।"</string>
     <string name="accessibility_vpn_on" msgid="8037549696057288731">"ভিপিএন অন অৱস্থাত আছে।"</string>
     <string name="accessibility_no_sims" msgid="5711270400476534667">"কোনো ছিম কাৰ্ড নাই"</string>
-    <string name="accessibility_battery_details" msgid="6184390274150865789">"বেটাৰিৰ বিৱৰণসমূহ খোলক"</string>
-    <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰি।"</string>
+    <string name="accessibility_battery_details" msgid="6184390274150865789">"বেটাৰীৰ বিৱৰণসমূহ খোলক"</string>
+    <string name="accessibility_battery_level" msgid="5143715405241138822">"<xliff:g id="NUMBER">%d</xliff:g> শতাংশ বেটাৰী।"</string>
     <string name="accessibility_battery_level_with_estimate" msgid="4843119982547599452">"আপোনাৰ ব্যৱহাৰৰ ওপৰত ভিত্তি কৰি বেটাৰী <xliff:g id="PERCENTAGE">%1$s</xliff:g> শতাংশ, প্ৰায় <xliff:g id="TIME">%2$s</xliff:g> বাকী আছে"</string>
-    <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"বেটাৰি চাৰ্জ হৈ আছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ।"</string>
+    <string name="accessibility_battery_level_charging" msgid="8892191177774027364">"বেটাৰী চাৰ্জ হৈ আছে, <xliff:g id="BATTERY_PERCENTAGE">%d</xliff:g> শতাংশ।"</string>
     <string name="accessibility_settings_button" msgid="2197034218538913880">"ছিষ্টেমৰ ছেটিং৷"</string>
     <string name="accessibility_notifications_button" msgid="3960913924189228831">"জাননীসমূহ।"</string>
     <string name="accessibility_overflow_action" msgid="8555835828182509104">"সকলো জাননীবোৰ চাওক"</string>
@@ -258,7 +258,7 @@
     <string name="accessibility_quick_settings_wifi_changed_off" msgid="2230487165558877262">"ৱাই-ফাই অফ কৰা হ’ল।"</string>
     <string name="accessibility_quick_settings_wifi_changed_on" msgid="1490362586009027611">"ৱাই-ফাই অন কৰা হ’ল।"</string>
     <string name="accessibility_quick_settings_mobile" msgid="1817825313718492906">"ম’বাইল <xliff:g id="SIGNAL">%1$s</xliff:g>. <xliff:g id="TYPE">%2$s</xliff:g>. <xliff:g id="NETWORK">%3$s</xliff:g>."</string>
-    <string name="accessibility_quick_settings_battery" msgid="533594896310663853">"বেটাৰি <xliff:g id="STATE">%s</xliff:g>।"</string>
+    <string name="accessibility_quick_settings_battery" msgid="533594896310663853">"বেটাৰী <xliff:g id="STATE">%s</xliff:g>।"</string>
     <string name="accessibility_quick_settings_airplane_off" msgid="1275658769368793228">"এয়াৰপ্লেইন ম\'ড অফ হৈ আছে৷"</string>
     <string name="accessibility_quick_settings_airplane_on" msgid="8106176561295294255">"এয়াৰপ্লেইন ম\'ড অন হৈ আছে৷"</string>
     <string name="accessibility_quick_settings_airplane_changed_off" msgid="8880183481476943754">"এয়াৰপ্লেইন ম\'ড অফ কৰা হ’ল।"</string>
@@ -338,7 +338,7 @@
     <string name="quick_settings_bluetooth_multiple_devices_label" msgid="6595808498429809855">"ব্লুটুথ (<xliff:g id="NUMBER">%d</xliff:g>টা ডিভাইচ)"</string>
     <string name="quick_settings_bluetooth_off_label" msgid="6375098046500790870">"ব্লুটুথ বন্ধ অৱস্থাত আছে"</string>
     <string name="quick_settings_bluetooth_detail_empty_text" msgid="5760239584390514322">"কোনো যোৰা লগোৱা ডিভাইচ উপলব্ধ নহয়।"</string>
-    <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
+    <string name="quick_settings_bluetooth_secondary_label_battery_level" msgid="4182034939479344093">"বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%s</xliff:g>"</string>
     <string name="quick_settings_bluetooth_secondary_label_audio" msgid="780333390310051161">"অডিঅ’"</string>
     <string name="quick_settings_bluetooth_secondary_label_headset" msgid="2332093067553000852">"হেডছেট"</string>
     <string name="quick_settings_bluetooth_secondary_label_input" msgid="3887552721233148132">"ইনপুট"</string>
@@ -391,7 +391,7 @@
     <string name="quick_settings_done" msgid="2163641301648855793">"সম্পন্ন কৰা হ’ল"</string>
     <string name="quick_settings_close_user_panel" msgid="5599724542275896849">"বন্ধ কৰক"</string>
     <string name="quick_settings_connected" msgid="3873605509184830379">"সংযোগ কৰা হ’ল"</string>
-    <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"সংযুক্ত, বেটাৰি <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
+    <string name="quick_settings_connected_battery_level" msgid="1322075669498906959">"সংযুক্ত, বেটাৰী <xliff:g id="BATTERY_LEVEL_AS_PERCENTAGE">%1$s</xliff:g>"</string>
     <string name="quick_settings_connecting" msgid="2381969772953268809">"সংযোগ কৰি থকা হৈছে..."</string>
     <string name="quick_settings_tethering_label" msgid="5257299852322475780">"টেডাৰ কৰি থকা হৈছে"</string>
     <string name="quick_settings_hotspot_label" msgid="1199196300038363424">"হটস্পট"</string>
@@ -504,9 +504,9 @@
     <string name="user_remove_user_title" msgid="9124124694835811874">"ব্যৱহাৰকাৰীক আঁতৰাবনে?"</string>
     <string name="user_remove_user_message" msgid="6702834122128031833">"এই ব্যৱহাৰকাৰীৰ সকলো এপ্ আৰু ডেটা মচা হ\'ব।"</string>
     <string name="user_remove_user_remove" msgid="8387386066949061256">"আঁতৰাওক"</string>
-    <string name="battery_saver_notification_title" msgid="8419266546034372562">"বেটাৰি সঞ্চয়কাৰী অন হৈ আছে"</string>
+    <string name="battery_saver_notification_title" msgid="8419266546034372562">"বেটাৰী সঞ্চয়কাৰী অন হৈ আছে"</string>
     <string name="battery_saver_notification_text" msgid="2617841636449016951">"কাৰ্যদক্ষতা আৰু নেপথ্য ডেটা হ্ৰাস কৰে"</string>
-    <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"বেটাৰি সঞ্চয়কাৰী অফ কৰক"</string>
+    <string name="battery_saver_notification_action_text" msgid="6022091913807026887">"বেটাৰী সঞ্চয়কাৰী অফ কৰক"</string>
     <string name="media_projection_dialog_text" msgid="1755705274910034772">"<xliff:g id="APP_SEEKING_PERMISSION">%s</xliff:g>এ আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিঙৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
     <string name="media_projection_dialog_service_text" msgid="958000992162214611">"এই সুবিধাটো প্ৰদান কৰা সেৱাটোৱে আপোনাৰ স্ক্ৰীনত দৃশ্যমান হোৱা অথবা ৰেকর্ডিং অথবা কাষ্টিংৰ সময়ত আপোনাৰ ডিভাইচত প্লে\' কৰা সকলো তথ্যলৈ এক্সেছ পাব। এইটোত পাছৱর্ড, পৰিশোধৰ সবিশেষ, ফট\', বার্তাসমূহ আৰু আপুনি প্লে\' কৰা অডিঅ\'ৰ দৰে তথ্য অন্তর্ভুক্ত হয়।"</string>
     <string name="media_projection_dialog_service_title" msgid="2888507074107884040">"ৰেকর্ডিং অথবা কাষ্টিং আৰম্ভ কৰিবনে?"</string>
@@ -657,8 +657,8 @@
     <string name="output_service_wifi" msgid="9003667810868222134">"ৱাই-ফাই"</string>
     <string name="output_service_bt_wifi" msgid="7186882540475524124">"ব্লুটুথ আৰু ৱাই-ফাই"</string>
     <string name="system_ui_tuner" msgid="1471348823289954729">"System UI Tuner"</string>
-    <string name="show_battery_percentage" msgid="6235377891802910455">"সংযুক্ত বেটাৰিৰ কিমান শতাংশ বাকী আছে দেখুওৱাক"</string>
-    <string name="show_battery_percentage_summary" msgid="9053024758304102915">"চাৰ্জ হৈ নথকা অৱস্থাত বেটাৰি কিমান শতাংশ বাকী স্থিতি দণ্ডৰ ভিতৰত দেখুৱাওক"</string>
+    <string name="show_battery_percentage" msgid="6235377891802910455">"সংযুক্ত বেটাৰীৰ কিমান শতাংশ বাকী আছে দেখুওৱাক"</string>
+    <string name="show_battery_percentage_summary" msgid="9053024758304102915">"চাৰ্জ হৈ নথকা অৱস্থাত বেটাৰী কিমান শতাংশ বাকী স্থিতি দণ্ডৰ ভিতৰত দেখুৱাওক"</string>
     <string name="quick_settings" msgid="6211774484997470203">"ক্ষিপ্ৰ ছেটিং"</string>
     <string name="status_bar" msgid="4357390266055077437">"স্থিতি দণ্ড"</string>
     <string name="overview" msgid="3522318590458536816">"অৱলোকন"</string>
@@ -696,7 +696,7 @@
     <string name="remove_from_settings_prompt" msgid="551565437265615426">"ছেটিঙৰ পৰা System UI Tuner আঁতৰাই ইয়াৰ সুবিধাসমূহ ব্যৱহাৰ কৰাটো বন্ধ কৰিবনে?"</string>
     <string name="activity_not_found" msgid="8711661533828200293">"আপোনাৰ ডিভাইচত এপ্লিকেশ্বনটো ইনষ্টল কৰা হোৱা নাই"</string>
     <string name="clock_seconds" msgid="8709189470828542071">"ঘড়ীৰ ছেকেণ্ড দেখুৱাওক"</string>
-    <string name="clock_seconds_desc" msgid="2415312788902144817">"স্থিতি দণ্ডত ঘড়ীৰ ছেকেণ্ড দেখুৱাওক। এই কার্যই বেটাৰিৰ অৱস্থাত প্ৰভাৱ পেলাব পাৰে।"</string>
+    <string name="clock_seconds_desc" msgid="2415312788902144817">"স্থিতি দণ্ডত ঘড়ীৰ ছেকেণ্ড দেখুৱাওক। এই কার্যই বেটাৰীৰ জীৱনকালত প্ৰভাৱ পেলাব পাৰে।"</string>
     <string name="qs_rearrange" msgid="484816665478662911">"ক্ষিপ্ৰ ছেটিং পুনৰ সজাওক"</string>
     <string name="show_brightness" msgid="6700267491672470007">"দ্ৰুত ছেটিঙত উজ্জ্বলতা দেখুৱাওক"</string>
     <string name="experimental" msgid="3549865454812314826">"পৰীক্ষামূলক"</string>
@@ -802,8 +802,8 @@
       <item quantity="one"> %d মিনিট</item>
       <item quantity="other"> %d মিনিট</item>
     </plurals>
-    <string name="battery_panel_title" msgid="5931157246673665963">"বেটাৰিৰ ব্যৱহাৰ"</string>
-    <string name="battery_detail_charging_summary" msgid="8821202155297559706">"চ্চাৰ্জ কৰি থকাৰ সময়ত বেটাৰি সঞ্চয়কাৰী উপলব্ধ নহয়।"</string>
+    <string name="battery_panel_title" msgid="5931157246673665963">"বেটাৰীৰ ব্যৱহাৰ"</string>
+    <string name="battery_detail_charging_summary" msgid="8821202155297559706">"চাৰ্জ কৰি থকাৰ সময়ত বেটাৰী সঞ্চয়কাৰী উপলব্ধ নহয়।"</string>
     <string name="battery_detail_switch_title" msgid="6940976502957380405">"বেটাৰী সঞ্চয়কাৰী"</string>
     <string name="battery_detail_switch_summary" msgid="3668748557848025990">"কাৰ্যদক্ষতা আৰু নেপথ্য ডেটা হ্ৰাস কৰে"</string>
     <string name="keyboard_key_button_template" msgid="8005673627272051429">"<xliff:g id="NAME">%1$s</xliff:g> বুটাম"</string>
@@ -853,7 +853,7 @@
     <string name="volume_and_do_not_disturb" msgid="502044092739382832">"অসুবিধা নিদিব"</string>
     <string name="volume_dnd_silent" msgid="4154597281458298093">"ভলিউম বুটামসমূহৰ শ্বৰ্টকাট"</string>
     <string name="volume_up_silent" msgid="1035180298885717790">"ভলিউম বঢ়োৱা বুটাম ব্যৱহাৰ কৰি অসুবিধা নিদিব নিষ্ক্ৰিয় কৰক"</string>
-    <string name="battery" msgid="769686279459897127">"বেটাৰি"</string>
+    <string name="battery" msgid="769686279459897127">"বেটাৰী"</string>
     <string name="clock" msgid="8978017607326790204">"ঘড়ী"</string>
     <string name="headset" msgid="4485892374984466437">"হেডছেট"</string>
     <string name="accessibility_long_click_tile" msgid="210472753156768705">"ছেটিং খোলক"</string>
@@ -962,7 +962,7 @@
     <string name="tuner_menu" msgid="363690665924769420">"মেনু"</string>
     <string name="tuner_app" msgid="6949280415826686972">"<xliff:g id="APP">%1$s</xliff:g> এপ্"</string>
     <string name="notification_channel_alerts" msgid="3385787053375150046">"সতৰ্কবার্তাসমূহ"</string>
-    <string name="notification_channel_battery" msgid="9219995638046695106">"বেটাৰি"</string>
+    <string name="notification_channel_battery" msgid="9219995638046695106">"বেটাৰী"</string>
     <string name="notification_channel_screenshot" msgid="7665814998932211997">"স্ক্ৰীণশ্বটসমূহ"</string>
     <string name="notification_channel_general" msgid="4384774889645929705">"সাধাৰণ বার্তাসমূহ"</string>
     <string name="notification_channel_storage" msgid="2720725707628094977">"ষ্ট\'ৰেজ"</string>
@@ -986,7 +986,7 @@
     <string name="qs_dnd_keep" msgid="3829697305432866434">"Keep"</string>
     <string name="qs_dnd_replace" msgid="7712119051407052689">"সলনি কৰক"</string>
     <string name="running_foreground_services_title" msgid="5137313173431186685">"নেপথ্যত চলি থকা এপসমূহ"</string>
-    <string name="running_foreground_services_msg" msgid="3009459259222695385">"বেটাৰি আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে বিশদভাৱে জানিবলৈ টিপক"</string>
+    <string name="running_foreground_services_msg" msgid="3009459259222695385">"বেটাৰী আৰু ডেটাৰ ব্যৱহাৰৰ বিষয়ে সবিশেষ জানিবলৈ টিপক"</string>
     <string name="mobile_data_disable_title" msgid="5366476131671617790">"ম’বাইল ডেটা অফ কৰিবনে?"</string>
     <string name="mobile_data_disable_message" msgid="8604966027899770415">"আপুনি <xliff:g id="CARRIER">%s</xliff:g>ৰ জৰিয়তে ডেটা সংযোগ বা ইণ্টাৰনেট সংযোগ নাপাব। কেৱল ৱাই-ফাইৰ যোগেৰে ইণ্টাৰনেট উপলব্ধ হ\'ব।"</string>
     <string name="mobile_data_disable_message_default_carrier" msgid="6496033312431658238">"আপোনাৰ বাহক"</string>
@@ -997,11 +997,11 @@
     <string name="slice_permission_checkbox" msgid="4242888137592298523">"<xliff:g id="APP">%1$s</xliff:g>ক যিকোনো এপৰ অংশ দেখুওৱাবলৈ অনুমতি দিয়ক"</string>
     <string name="slice_permission_allow" msgid="6340449521277951123">"অনুমতি দিয়ক"</string>
     <string name="slice_permission_deny" msgid="6870256451658176895">"অস্বীকাৰ কৰক"</string>
-    <string name="auto_saver_title" msgid="6873691178754086596">"বেটাৰি সঞ্চয়কাৰীৰ সময়সূচী সক্ৰিয় কৰিবলৈ টিপক"</string>
-    <string name="auto_saver_text" msgid="3214960308353838764">"বেটাৰি শেষ হোৱাৰ সম্ভাৱনা থাকিলে অন কৰক"</string>
+    <string name="auto_saver_title" msgid="6873691178754086596">"বেটাৰী সঞ্চয়কাৰীৰ সময়সূচী সক্ৰিয় কৰিবলৈ টিপক"</string>
+    <string name="auto_saver_text" msgid="3214960308353838764">"বেটাৰী শেষ হোৱাৰ সম্ভাৱনা থাকিলে অন কৰক"</string>
     <string name="no_auto_saver_action" msgid="7467924389609773835">"নালাগে, ধন্যবাদ"</string>
-    <string name="auto_saver_enabled_title" msgid="4294726198280286333">"বেটাৰি সঞ্চয়কাৰীৰ সময়সূচী অন কৰা অৱস্থাত আছে"</string>
-    <string name="auto_saver_enabled_text" msgid="7889491183116752719">"বেটাৰি চ্চাৰ্জৰ স্তৰ <xliff:g id="PERCENTAGE">%d</xliff:g>%%তকৈ কম হোৱাৰ লগে লগে বেটাৰি সঞ্চয়কাৰী স্বয়ংক্ৰিয়ভাৱে অন হ’ব।"</string>
+    <string name="auto_saver_enabled_title" msgid="4294726198280286333">"বেটাৰী সঞ্চয়কাৰীৰ সময়সূচী অন কৰা অৱস্থাত আছে"</string>
+    <string name="auto_saver_enabled_text" msgid="7889491183116752719">"বেটাৰী চাৰ্জৰ স্তৰ <xliff:g id="PERCENTAGE">%d</xliff:g>%%তকৈ কম হোৱাৰ লগে লগে বেটাৰী সঞ্চয়কাৰী স্বয়ংক্ৰিয়ভাৱে অন হ’ব।"</string>
     <string name="open_saver_setting_action" msgid="2111461909782935190">"ছেটিং"</string>
     <string name="auto_saver_okay_action" msgid="7815925750741935386">"বুজি পালোঁ"</string>
     <string name="heap_dump_tile_name" msgid="2464189856478823046">"SysUI হীপ ডাম্প কৰক"</string>
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"এতিয়া ৱাই-ফাই স্বয়ংক্ৰিয়ভাৱে সংযুক্ত নহ’ব"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"আটাইবোৰ চাওক"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"নেটৱৰ্ক সলনি কৰিবলৈ ইথাৰনেটৰ পৰা সংযোগ বিচ্ছিন্ন কৰক"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ডিভাইচ ব্যৱহাৰৰ অভিজ্ঞতা উন্নত কৰিবলৈ ৱাই-ফাই অফ থকা অৱস্থাতো এপ্ আৰু সেৱাসমূহে ৱাই-ফাই নেটৱৰ্কবোৰ স্কেন কৰিব পাৰে। আপুনি ৱাই-ফাই স্কেনিঙৰ ছেটিঙত এইটো সলনি কৰিব পাৰে। "<annotation id="link">"সলনি কৰক"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ব্যৱহাৰকাৰী বাছনি কৰক"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-az/strings.xml b/packages/SystemUI/res/values-az/strings.xml
index dad7add..a232834 100644
--- a/packages/SystemUI/res/values-az/strings.xml
+++ b/packages/SystemUI/res/values-az/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi hələlik avtomatik qoşulmayacaq"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Hamısına baxın"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Şəbəkəni dəyişmək üçün etherneti ayırın"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Cihaz təcrübəsini yaxşılaşdırmaq üçün Wi-Fi deaktiv olduqda belə, tətbiqlər və xidmətlər Wi-Fi şəbəkəsini axtara biləcək. Bunu Wi-Fi axtarışı ayarlarında dəyişə bilərsiniz. "<annotation id="link">"Dəyişin"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"İstifadəçi seçin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-b+sr+Latn/strings.xml b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
index 1761205..caab554 100644
--- a/packages/SystemUI/res/values-b+sr+Latn/strings.xml
+++ b/packages/SystemUI/res/values-b+sr+Latn/strings.xml
@@ -1185,5 +1185,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi trenutno ne može da se automatski poveže"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Pogledajte sve"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Da biste promenili mrežu, prekinite eternet vezu"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Radi boljeg doživljaja uređaja, aplikacije i usluge i dalje mogu da traže WiFi mreže u bilo kom trenutku, čak i kada je WiFi isključen. To možete da promenite u podešavanjima WiFi skeniranja. "<annotation id="link">"Promenite"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Izaberite korisnika"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-be/strings.xml b/packages/SystemUI/res/values-be/strings.xml
index 8bfc32f..d327b4d 100644
--- a/packages/SystemUI/res/values-be/strings.xml
+++ b/packages/SystemUI/res/values-be/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Аўтаматычнае падключэнне да Wi-Fi адсутнічае"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Паказаць усе"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Каб падключыцца да сетак, выключыце Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Каб палепшыць працу прылады, вы можаце дазволіць праграмам і сэрвісам шукаць сеткі Wi-Fi, нават калі Wi‑Fi выключаны. Змяніць гэты рэжым можна ў наладах пошуку сетак Wi-Fi. "<annotation id="link">"Змяніць"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Выбар карыстальніка"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bg/strings.xml b/packages/SystemUI/res/values-bg/strings.xml
index d9d06dc..42b80f4 100644
--- a/packages/SystemUI/res/values-bg/strings.xml
+++ b/packages/SystemUI/res/values-bg/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Засега Wi-Fi няма да се свързва автоматично"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Вижте всички"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"За да превключите мрежите, прекъснете връзката с Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"С цел подобряване на практическата работа с устройството приложенията и услугите пак могат да сканират за Wi‑Fi мрежи по всяко време дори когато функцията за Wi‑Fi e изключена. Можете да промените съответното поведение от настройките за сканиране за Wi‑Fi. "<annotation id="link">"Промяна"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Избор на потребител"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bn/strings.xml b/packages/SystemUI/res/values-bn/strings.xml
index 4ba1436..5b8c662 100644
--- a/packages/SystemUI/res/values-bn/strings.xml
+++ b/packages/SystemUI/res/values-bn/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"আবার চালু করুন"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"সেটিংস"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-এর <xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%3$s</xliff:g> অ্যাপে চলছে"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>টির মধ্যে <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>টি"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"চালান"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> অ্যাপ খুলুন"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g>-এর <xliff:g id="SONG_NAME">%1$s</xliff:g> গানটি <xliff:g id="APP_LABEL">%3$s</xliff:g> অ্যাপে চালান"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"এখন ওয়াই-ফাই নিজে থেকে কানেক্ট হবে না"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"সবকটি দেখুন"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"নেটওয়ার্ক বদলাতে ইথারনেট ডিসকানেক্ট করুন"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ডিভাইস সংক্রান্ত অভিজ্ঞতা আরও ভাল করতে, অ্যাপ ও পরিষেবা যেকোনও সময় আপনার ওয়াই-ফাই নেটওয়ার্ক স্ক্যান করতে পারবে, এমনকি ডিভাইসের ওয়াই-ফাই বন্ধ করা থাকলেও। ওয়াই-ফাই স্ক্যানিং সেটিংস থেকে আপনি এটি পরিবর্তন করতে পারবেন। "<annotation id="link">"পরিবর্তন করুন"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ব্যবহারকারী বেছে নিন"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-bs/strings.xml b/packages/SystemUI/res/values-bs/strings.xml
index 95bca33..19e868f 100644
--- a/packages/SystemUI/res/values-bs/strings.xml
+++ b/packages/SystemUI/res/values-bs/strings.xml
@@ -1185,5 +1185,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi se trenutno ne može automatski povezati"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Prikaži sve"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Da promijenite mrežu, isključite ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Radi poboljšanja iskustva s uređajem aplikacije i usluge i dalje mogu bilo kada skenirati WiFi mreže, čak i kada je WiFi isključen. Ovo možete promijeniti u Postavkama skeniranja WiFi mreže. "<annotation id="link">"Promijeni"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Odaberite korisnika"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ca/strings.xml b/packages/SystemUI/res/values-ca/strings.xml
index 2ca9897..f31a72d 100644
--- a/packages/SystemUI/res/values-ca/strings.xml
+++ b/packages/SystemUI/res/values-ca/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Per ara la Wi‑Fi no es connectarà automàticament"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Mostra-ho tot"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Per canviar de xarxa, desconnecta la connexió Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per millorar l\'experiència del dispositiu, les aplicacions i els serveis poden cercar xarxes Wi‑Fi en qualsevol moment, fins i tot quan la Wi‑Fi estigui desactivada. Pots canviar aquesta opció a la configuració de cerca de xarxes Wi‑Fi. "<annotation id="link">"Canvia-la"</annotation>"."</string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecciona un usuari"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-cs/strings.xml b/packages/SystemUI/res/values-cs/strings.xml
index bb205bf..05e4b1e 100644
--- a/packages/SystemUI/res/values-cs/strings.xml
+++ b/packages/SystemUI/res/values-cs/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi se prozatím nebude připojovat automaticky"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Zobrazit vše"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pokud chcete přepnout sítě, odpojte ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Za účelem lepšího fungování zařízení mohou aplikace a služby vyhledávat sítě Wi-Fi, i když je připojení Wi-Fi vypnuté. Toto chování můžete změnit v nastavení vyhledávání Wi-Fi. "<annotation id="link">"Změnit"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Zvolte uživatele"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-da/strings.xml b/packages/SystemUI/res/values-da/strings.xml
index 1a251d2..8145ffa 100644
--- a/packages/SystemUI/res/values-da/strings.xml
+++ b/packages/SystemUI/res/values-da/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Ingen automatisk forbindelse til Wi-Fi i øjeblikket"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Afbryd ethernetforbindelsen for at skifte netværk"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"For at forbedre brugeroplevelsen på enheden kan apps og tjenester stadig til enhver tid scanne efter Wi‑Fi-netværk, også selvom Wi‑Fi er deaktiveret. Du kan ændre dette i indstillingerne for Wi-Fi-scanning. "<annotation id="link">"Skift indstilling"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Vælg bruger"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-de/strings.xml b/packages/SystemUI/res/values-de/strings.xml
index ce469d5..fc36c84 100644
--- a/packages/SystemUI/res/values-de/strings.xml
+++ b/packages/SystemUI/res/values-de/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"Fortsetzen"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Einstellungen"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> wird gerade über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergegeben"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> von <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Wiedergeben"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> öffnen"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> von <xliff:g id="ARTIST_NAME">%2$s</xliff:g> über <xliff:g id="APP_LABEL">%3$s</xliff:g> wiedergeben"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Zurzeit wird keine automatische WLAN-Verbindung hergestellt"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Alle ansehen"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Trenne das Ethernetkabel, um das Netzwerk zu wechseln"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Zur Verbesserung der Gerätenutzung können Apps und Dienste weiter nach WLANs suchen, auch wenn die WLAN-Funktion deaktiviert ist. Dies lässt sich in den Einstellungen für die WLAN-Suche ändern. "<annotation id="link">"Ändern"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Nutzer auswählen"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-el/strings.xml b/packages/SystemUI/res/values-el/strings.xml
index 2fa648c..a93fec5 100644
--- a/packages/SystemUI/res/values-el/strings.xml
+++ b/packages/SystemUI/res/values-el/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Δεν θα γίνεται προς το παρόν αυτόματη σύνδεση Wi-Fi."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Εμφάνιση όλων"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Για εναλλαγή δικτύων, αποσυνδέστε το ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Για βελτίωση της εμπειρίας στη συσκευή, οι εφαρμογές και οι υπηρεσίες μπορούν ακόμα να εκτελούν σάρωση για δίκτυα Wi‑Fi ανά πάσα στιγμή, ακόμα και όταν το Wi‑Fi είναι απενεργοποιημένο. Μπορείτε να αλλάξετε αυτήν τη ρύθμιση στις ρυθμίσεις της Σάρωσης Wi‑Fi. "<annotation id="link">"Αλλαγή"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Επιλογή χρήστη"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rAU/strings.xml b/packages/SystemUI/res/values-en-rAU/strings.xml
index 84b24d6..2f4a17d 100644
--- a/packages/SystemUI/res/values-en-rAU/strings.xml
+++ b/packages/SystemUI/res/values-en-rAU/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rCA/strings.xml b/packages/SystemUI/res/values-en-rCA/strings.xml
index c435a83..e1ab43a 100644
--- a/packages/SystemUI/res/values-en-rCA/strings.xml
+++ b/packages/SystemUI/res/values-en-rCA/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rGB/strings.xml b/packages/SystemUI/res/values-en-rGB/strings.xml
index 84b24d6..2f4a17d 100644
--- a/packages/SystemUI/res/values-en-rGB/strings.xml
+++ b/packages/SystemUI/res/values-en-rGB/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rIN/strings.xml b/packages/SystemUI/res/values-en-rIN/strings.xml
index 84b24d6..2f4a17d 100644
--- a/packages/SystemUI/res/values-en-rIN/strings.xml
+++ b/packages/SystemUI/res/values-en-rIN/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi won’t auto-connect for now"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"See all"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"To switch networks, disconnect Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. "<annotation id="link">"Change"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Select user"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-en-rXC/strings.xml b/packages/SystemUI/res/values-en-rXC/strings.xml
index 1ed76dc..7ddbdd6 100644
--- a/packages/SystemUI/res/values-en-rXC/strings.xml
+++ b/packages/SystemUI/res/values-en-rXC/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‎‎‎‎‎‎‏‏‏‏‏‎‏‏‎‎‏‎‏‏‎‏‏‎‎‏‏‎‏‎‎‎‎‎‏‏‏‏‎‏‏‏‏‏‏‎‎‏‏‎‏‎‏‏‏‏‎‎‏‎‎Wi‑Fi won’t auto-connect for now‎‏‎‎‏‎"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‏‎‏‏‏‏‎‏‏‎‎‎‎‏‎‎‎‎‎‎‎‎‎‎‏‏‎‏‏‏‏‏‎‏‏‎‏‏‏‏‏‏‎‏‏‏‎‏‏‏‏‏‎‏‎‎See all‎‏‎‎‏‎"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‏‏‎‏‏‏‎‎‏‏‏‏‎‏‎‎‎‏‏‏‏‎‎‎‏‎‎‎‏‏‏‎‏‏‏‏‎‎‏‎‏‎‎‎‏‏‏‏‏‎‎‎‎‏‏‏‏‎‎‏‎‎‏‏‎To switch networks, disconnect ethernet‎‏‎‎‏‎"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‏‎‏‎‎‎‎‎‏‏‎‎‎‎‏‎‏‎‎‎‏‎‎‏‎‏‎‏‏‏‎‏‎‏‏‎‏‎‏‏‏‎‎‎‏‎‎‎‏‎‏‏‎‏‏‏‎‎‎‏‎‎To improve device experience, apps and services can still scan for Wi‑Fi networks at any time, even when Wi‑Fi is off. You can change this in Wi‑Fi scanning settings. ‎‏‎‎‏‏‎"<annotation id="link">"‎‏‎‎‏‏‏‎Change‎‏‎‎‏‏‎"</annotation>"‎‏‎‎‏‏‏‎‎‏‎‎‏‎"</string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"‎‏‎‎‎‎‎‏‎‏‏‏‎‎‎‎‎‎‏‎‎‏‎‎‎‎‏‏‏‏‏‏‎‏‎‏‎‏‎‎‏‎‎‎‎‏‎‏‎‏‎‏‏‏‏‏‎‎‎‎‏‏‏‎‏‎‎‎‏‏‎‎‎‎‏‏‏‏‏‎‏‎‏‎‏‏‎‏‏‏‏‎‏‏‎‎Select user‎‏‎‎‏‎"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es-rUS/strings.xml b/packages/SystemUI/res/values-es-rUS/strings.xml
index 4875e63..95cd9ba 100644
--- a/packages/SystemUI/res/values-es-rUS/strings.xml
+++ b/packages/SystemUI/res/values-es-rUS/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por ahora, el Wi-Fi no se conectará automáticamente"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de red, desconéctate de Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mejorar la experiencia con el dispositivo, las apps y los servicios pueden seguir buscando redes Wi-Fi en cualquier momento, incluso cuando la conexión Wi-Fi esté desactivada. Puedes cambiar este parámetro en la configuración de búsqueda de Wi-Fi. "<annotation id="link">"Cambiar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleccionar usuario"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-es/strings.xml b/packages/SystemUI/res/values-es/strings.xml
index af32894..15af903 100644
--- a/packages/SystemUI/res/values-es/strings.xml
+++ b/packages/SystemUI/res/values-es/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por ahora no se conectará automáticamente a redes Wi-Fi"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de red, desconecta el cable Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mejorar la experiencia con el dispositivo, las aplicaciones y los servicios podrán buscar redes Wi-Fi en cualquier momento, aunque la conexión Wi-Fi esté desactivada. Puedes cambiarlo en los ajustes de búsqueda de redes Wi-Fi. "<annotation id="link">"Cambiar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleccionar usuario"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-et/strings.xml b/packages/SystemUI/res/values-et/strings.xml
index ebab6f3..39d29cc 100644
--- a/packages/SystemUI/res/values-et/strings.xml
+++ b/packages/SystemUI/res/values-et/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi-ühendust ei looda praegu automaatselt"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Kuva kõik"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Võrkude vahetamiseks katkestage Etherneti-ühendus"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Seadme kasutuskogemuse parandamiseks võivad rakendused ja teenused siiski alati otsida WiFi-võrke isegi siis, kui WiFi on väljas. Seda saab muuta WiFi-skannimise seadetes. "<annotation id="link">"Muuda"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kasutaja valimine"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-eu/strings.xml b/packages/SystemUI/res/values-eu/strings.xml
index 0d58986..bacf6ef 100644
--- a/packages/SystemUI/res/values-eu/strings.xml
+++ b/packages/SystemUI/res/values-eu/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Oraingoz ez da automatikoki konektatuko wifira"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Ikusi guztiak"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Sarea aldatzeko, deskonektatu Ethernet-a"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Gailuaren funtzionamendua hobetzeko, aplikazioek eta zerbitzuek wifi-sareak bilatzen jarraituko dute, baita wifi-konexioa desaktibatuta dagoenean ere. Aukera hori aldatzeko, joan wifi-sareen bilaketaren ezarpenetara. "<annotation id="link">"Aldatu"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Hautatu erabiltzaile bat"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fa/strings.xml b/packages/SystemUI/res/values-fa/strings.xml
index dfc88f4..9a9c20f 100644
--- a/packages/SystemUI/res/values-fa/strings.xml
+++ b/packages/SystemUI/res/values-fa/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"ازسرگیری"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"تنظیمات"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش می‌شود"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> از <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"پخش"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"باز کردن <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="SONG_NAME">%1$s</xliff:g> از <xliff:g id="ARTIST_NAME">%2$s</xliff:g> را ازطریق <xliff:g id="APP_LABEL">%3$s</xliff:g> پخش کنید"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"‏فعلاً Wi-Fi به‌طور خودکار متصل نمی‌شود"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"مشاهده همه"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"برای تغییر شبکه، اترنت را قطع کنید"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"‏برای بهبود تجربه استفاده از دستگاه، برنامه‌ها و سرویس‌ها همچنان می‌توانند در هر زمانی شبکه‌های Wi-Fi را اسکن کنند؛ حتی وقتی که Wi-Fi خاموش باشد. می‌توانید این مورد را در تنظیمات اسکن کردن Wi‑Fi تغییر دهید. "<annotation id="link">"تغییر"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"انتخاب کاربر"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fi/strings.xml b/packages/SystemUI/res/values-fi/strings.xml
index c62f664..ca0f452 100644
--- a/packages/SystemUI/res/values-fi/strings.xml
+++ b/packages/SystemUI/res/values-fi/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"Jatka"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Asetukset"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> soittaa nyt tätä: <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>)"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g>/<xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Toista"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Avaa <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Soita <xliff:g id="SONG_NAME">%1$s</xliff:g> (<xliff:g id="ARTIST_NAME">%2$s</xliff:g>) sovelluksessa <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi ei toistaiseksi yhdistä automaattisesti"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Näytä kaikki"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Irrota Ethernet-johto, jos haluat vaihtaa verkkoa"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Laitteen käyttökokemuksen parantamiseksi sovellukset ja palvelut voivat hakea Wi-Fi-verkkoja myös silloin, kun Wi-Fi on pois päältä. Voit muuttaa asetusta Wi-Fi-haun asetuksissa. "<annotation id="link">"Muuta"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Valitse käyttäjä"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr-rCA/strings.xml b/packages/SystemUI/res/values-fr-rCA/strings.xml
index 0f60249..ef4f86d 100644
--- a/packages/SystemUI/res/values-fr-rCA/strings.xml
+++ b/packages/SystemUI/res/values-fr-rCA/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connexion automatique au Wi-Fi impossible pour le moment"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pour changer de réseau, débranchez le câble Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pour améliorer l\'expérience de l\'appareil, les applications et les services peuvent quand même rechercher des réseaux Wi-Fi en tout temps, même lorsque le Wi-Fi est désactivé. Vous pouvez modifier vos préférences dans les paramètres de recherche de réseaux Wi-Fi. "<annotation id="link">"Modifier"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Sélect. utilisateur"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-fr/strings.xml b/packages/SystemUI/res/values-fr/strings.xml
index c31ccafc..3d6dd55 100644
--- a/packages/SystemUI/res/values-fr/strings.xml
+++ b/packages/SystemUI/res/values-fr/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"Reprendre"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Paramètres"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> est en cours de lecture depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> sur <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Lire"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Ouvre <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Mets <xliff:g id="SONG_NAME">%1$s</xliff:g> par <xliff:g id="ARTIST_NAME">%2$s</xliff:g> depuis <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connexion automatique au Wi-Fi désactivée pour le moment"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Tout afficher"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pour changer de réseau, déconnectez l\'Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pour améliorer l\'expérience sur l\'appareil, les applis et les services peuvent continuer de rechercher les réseaux Wi-Fi, même si le Wi-Fi est désactivé. Vous pouvez modifier cela dans les paramètres de recherche Wi-Fi. "<annotation id="link">"Modifier"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Choisir utilisateur"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gl/strings.xml b/packages/SystemUI/res/values-gl/strings.xml
index 002f0a1..8570e9a 100644
--- a/packages/SystemUI/res/values-gl/strings.xml
+++ b/packages/SystemUI/res/values-gl/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"De momento, a wifi non se conectará automaticamente"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Ver todo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para cambiar de rede, desconecta a Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para mellorar a experiencia que ofrece o dispositivo, as aplicacións e os servizos poden seguir buscando redes wifi en calquera momento, aínda que esta conexión estea desactivada. Podes cambiar esta opción na configuración da función Busca de redes wifi. "<annotation id="link">"Cambiar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleccionar usuario"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-gu/strings.xml b/packages/SystemUI/res/values-gu/strings.xml
index cf001fc..95efbad 100644
--- a/packages/SystemUI/res/values-gu/strings.xml
+++ b/packages/SystemUI/res/values-gu/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"ફરી શરૂ કરો"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"સેટિંગ"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g> પર <xliff:g id="ARTIST_NAME">%2$s</xliff:g>નું <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચાલી રહ્યું છે"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>માંથી <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ચલાવો"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ખોલો"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> પર <xliff:g id="ARTIST_NAME">%2$s</xliff:g>નું <xliff:g id="SONG_NAME">%1$s</xliff:g> ગીત ચલાવો"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"હમણાં પૂરતું વાઇ-ફાઇ ઑટોમૅટિક રીતે કનેક્ટ થશે નહીં"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"બધા જુઓ"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"બીજા નેટવર્ક પર જવા માટે, ઇથરનેટ ડિસ્કનેક્ટ કરો"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ડિવાઇસના અનુભવને બહેતર બનાવવા માટે, વાઇ-ફાઇ બંધ હોય ત્યારે પણ ઍપ અને સેવાઓ કોઈપણ સમયે વાઇ-ફાઇ નેટવર્ક સ્કૅન કરી શકે છે. તમે વાઇ-ફાઇ સ્કૅનિંગના સેટિંગમાં જઈને આને બદલી શકો છો. "<annotation id="link">"બદલો"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"વપરાશકર્તા પસંદ કરો"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hi/strings.xml b/packages/SystemUI/res/values-hi/strings.xml
index 143152e..2a647556 100644
--- a/packages/SystemUI/res/values-hi/strings.xml
+++ b/packages/SystemUI/res/values-hi/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"फ़िलहाल, वाई-फ़ाई अपने-आप कनेक्ट नहीं होगा"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"सभी देखें"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"नेटवर्क बदलने के लिए, पहले ईथरनेट को डिसकनेक्ट करें"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"डिवाइस इस्तेमाल करने के अनुभव काे बेहतर बनाने के लिए, ऐप्लिकेशन और सेवाओं की मदद से, किसी भी समय वाई-फ़ाई नेटवर्क स्कैन किए जा सकते हैं. ऐसा वाई-फ़ाई बंद होने पर भी किया जा सकता है. वाई-फ़ाई स्कैनिंग की सेटिंग में जाकर, इसे बदला जा सकता है. "<annotation id="link">"बदलें"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"उपयोगकर्ता चुनें"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hr/strings.xml b/packages/SystemUI/res/values-hr/strings.xml
index 206f297..3edd928 100644
--- a/packages/SystemUI/res/values-hr/strings.xml
+++ b/packages/SystemUI/res/values-hr/strings.xml
@@ -1185,5 +1185,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi se zasad neće automatski povezivati"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Prikaži sve"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Da biste se prebacili na drugu mrežu, odspojite Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Da bi se poboljšao doživljaj uređaja, aplikacije i usluge i dalje mogu tražiti Wi-Fi mreže u bilo kojem trenutku, čak i kada je Wi-Fi isključen. To možete promijeniti u postavkama traženja Wi-Fija. "<annotation id="link">"Promijeni"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Odabir korisnika"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hu/strings.xml b/packages/SystemUI/res/values-hu/strings.xml
index ab91233..3485808 100644
--- a/packages/SystemUI/res/values-hu/strings.xml
+++ b/packages/SystemUI/res/values-hu/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A Wi-Fi-re történő csatlakozás jelenleg nem automatikus"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Megtekintés"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Hálózatváltáshoz válassza le az ethernetet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Az eszközhasználati élmény javítása érdekében az alkalmazások és a szolgáltatások továbbra is bármikor kereshetnek Wi-Fi-hálózatokat, még akkor is, ha a Wi-Fi ki van kapcsolva. A funkciót a „Wi-Fi scanning settings” (Wi-Fi-keresési beállítások) részben módosíthatja. "<annotation id="link">"Módosítás"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Felhasználóválasztás"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-hy/strings.xml b/packages/SystemUI/res/values-hy/strings.xml
index 7638843..fde4d32 100644
--- a/packages/SystemUI/res/values-hy/strings.xml
+++ b/packages/SystemUI/res/values-hy/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi-ն ավտոմատ չի միանա"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Տեսնել բոլորը"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Մի ցանցից մյուսին անցնելու համար անջատեք Ethernet-ը"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Սարքի աշխատանքը բարելավելու համար հավելվածներն ու ծառայությունները կորոնեն Wi‑Fi ցանցեր, նույնիսկ երբ Wi‑Fi-ն անջատված է։ Այս պարամետրը կարող եք փոխել Wi‑Fi ցանցերի որոնման կարգավորումներում։ "<annotation id="link">"Փոխել"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Ընտրեք օգտատեր"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-in/strings.xml b/packages/SystemUI/res/values-in/strings.xml
index 1745690..f3bf7df 100644
--- a/packages/SystemUI/res/values-in/strings.xml
+++ b/packages/SystemUI/res/values-in/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tidak akan otomatis terhubung untuk saat ini"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Untuk beralih jaringan, lepaskan kabel ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Agar pengalaman perangkat menjadi lebih baik, aplikasi dan layanan tetap dapat memindai jaringan Wi-Fi kapan saja, bahkan saat Wi-Fi nonaktif. Anda dapat mengubahnya di setelan pemindaian Wi-Fi. "<annotation id="link">"Ubah"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Pilih pengguna"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-is/strings.xml b/packages/SystemUI/res/values-is/strings.xml
index 100b6f2..7cd5444 100644
--- a/packages/SystemUI/res/values-is/strings.xml
+++ b/packages/SystemUI/res/values-is/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tengist ekki sjálfkrafa eins og er"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Sjá allt"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Aftengdu ethernet til að skipta um net"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Til að bæta tækjaupplifun geta forrit og þjónustur áfram leitað að WiFi-netum hvenær sem er, jafnvel þótt slökkt sé á WiFi. Hægt er að breyta þessu í stillingum WiFi-leitar. "<annotation id="link">"Breyta"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Velja notanda"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-it/strings.xml b/packages/SystemUI/res/values-it/strings.xml
index 15598f0..496b287 100644
--- a/packages/SystemUI/res/values-it/strings.xml
+++ b/packages/SystemUI/res/values-it/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Connessione automatica rete Wi-Fi non attiva al momento"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Mostra tutte"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Per cambiare rete, scollega il cavo Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Per migliorare l\'esperienza con il dispositivo, le app e i servizi possono continuare a cercare reti Wi-Fi in qualsiasi momento, anche quando la connessione Wi-Fi non è attiva. Puoi modificare questa preferenza nelle impostazioni relative alla ricerca di reti Wi-Fi. "<annotation id="link">"Cambia"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Seleziona utente"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-iw/strings.xml b/packages/SystemUI/res/values-iw/strings.xml
index 9f019b4..ec9d323 100644
--- a/packages/SystemUI/res/values-iw/strings.xml
+++ b/packages/SystemUI/res/values-iw/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"‏ה-Wi-Fi לא יתחבר באופן אוטומטי בינתיים"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"הצגת הכול"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"כדי לעבור בין רשתות, צריך לנתק את האתרנט"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"‏כדי לשפר את חוויית השימוש במכשיר, אפליקציות ושירותים יוכלו לחפש רשתות Wi-Fi בכל שלב, גם כאשר ה-Wi-Fi כבוי. אפשר לשנות זאת בהגדרות של חיפוש נקודות Wi-Fi. "<annotation id="link">"שינוי"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"בחירת משתמש"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ja/strings.xml b/packages/SystemUI/res/values-ja/strings.xml
index 94dbd0e..dc8f668 100644
--- a/packages/SystemUI/res/values-ja/strings.xml
+++ b/packages/SystemUI/res/values-ja/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi に自動接続しません"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"すべて表示"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ネットワークを変更するにはイーサネット接続を解除してください"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"デバイスの機能向上のため、アプリやサービスは、Wi-Fi が OFF の場合でも、いつでも Wi-Fi ネットワークをスキャンできます。この設定は Wi-Fi スキャンの設定で変更できます。"<annotation id="link">"変更"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ユーザーの選択"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ka/strings.xml b/packages/SystemUI/res/values-ka/strings.xml
index 889ce24..bcd7af2 100644
--- a/packages/SystemUI/res/values-ka/strings.xml
+++ b/packages/SystemUI/res/values-ka/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi ინტერნეტს დროებით ავტომატურად არ დაუკავშირდება"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ყველას ნახვა"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ქსელების გადასართავად, გაწყვიტეთ Ethernet-თან კავშირი"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"მოწყობილობისგან მიღებული გამოცდილების გასაუმჯობესებლად, აპებსა და სერვისებს მაინც შეუძლია სკანირება Wi‑Fi ქსელების აღმოსაჩენად, ნებისმიერ დროს, მაშინაც კი, როცა Wi‑Fi გამორთულია. ამის შეცვლა Wi-Fi სკანირების პარამეტრებში შეგიძლიათ. "<annotation id="link">"შეცვლა"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"მომხმარებლის არჩევა"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kk/strings.xml b/packages/SystemUI/res/values-kk/strings.xml
index b4f1d92..6685dc3 100644
--- a/packages/SystemUI/res/values-kk/strings.xml
+++ b/packages/SystemUI/res/values-kk/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Әзірше Wi-Fi автоматты түрде қосылмайды."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Барлығын көру"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Желілерді ауыстыру үшін ethernet кабелін ажыратыңыз."</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Құрылғы жұмысын жақсарту үшін қолданбалар мен қызметтер Wi-Fi байланысы өшірулі кезде де Wi-Fi желілерін іздейді. Оны Wi-Fi іздеу параметрлерінен өзгерте аласыз. "<annotation id="link">"Өзгерту"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Пайдаланушыны таңдау"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-km/strings.xml b/packages/SystemUI/res/values-km/strings.xml
index 3896eb0..70d10f9 100644
--- a/packages/SystemUI/res/values-km/strings.xml
+++ b/packages/SystemUI/res/values-km/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi នឹងមិន​ភ្ជាប់ដោយស្វ័យ​ប្រវត្តិក្នុងពេលនេះទេ"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"មើលទាំងអស់"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ដើម្បី​ប្ដូរ​បណ្ដាញ សូមផ្ដាច់​អ៊ីសឺរណិត"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ដើម្បីធ្វើឱ្យ​បទពិសោធន៍ប្រើប្រាស់​ឧបករណ៍ប្រសើរឡើង កម្មវិធី និងសេវាកម្ម​នៅតែអាចស្កេនរក​បណ្ដាញ Wi‑Fi បានគ្រប់ពេល ទោះបីជា​នៅពេលដែលបិទ Wi‑Fi ក៏ដោយ។ អ្នកអាចប្ដូរវាបាន​នៅក្នុង​ការកំណត់​ការស្កេន Wi‑Fi។ "<annotation id="link">"ប្ដូរ"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ជ្រើសរើសអ្នកប្រើប្រាស់"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-kn/strings.xml b/packages/SystemUI/res/values-kn/strings.xml
index 9d90884..3a1e6a6 100644
--- a/packages/SystemUI/res/values-kn/strings.xml
+++ b/packages/SystemUI/res/values-kn/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"ಪುನರಾರಂಭಿಸಿ"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ಸೆಟ್ಟಿಂಗ್‌ಗಳು"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ಅವರ <xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಲಾಗುತ್ತಿದೆ"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g> ರಲ್ಲಿ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ಪ್ಲೇ ಮಾಡಿ"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ಅನ್ನು ತೆರೆಯಿರಿ"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> ಅವರ <xliff:g id="SONG_NAME">%1$s</xliff:g> ಹಾಡನ್ನು <xliff:g id="APP_LABEL">%3$s</xliff:g> ನಲ್ಲಿ ಪ್ಲೇ ಮಾಡಿ"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ಸದ್ಯದ ಮಟ್ಟಿಗೆ ವೈ-ಫೈ ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಕನೆಕ್ಟ್ ಆಗುವುದಿಲ್ಲ"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ಎಲ್ಲವನ್ನೂ ನೋಡಿ"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ನೆಟ್‌ವರ್ಕ್‌ಗಳನ್ನು ಬದಲಿಸಲು, ಇಥರ್ನೆಟ್ ಅನ್ನು ಡಿಸ್‌ಕನೆಕ್ಟ್ ಮಾಡಿ"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ವೈ-ಫೈ ಆಫ್ ಇದ್ದಾಗಲೂ ಸಹ, ಸಾಧನದ ಅನುಭವವನ್ನು ಸುಧಾರಿಸಲು, ಆ್ಯಪ್‌ಗಳು ಮತ್ತು ಸೇವೆಗಳು ಯಾವಾಗ ಬೇಕಾದರೂ ಸಹ ವೈ-ಫೈ ನೆಟ್‌ವರ್ಕ್‌ಗಳಿಗಾಗಿ ಸ್ಕ್ಯಾನ್ ಮಾಡಬಹುದು. ನೀವು ಇದನ್ನು ವೈ-ಫೈ ಸ್ಕ್ಯಾನಿಂಗ್ ಸೆಟ್ಟಿಂಗ್‌ಗಳಲ್ಲಿ ಬದಲಾಯಿಸಬಹುದು. "<annotation id="link">"ಬದಲಿಸಿ"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ಬಳಕೆದಾರ ಆಯ್ಕೆಮಾಡಿ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ko/strings.xml b/packages/SystemUI/res/values-ko/strings.xml
index 4ca855d..4b705fb 100644
--- a/packages/SystemUI/res/values-ko/strings.xml
+++ b/packages/SystemUI/res/values-ko/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"지금은 Wi-Fi가 자동으로 연결되지 않습니다."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"모두 보기"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"네트워크를 전환하려면 이더넷을 연결 해제하세요."</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"기기 환경을 개선하기 위해 Wi‑Fi가 꺼져 있을 때도 앱과 서비스에서 Wi‑Fi 네트워크를 검색할 수 있습니다. 이 설정은 Wi‑Fi 검색 설정에서 변경할 수 있습니다. "<annotation id="link">"변경"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"사용자 선택"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ky/strings.xml b/packages/SystemUI/res/values-ky/strings.xml
index 77a933c..58114d8 100644
--- a/packages/SystemUI/res/values-ky/strings.xml
+++ b/packages/SystemUI/res/values-ky/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi азырынча автоматтык түрдө туташпайт"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Баарын көрүү"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Башка тармактарга которулуу үчүн Ethernet кабелин ажыратыңыз"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Түзмөктүн колдонулушун жакшыртуу үчүн колдонмолор менен кызматтар Wi‑Fi өчүп турса да зымсыз тармактарды издей беришет. Аны Wi-Fi тармактарын издөө жөндөөлөрүнөн өзгөртө аласыз. "<annotation id="link">"Өзгөртүү"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Колдонуучуну тандоо"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-land/styles.xml b/packages/SystemUI/res/values-land/styles.xml
index 82cba58..f3d83645 100644
--- a/packages/SystemUI/res/values-land/styles.xml
+++ b/packages/SystemUI/res/values-land/styles.xml
@@ -25,12 +25,6 @@
         <item name="android:layout_gravity">center_horizontal</item>
     </style>
 
-    <style name="DockedDividerHandle">
-        <item name="android:layout_gravity">center_vertical</item>
-        <item name="android:layout_width">48dp</item>
-        <item name="android:layout_height">96dp</item>
-    </style>
-
     <style name="DockedDividerMinimizedShadow">
         <item name="android:layout_width">8dp</item>
         <item name="android:layout_height">match_parent</item>
diff --git a/packages/SystemUI/res/values-lo/strings.xml b/packages/SystemUI/res/values-lo/strings.xml
index 351b198..9ff47ac 100644
--- a/packages/SystemUI/res/values-lo/strings.xml
+++ b/packages/SystemUI/res/values-lo/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi ຈະບໍ່ເຊື່ອມຕໍ່ອັດຕະໂນມັດສຳລັບຕອນນີ້"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ເບິ່ງທັງໝົດ"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ເພື່ອສະຫຼັບເຄືອຂ່າຍ, ໃຫ້ຕັດການເຊື່ອມຕໍ່ອີເທີເນັດກ່ອນ"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ເພື່ອປັບປຸງປະສົບການອຸປະກອນ, ແອັບ ແລະ ບໍລິການຍັງຄົງສາມາດສະແກນຫາເຄືອຂ່າຍ Wi‑Fi ຕອນໃດກໍໄດ້, ເຖິງແມ່ນວ່າຈະປິດ Wi‑Fi ໄວ້ກໍຕາມ. ທ່ານສາມາດປ່ຽນສິ່ງນີ້ໄດ້ໃນການຕັ້ງຄ່າການສະແກນ Wi‑Fi. "<annotation id="link">"ປ່ຽນ"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ເລືອກຜູ້ໃຊ້"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lt/strings.xml b/packages/SystemUI/res/values-lt/strings.xml
index 3e4d3ffb..0161aaf 100644
--- a/packages/SystemUI/res/values-lt/strings.xml
+++ b/packages/SystemUI/res/values-lt/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"„Wi-Fi“ šiuo metu nebus prijungtas automatiškai"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Žiūrėti viską"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Norėdami perjungti tinklus, atjunkite eternetą"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Kad pagerintų įrenginio funkcijas, programos ir paslaugos vis tiek gali bet kada nuskaityti ieškodamos „Wi‑Fi“ tinklų, net jei „Wi‑Fi“ išjungtas. Tai galite pakeisti „Wi-Fi“ nuskaitymo nustatymuose. "<annotation id="link">"Pakeisti"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Naudotojo pasirinkimas"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-lv/strings.xml b/packages/SystemUI/res/values-lv/strings.xml
index f0d1bba..2ff48e3 100644
--- a/packages/SystemUI/res/values-lv/strings.xml
+++ b/packages/SystemUI/res/values-lv/strings.xml
@@ -1185,5 +1185,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi savienojums īslaicīgi netiks izveidots automātiski."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Visu tīklu skatīšana"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Lai pārslēgtu tīklus, atvienojiet tīkla Ethernet vadu."</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Lai uzlabotu ierīces lietošanas iespējas, lietotnes un pakalpojumi joprojām varēs meklēt Wi‑Fi tīklus jebkurā laikā, pat ja Wi‑Fi būs izslēgts. Varat to mainīt Wi‑Fi meklēšanas iestatījumos. "<annotation id="link">"Mainīt"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Lietotāja atlase"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mk/strings.xml b/packages/SystemUI/res/values-mk/strings.xml
index 29feaec..6c495a7 100644
--- a/packages/SystemUI/res/values-mk/strings.xml
+++ b/packages/SystemUI/res/values-mk/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi нема да се поврзува автоматски засега"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Прикажи ги сите"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"За промена на мрежата, прекинете ја врската со етернетот"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"За да се подобри доживувањето на уредот, апликациите и услугите може сѐ уште да скенираат за Wi‑Fi мрежи во секое време, дури и кога Wi‑Fi е исклучено. Може да го промените ова во поставките за „Скенирање за Wi-Fi“. "<annotation id="link">"Промени"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Изберете корисник"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ml/strings.xml b/packages/SystemUI/res/values-ml/strings.xml
index 674ed84..db338ef 100644
--- a/packages/SystemUI/res/values-ml/strings.xml
+++ b/packages/SystemUI/res/values-ml/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"വൈഫൈ ഇപ്പോൾ സ്വയമേവ കണക്റ്റ് ചെയ്യില്ല"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"എല്ലാം കാണുക"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"മറ്റ് നെറ്റ്‌വർക്കുകളിലേക്ക് മാറാൻ, ഇതർനെറ്റ് വിച്ഛേദിക്കുക"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ഉപകരണ അനുഭവം മെച്ചപ്പെടുത്താൻ, വൈഫൈ ഓഫാക്കിയിരിക്കുമ്പോൾ പോലും ആപ്പുകൾക്കും സേവനങ്ങൾക്കും വൈഫൈ നെറ്റ്‌വർക്കുകൾ കണ്ടെത്താൻ ഏത് സമയത്തും സ്‌കാൻ ചെയ്യാനാകും. നിങ്ങൾക്ക് ഇത് വൈഫൈ സ്‌കാനിംഗ് ക്രമീകരണത്തിൽ മാറ്റാം. "<annotation id="link">"മാറ്റുക"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ഉപയോക്താവിനെ തിരഞ്ഞെടുക്കൂ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mn/strings.xml b/packages/SystemUI/res/values-mn/strings.xml
index 9cce14a..b34b75b 100644
--- a/packages/SystemUI/res/values-mn/strings.xml
+++ b/packages/SystemUI/res/values-mn/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi-г одоогоор автоматаар холбохгүй"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Бүгдийг харах"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Сүлжээг сэлгэхийн тулд этернэтийг салгана уу"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Төхөөрөмжийн туршлагыг сайжруулахын тулд аппууд болон үйлчилгээнүүд нь Wi-Fi сүлжээг хүссэн үедээ буюу Wi-Fi-г унтраалттай байсан ч скан хийх боломжтой хэвээр байна. Та үүнийг Wi-Fi скан хийх тохиргоонд өөрчлөх боломжтой. "<annotation id="link">"Өөрчлөх"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Хэрэглэгч сонгох"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-mr/strings.xml b/packages/SystemUI/res/values-mr/strings.xml
index 9753209..674290d 100644
--- a/packages/SystemUI/res/values-mr/strings.xml
+++ b/packages/SystemUI/res/values-mr/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"सध्या वाय-फाय ऑटो-कनेक्ट होणार नाही"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"सर्व पहा"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"नेटवर्क स्विच करण्यासाठी, इथरनेट केबल डिस्कनेक्ट करा"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"डिव्हाइसच्या अनुभवामध्ये सुधारणा करण्यासाठी, वाय-फाय बंद असले तरीही ॲप्स आणि सेवा या कधीही वाय-फाय नेटवर्क स्कॅन करू शकतात. तुम्ही हे वाय-फाय स्कॅनिंग सेटिंग्जमध्ये बदलू शकता. "<annotation id="link">"बदला"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"वापरकर्ता निवडा"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ms/strings.xml b/packages/SystemUI/res/values-ms/strings.xml
index 4418273..f349040 100644
--- a/packages/SystemUI/res/values-ms/strings.xml
+++ b/packages/SystemUI/res/values-ms/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi tidak akan disambungkan secara automatik buat masa ini"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Lihat semua"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Untuk menukar rangkaian, putuskan sambungan ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Untuk meningkatkan pengalaman peranti, apl dan perkhidmatan masih dapat melakukan imbasan untuk mengesan rangkaian Wi-Fi pada bila-bila masa, meskipun apabila Wi-Fi dimatikan. Anda boleh menukar tetapan ini dalam tetapan pengimbasan Wi-Fi. "<annotation id="link">"Tukar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Pilih pengguna"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-my/strings.xml b/packages/SystemUI/res/values-my/strings.xml
index 0fed37b..b434294 100644
--- a/packages/SystemUI/res/values-my/strings.xml
+++ b/packages/SystemUI/res/values-my/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi က လောလောဆယ် အလိုအလျောက် ချိတ်ဆက်မည်မဟုတ်ပါ"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"အားလုံးကြည့်ရန်"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ကွန်ရက်ပြောင်းရန် အီသာနက်ကို ချိတ်ဆက်မှုဖြုတ်ပါ"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"စက်ပစ္စည်းကို ပိုမိုကောင်းမွန်စွာ အသုံးပြုနိုင်ရန် Wi-Fi ပိတ်ထားသည့်တိုင် အက်ပ်နှင့် ဝန်ဆောင်မှုများက Wi-Fi ကွန်ရက်များကို အချိန်မရွေး စကင်ဖတ်နိုင်သည်။ ၎င်းကို Wi-Fi ရှာဖွေခြင်း ဆက်တင်များတွင် ပြောင်းနိုင်သည်။ "<annotation id="link">"ပြောင်းရန်"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"အသုံးပြုသူ ရွေးခြင်း"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nb/strings.xml b/packages/SystemUI/res/values-nb/strings.xml
index c37c81c..c64eb1c 100644
--- a/packages/SystemUI/res/values-nb/strings.xml
+++ b/packages/SystemUI/res/values-nb/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"Gjenoppta"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"Innstillinger"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="SONG_NAME">%1$s</xliff:g> av <xliff:g id="ARTIST_NAME">%2$s</xliff:g> spilles av fra <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="ELAPSED_TIME">%1$s</xliff:g> av <xliff:g id="TOTAL_TIME">%2$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"Spill av"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"Åpne <xliff:g id="APP_LABEL">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"Spill av <xliff:g id="SONG_NAME">%1$s</xliff:g> av <xliff:g id="ARTIST_NAME">%2$s</xliff:g> fra <xliff:g id="APP_LABEL">%3$s</xliff:g>"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi kobles ikke til automatisk inntil videre"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Se alle"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"For å bytte nettverk, koble fra Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"For å forbedre brukeropplevelsen på enheten kan apper og tjenester søke etter Wi-Fi-nettverk når som helst – også når Wi-Fi er slått av. Du kan endre dette i innstillingene for Wi-Fi-skanning. "<annotation id="link">"Bytt"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Velg bruker"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ne/strings.xml b/packages/SystemUI/res/values-ne/strings.xml
index 2405d50..fad9226 100644
--- a/packages/SystemUI/res/values-ne/strings.xml
+++ b/packages/SystemUI/res/values-ne/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"केही समयका लागि Wi-Fi स्वतः कनेक्ट हुँदैन"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"सबै नेटवर्क हेर्नुहोस्"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"नेटवर्क बदल्न इथरनेट डिस्कनेक्ट गर्नुहोस्"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"डिभाइस प्रयोगको अनुभवमा गुणस्तर सुधार गर्न, एप तथा सेवाहरूले अझै पनि जुनसुकै बेला (Wi‑Fi अफ भएका बेलामा पनि) Wi‑Fi नेटवर्क खोज्न सक्छन्। तपाईं यसलाई Wi‑Fi स्क्यानिङका सेटिङमा गई परिवर्तन गर्न सक्नुहुन्छ। "<annotation id="link">"बदल्नुहोस्"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"प्रयोगकर्ता चयन गर्नु…"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-nl/strings.xml b/packages/SystemUI/res/values-nl/strings.xml
index b60a76d..2dd2bb7 100644
--- a/packages/SystemUI/res/values-nl/strings.xml
+++ b/packages/SystemUI/res/values-nl/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wifi maakt momenteel niet automatisch verbinding"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Alles tonen"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Verbreek de ethernetverbinding om van netwerk te wisselen"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Apps en services kunnen nog steeds op elk moment scannen op wifi-netwerken, zelfs als wifi uitstaat, om de apparaatfunctionaliteit te verbeteren. Je kunt dit aanpassen in de instellingen voor wifi-scannen. "<annotation id="link">"Wijzigen"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Gebruiker selecteren"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-or/strings.xml b/packages/SystemUI/res/values-or/strings.xml
index f276a22..ee96b31 100644
--- a/packages/SystemUI/res/values-or/strings.xml
+++ b/packages/SystemUI/res/values-or/strings.xml
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"ପୁଣି ଆରମ୍ଭ କରନ୍ତୁ"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"ସେଟିଂସ୍"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ରୁ <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ଙ୍କ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚାଲୁଛି"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>ରୁ <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ଚଲାନ୍ତୁ"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g> ଖୋଲନ୍ତୁ"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g>ରୁ <xliff:g id="ARTIST_NAME">%2$s</xliff:g>ଙ୍କ <xliff:g id="SONG_NAME">%1$s</xliff:g> ଚଲାନ୍ତୁ"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ବର୍ତ୍ତମାନ ପାଇଁ ୱାଇ-ଫାଇ ସ୍ୱତଃ-ସଂଯୋଗ ହେବ ନାହିଁ"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ସବୁ ଦେଖନ୍ତୁ"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ନେଟୱାର୍କ ସ୍ୱିଚ୍ କରିବାକୁ, ଇଥରନେଟ୍ ବିଚ୍ଛିନ୍ନ କରନ୍ତୁ"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ଡିଭାଇସ ଅନୁଭୂତିକୁ ଉନ୍ନତ କରିବା ପାଇଁ, ୱାଇ-ଫାଇ ବନ୍ଦ ଥିଲେ ମଧ୍ୟ ଆପ ଓ ସେବାଗୁଡ଼ିକ ଏବେ ବି ଯେ କୌଣସି ସମୟରେ ୱାଇ-ଫାଇ ନେଟୱାର୍କ ପାଇଁ ସ୍କାନ କରିପାରିବ। ଆପଣ ଏହାକୁ ୱାଇ-ଫାଇ ସ୍କାନିଂ ସେଟିଂସରେ ପରିବର୍ତ୍ତନ କରିପାରିବେ। "<annotation id="link">"ପରିବର୍ତ୍ତନ କରନ୍ତୁ"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ଉପଯୋଗକର୍ତ୍ତା ଚୟନ କର"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pa/strings.xml b/packages/SystemUI/res/values-pa/strings.xml
index 0ca4f7d..80fae3d 100644
--- a/packages/SystemUI/res/values-pa/strings.xml
+++ b/packages/SystemUI/res/values-pa/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ਫ਼ਿਲਹਾਲ ਵਾਈ-ਫਾਈ ਸਵੈ-ਕਨੈਕਟ ਨਹੀਂ ਹੋਵੇਗਾ"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ਸਭ ਦੇਖੋ"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ਨੈੱਟਵਰਕਾਂ ਨੂੰ ਬਦਲਣ ਲਈ, ਈਥਰਨੈੱਟ ਨੂੰ ਡਿਸਕਨੈਕਟ ਕਰੋ"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"ਡੀਵਾਈਸ ਦੇ ਅਨੁਭਵ ਨੂੰ ਬਿਹਤਰ ਬਣਾਉਣ ਲਈ, ਐਪਾਂ ਅਤੇ ਸੇਵਾਵਾਂ ਕਿਸੇ ਵੀ ਸਮੇਂ ਵਾਈ-ਫਾਈ ਨੈੱਟਵਰਕਾਂ ਲਈ ਸਕੈਨ ਕਰ ਸਕਦੀਆਂ ਹਨ, ਭਾਵੇਂ ਵਾਈ-ਫਾਈ ਬੰਦ ਹੀ ਕਿਉਂ ਨਾ ਹੋਵੇ। ਤੁਸੀਂ ਇਸ ਨੂੰ ਵਾਈ‑ਫਾਈ ਸਕੈਨਿੰਗ ਸੈਟਿੰਗਾਂ ਵਿੱਚ ਜਾ ਕੇ ਬਦਲ ਸਕਦੇ ਹੋ। "<annotation id="link">"ਬਦਲੋ"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"ਵਰਤੋਂਕਾਰ ਚੁਣੋ"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pl/strings.xml b/packages/SystemUI/res/values-pl/strings.xml
index 73b538f..7f8f47b 100644
--- a/packages/SystemUI/res/values-pl/strings.xml
+++ b/packages/SystemUI/res/values-pl/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi nie będzie na razie włączać się automatycznie"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Pokaż wszystko"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Aby przełączać sieci, odłącz Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Aby zapewnić Ci większy komfort korzystania z urządzenia, aplikacje i usługi mogą nadal wyszukiwać sieci Wi-Fi w pobliżu nawet wtedy, gdy Wi-Fi jest wyłączone. Możesz to zmienić w ustawieniach skanowania Wi-Fi. "<annotation id="link">"Zmień"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Wybierz użytkownika"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rBR/strings.xml b/packages/SystemUI/res/values-pt-rBR/strings.xml
index 0205e8c..41e5a77 100644
--- a/packages/SystemUI/res/values-pt-rBR/strings.xml
+++ b/packages/SystemUI/res/values-pt-rBR/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A conexão automática ao Wi-Fi ficará indisponível"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desconecte o cabo Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência no dispositivo, os apps e serviços ainda podem procurar redes Wi-Fi a qualquer momento, mesmo quando o Wi-Fi estiver desativado. Você pode mudar essa opção nas configurações de busca por Wi-Fi. "<annotation id="link">"Mudar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecionar usuário"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt-rPT/strings.xml b/packages/SystemUI/res/values-pt-rPT/strings.xml
index 3be4e72..fa10607 100644
--- a/packages/SystemUI/res/values-pt-rPT/strings.xml
+++ b/packages/SystemUI/res/values-pt-rPT/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Por agora, o Wi-Fi não irá estabelecer lig. automaticamente"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Veja tudo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desligue a Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência do dispositivo, as apps e os serviços podem continuar a procurar redes Wi-Fi em qualquer altura, mesmo quando o Wi-Fi está desativado. Pode alterar esta opção nas definições de procura de Wi-Fi. "<annotation id="link">"Alterar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecione utilizador"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-pt/strings.xml b/packages/SystemUI/res/values-pt/strings.xml
index 0205e8c..41e5a77 100644
--- a/packages/SystemUI/res/values-pt/strings.xml
+++ b/packages/SystemUI/res/values-pt/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"A conexão automática ao Wi-Fi ficará indisponível"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Ver tudo"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para mudar de rede, desconecte o cabo Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para melhorar a experiência no dispositivo, os apps e serviços ainda podem procurar redes Wi-Fi a qualquer momento, mesmo quando o Wi-Fi estiver desativado. Você pode mudar essa opção nas configurações de busca por Wi-Fi. "<annotation id="link">"Mudar"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Selecionar usuário"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ro/strings.xml b/packages/SystemUI/res/values-ro/strings.xml
index 9630356..0a7ab90 100644
--- a/packages/SystemUI/res/values-ro/strings.xml
+++ b/packages/SystemUI/res/values-ro/strings.xml
@@ -1185,5 +1185,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Deocamdată, Wi-Fi nu se poate conecta automat"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Afișează-le pe toate"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Pentru a schimba rețeaua, deconectați ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Pentru a îmbunătăți experiența cu dispozitivul, aplicațiile și serviciile pot să caute în continuare rețele Wi‑Fi chiar și atunci când conexiunea Wi-Fi este dezactivată. Puteți să schimbați acest aspect din setările pentru căutarea de rețele Wi-Fi. "<annotation id="link">"Schimbați"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Alegeți utilizatorul"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ru/strings.xml b/packages/SystemUI/res/values-ru/strings.xml
index a386d5a..7767761 100644
--- a/packages/SystemUI/res/values-ru/strings.xml
+++ b/packages/SystemUI/res/values-ru/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Подключение по Wi-Fi не установится автоматически."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Показать все"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Чтобы переключиться между сетями, отключите кабель Ethernet."</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Чтобы улучшать работу устройства, приложения и сервисы могут искать беспроводные сети в любое время, даже если вы отключили Wi‑Fi. Чтобы запретить это, отключите поиск сетей Wi‑Fi. "<annotation id="link">"Открыть настройки"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Выберите профиль"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-si/strings.xml b/packages/SystemUI/res/values-si/strings.xml
index ec03c53..a42544e 100644
--- a/packages/SystemUI/res/values-si/strings.xml
+++ b/packages/SystemUI/res/values-si/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi දැනට ස්වයං-සබැඳි නොවනු ඇත"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"සියල්ල බලන්න"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ජාල මාරු කිරීමට, ඊතර්නෙට් විසන්ධි කරන්න"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"උපාංග අත්දැකීම වැඩි දියුණු කිරිමට, Wi‑Fi ක්‍රියාවිරහිත විට පවා, ඕනෑම අවස්ථාවක Wi‑Fi ජාල සඳහා ස්කෑන් කිරීමට යෙදුම් සහ සේවාවලට හැකිය. ඔබට මෙය Wi‑Fi ස්කෑන් කිරීමේ සැකසීම් තුළ වෙනස් කළ හැකිය. "<annotation id="link">"වෙනස් කරන්න"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"පරිශීලක තෝරන්න"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sk/strings.xml b/packages/SystemUI/res/values-sk/strings.xml
index dd47219..8bb7b4a 100644
--- a/packages/SystemUI/res/values-sk/strings.xml
+++ b/packages/SystemUI/res/values-sk/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi‑Fi sa teraz automaticky nepripojí"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Zobraziť všetko"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ak chcete prepnúť siete, odpojte ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Aplikácie a služby môžu kedykoľvek vyhľadávať siete Wi‑Fi (a to aj vtedy, keď je pripojenie Wi‑Fi vypnuté), čím zlepšujú prostredie v zariadení. Môžete to zmeniť v nastaveniach vyhľadávania sietí Wi‑Fi. "<annotation id="link">"Zmeniť"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Vyberte používateľa"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sl/strings.xml b/packages/SystemUI/res/values-sl/strings.xml
index b55c923..1e5c20e 100644
--- a/packages/SystemUI/res/values-sl/strings.xml
+++ b/packages/SystemUI/res/values-sl/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Vmesnik Wi-Fi trenutno ne bo samodejno vzpostavil povezave."</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Prikaz vseh omrežij"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Če želite preklopiti omrežje, prekinite ethernetno povezavo."</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Za izboljšano izkušnjo pri uporabi naprave lahko aplikacije in storitve kadar koli iščejo omrežja Wi‑Fi, tudi ko je Wi‑Fi izklopljen. To lahko spremenite v nastavitvah iskanja omrežij Wi-Fi. "<annotation id="link">"Spremeni"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Izberite uporabnika"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sq/strings.xml b/packages/SystemUI/res/values-sq/strings.xml
index b728cf2..a8b0db1 100644
--- a/packages/SystemUI/res/values-sq/strings.xml
+++ b/packages/SystemUI/res/values-sq/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi nuk do të lidhet automatikisht për momentin"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Shiko të gjitha"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Për të ndërruar rrjetet, shkëput Ethernet-in"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Për të përmirësuar përvojën e pajisjes, aplikacionet dhe shërbimet mund të vazhdojnë të skanojnë për rrjete Wi-Fi në çdo kohë, edhe kur Wi-Fi është joaktiv. Mund ta ndryshosh këtë te cilësimet e skanimit të Wi-Fi. "<annotation id="link">"Ndrysho"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Zgjidh përdoruesin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sr/strings.xml b/packages/SystemUI/res/values-sr/strings.xml
index 8658df6..c2d6654 100644
--- a/packages/SystemUI/res/values-sr/strings.xml
+++ b/packages/SystemUI/res/values-sr/strings.xml
@@ -1185,5 +1185,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WiFi тренутно не може да се аутоматски повеже"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Погледајте све"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Да бисте променили мрежу, прекините етернет везу"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Ради бољег доживљаја уређаја, апликације и услуге и даље могу да траже WiFi мреже у било ком тренутку, чак и када је WiFi искључен. То можете да промените у подешавањима WiFi скенирања. "<annotation id="link">"Промените"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Изаберите корисника"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sv/strings.xml b/packages/SystemUI/res/values-sv/strings.xml
index e1ecff9..7474e2f 100644
--- a/packages/SystemUI/res/values-sv/strings.xml
+++ b/packages/SystemUI/res/values-sv/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Du ansluts inte till wifi automatiskt för närvarande"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Visa alla"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Koppla bort Ethernet för att växla nätverk"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"I syfte att förbättra upplevelsen med enheten kan appar och tjänster fortfarande söka efter wifi-nätverk när som helst, även om wifi har inaktiverats. "<annotation id="link">"Ändra"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Välj användare"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw/strings.xml b/packages/SystemUI/res/values-sw/strings.xml
index 7b2f287..85fc395 100644
--- a/packages/SystemUI/res/values-sw/strings.xml
+++ b/packages/SystemUI/res/values-sw/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi haitaunganishwa kiotomatiki kwa sasa"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Angalia yote"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ili kubadili mitandao, tenganisha ethaneti"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Ili kuboresha hali ya matumizi ya kifaa, programu na huduma bado zinaweza kutafuta mitandao ya Wi‑Fi wakati wowote, hata wakati umezima Wi‑Fi. Unaweza kubadilisha mipangilio hii katika mipangilio ya kutafuta Wi-Fi. "<annotation id="link">"Badilisha"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Chagua mtumiaji"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-sw600dp/dimens.xml b/packages/SystemUI/res/values-sw600dp/dimens.xml
index 85f8f09..4e57861 100644
--- a/packages/SystemUI/res/values-sw600dp/dimens.xml
+++ b/packages/SystemUI/res/values-sw600dp/dimens.xml
@@ -105,5 +105,5 @@
     <dimen name="qs_detail_margin_top">0dp</dimen>
 
     <!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
-    <dimen name="large_dialog_width">624dp</dimen>
+    <dimen name="large_dialog_width">504dp</dimen>
 </resources>
diff --git a/packages/SystemUI/res/values-ta/strings.xml b/packages/SystemUI/res/values-ta/strings.xml
index 815a6f0..413149b 100644
--- a/packages/SystemUI/res/values-ta/strings.xml
+++ b/packages/SystemUI/res/values-ta/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"தற்போதைக்கு வைஃபை தானாக இணைக்கப்படாது"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"அனைத்தையும் காட்டு"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"நெட்வொர்க்குகளை மாற்ற ஈதர்நெட் இணைப்பைத் துண்டிக்கவும்"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"சாதன அனுபவத்தை மேம்படுத்த, வைஃபை ஆஃப் செய்யப்பட்டிருந்தாலும்கூட எந்த நேரத்திலும் ஆப்ஸும் சேவைகளும் வைஃபை நெட்வொர்க்குகளைத் தேடலாம். வைஃபை ஸ்கேனிங் அமைப்புகளில் இதை மாற்றிக் கொள்ளலாம். "<annotation id="link">"மாற்று"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"பயனரைத் தேர்வுசெய்க"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-te/strings.xml b/packages/SystemUI/res/values-te/strings.xml
index b1639ff..41f45d7 100644
--- a/packages/SystemUI/res/values-te/strings.xml
+++ b/packages/SystemUI/res/values-te/strings.xml
@@ -563,30 +563,30 @@
     <string name="monitoring_description_ca_certificate" msgid="448923057059097497">"ఈ పరికరంలో ప్రమాణపత్ర అధికారం ఇన్‌స్టాల్ చేయబడింది. మీ సురక్షిత నెట్‌వర్క్ ట్రాఫిక్ పర్యవేక్షించబడవచ్చు లేదా సవరించబడవచ్చు."</string>
     <string name="monitoring_description_management_network_logging" msgid="216983105036994771">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్‌ని పర్యవేక్షించగల నెట్‌వర్క్ లాగింగ్‌ని ఆన్ చేశారు."</string>
     <string name="monitoring_description_managed_profile_network_logging" msgid="6932303843097006037">"మీ అడ్మిన్ నెట్‌వర్క్ లాగింగ్‌ను ఆన్ చేశారు, ఇది మీ వర్క్ ప్రొఫైల్‌లోని ట్రాఫిక్‌ను పర్యవేక్షిస్తుంది కానీ మీ వ్యక్తిగత ప్రొఫైల్‌లో కాదు."</string>
-    <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
-    <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"మీరు ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP_0">%1$s</xliff:g> మరియు <xliff:g id="VPN_APP_1">%2$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string>
-    <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"మీ కార్యాలయ ప్రొఫైల్ ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
-    <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"మీ వ్యక్తిగత ప్రొఫైల్ ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
+    <string name="monitoring_description_named_vpn" msgid="5749932930634037027">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
+    <string name="monitoring_description_two_named_vpns" msgid="3516830755681229463">"మీరు ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP_0">%1$s</xliff:g> మరియు <xliff:g id="VPN_APP_1">%2$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string>
+    <string name="monitoring_description_managed_profile_named_vpn" msgid="368812367182387320">"మీ కార్యాలయ ప్రొఫైల్ ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
+    <string name="monitoring_description_personal_profile_named_vpn" msgid="8179722332380953673">"మీ వ్యక్తిగత ప్రొఫైల్ ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడింది."</string>
     <string name="monitoring_description_do_header_generic" msgid="6130190408164834986">"మీ పరికరం <xliff:g id="DEVICE_OWNER_APP">%1$s</xliff:g> ద్వారా నిర్వహించబడుతోంది."</string>
     <string name="monitoring_description_do_header_with_name" msgid="2696255132542779511">"<xliff:g id="ORGANIZATION_NAME">%1$s</xliff:g> మీ పరికరాన్ని నిర్వహించడానికి <xliff:g id="DEVICE_OWNER_APP">%2$s</xliff:g>ని ఉపయోగిస్తుంది."</string>
     <string name="monitoring_description_do_body" msgid="7700878065625769970">"మీ పరికరంతో అనుబంధించబడిన సెట్టింగ్‌లు, కార్పొరేట్ యాక్సెస్, యాప్‌లు, డేటా మరియు మీ పరికరం యొక్క లొకేషన్ సమాచారాన్ని మీ అడ్మిన్ పర్యవేక్షించగలరు, మేనేజ్ చేయగలరు."</string>
     <string name="monitoring_description_do_learn_more_separator" msgid="1467280496376492558">" "</string>
     <string name="monitoring_description_do_learn_more" msgid="645149183455573790">"మరింత తెలుసుకోండి"</string>
-    <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
+    <string name="monitoring_description_do_body_vpn" msgid="7699280130070502303">"మీరు <xliff:g id="VPN_APP">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="monitoring_description_vpn_settings_separator" msgid="8292589617720435430">" "</string>
     <string name="monitoring_description_vpn_settings" msgid="5264167033247632071">"VPN సెట్టింగ్‌లను తెరవండి"</string>
     <string name="monitoring_description_ca_cert_settings_separator" msgid="7107390013344435439">" "</string>
     <string name="monitoring_description_ca_cert_settings" msgid="8329781950135541003">"విశ్వసనీయ ఆధారాలను తెరువు"</string>
     <string name="monitoring_description_network_logging" msgid="577305979174002252">"మీ నిర్వాహకులు మీ పరికరంలోని ట్రాఫిక్‌ని పర్యవేక్షించగల నెట్‌వర్క్ లాగింగ్‌ని ఆన్ చేశారు.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి."</string>
-    <string name="monitoring_description_vpn" msgid="1685428000684586870">"మీరు VPN కనెక్షన్ సెటప్ చేయడానికి ఒక యాప్‌నకు అనుమతి ఇచ్చారు.\n\nఈ యాప్ ఇమెయిల్‌లు,యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ డివైజ్ మరియు నెట్‌వర్క్ యాక్టివిటీని పర్యవేక్షించగలదు."</string>
-    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ద్వారా మీ కార్యాలయ ప్రొఫైల్ నిర్వహించబడుతోంది.\n\nఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల సామర్థ్యం మీ నిర్వాహకులకు ఉంది.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి.\n\nమీరు VPNకి కూడా కనెక్ట్ అయ్యారు, ఇది మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
+    <string name="monitoring_description_vpn" msgid="1685428000684586870">"మీరు VPN కనెక్షన్ సెటప్ చేయడానికి ఒక యాప్‌నకు అనుమతి ఇచ్చారు.\n\nఈ యాప్ ఈమెయిళ్లు,యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ డివైజ్ మరియు నెట్‌వర్క్ యాక్టివిటీని పర్యవేక్షించగలదు."</string>
+    <string name="monitoring_description_vpn_profile_owned" msgid="4964237035412372751">"<xliff:g id="ORGANIZATION">%1$s</xliff:g> ద్వారా మీ కార్యాలయ ప్రొఫైల్ నిర్వహించబడుతోంది.\n\nఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల సామర్థ్యం మీ నిర్వాహకులకు ఉంది.\n\nమరింత సమాచారం కావాలంటే, మీ నిర్వాహకులను సంప్రదించండి.\n\nమీరు VPNకి కూడా కనెక్ట్ అయ్యారు, ఇది మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
     <string name="monitoring_description_parental_controls" msgid="8184693528917051626">"ఈ పరికరాన్ని మీ తల్లి/తండ్రి మేనేజ్ చేస్తున్నారు. మీ తల్లి/తండ్రి, మీరు ఉపయోగించే యాప్‌లు, మీ లొకేషన్, అలాగే మీ పరికర వినియోగ వ్యవధి వంటి సమాచారాన్ని చూడగలరు, మేనేజ్ చేయగలరు."</string>
     <string name="legacy_vpn_name" msgid="4174223520162559145">"VPN"</string>
-    <string name="monitoring_description_app" msgid="376868879287922929">"మీరు ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string>
-    <string name="monitoring_description_app_personal" msgid="1970094872688265987">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌‍సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
-    <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
-    <string name="monitoring_description_app_work" msgid="3713084153786663662">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ కార్యాలయ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string>
-    <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఇమెయిల్‌లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ కార్యాలయ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>కి కూడా మీరు కనెక్ట్ చేయబడ్డారు."</string>
+    <string name="monitoring_description_app" msgid="376868879287922929">"మీరు ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు."</string>
+    <string name="monitoring_description_app_personal" msgid="1970094872688265987">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌‍సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
+    <string name="branded_monitoring_description_app_personal" msgid="1703511985892688885">"మీరు <xliff:g id="APPLICATION">%1$s</xliff:g>కి కనెక్ట్ చేయబడ్డారు, ఇది ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగలదు."</string>
+    <string name="monitoring_description_app_work" msgid="3713084153786663662">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ కార్యాలయ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమరింత సమాచారం కోసం, మీ నిర్వాహకులను సంప్రదించండి."</string>
+    <string name="monitoring_description_app_personal_work" msgid="6175816356939166101">"మీ కార్యాలయ ప్రొఫైల్ <xliff:g id="ORGANIZATION">%1$s</xliff:g> నిర్వహణలో ఉంది. ఈమెయిళ్లు, యాప్‌లు మరియు వెబ్‌సైట్‌లతో సహా మీ కార్యాలయ నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_WORK">%2$s</xliff:g>కి ప్రొఫైల్ కనెక్ట్ చేయబడింది.\n\nమీ వ్యక్తిగత నెట్‌వర్క్ కార్యాచరణను పర్యవేక్షించగల <xliff:g id="APPLICATION_PERSONAL">%3$s</xliff:g>కి కూడా మీరు కనెక్ట్ చేయబడ్డారు."</string>
     <string name="keyguard_indication_trust_unlocked" msgid="7395154975733744547">"TrustAgent ద్వారా అన్‌లాక్ చేయబడింది"</string>
     <string name="keyguard_indication_trust_disabled" msgid="6820793704816727918">"మీరు మాన్యువల్‌గా అన్‌లాక్ చేస్తే మినహా పరికరం లాక్ చేయబడి ఉంటుంది"</string>
     <string name="keyguard_indication_trust_unlocked_plugged_in" msgid="2323452175329362855">"<xliff:g id="KEYGUARD_INDICATION">%1$s</xliff:g>\n<xliff:g id="POWER_INDICATION">%2$s</xliff:g>"</string>
@@ -611,7 +611,7 @@
     <string name="screen_pinning_description_gestural" msgid="7246323931831232068">"మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి, పైకి స్వైప్ చేసి &amp; పట్టుకోండి."</string>
     <string name="screen_pinning_description_accessible" msgid="7386449191953535332">"దీని వలన మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి స్థూలదృష్టిని తాకి &amp; అలాగే పట్టుకోండి."</string>
     <string name="screen_pinning_description_recents_invisible_accessible" msgid="2857071808674481986">"దీని వలన మీరు అన్‌పిన్ చేసే వరకు ఇది వీక్షణలో ఉంచబడుతుంది. అన్‌పిన్ చేయడానికి హోమ్‌ని తాకి &amp; అలాగే పట్టుకోండి."</string>
-    <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"వ్యక్తిగత డేటా (కాంటాక్ట్‌లు, ఇంకా ఇమెయిల్ కంటెంట్ లాంటివి) యాక్సెస్ చేయబడవచ్చు."</string>
+    <string name="screen_pinning_exposes_personal_data" msgid="8189852022981524789">"వ్యక్తిగత డేటా (కాంటాక్ట్‌లు, ఇంకా ఈమెయిల్‌ కంటెంట్ లాంటివి) యాక్సెస్ చేయబడవచ్చు."</string>
     <string name="screen_pinning_can_open_other_apps" msgid="7529756813231421455">"పిన్ చేయబడిన యాప్ ఇతర యాప్‌లను తెరవవచ్చు."</string>
     <string name="screen_pinning_toast" msgid="8177286912533744328">"ఈ యాప్‌ను అన్‌పిన్ చేయడానికి, \'వెనుకకు\', \'ఓవర్‌వ్యూ\' బటన్‌లను తాకి &amp; అలాగే పట్టుకోండి"</string>
     <string name="screen_pinning_toast_recents_invisible" msgid="6850978077443052594">"ఈ యాప్‌ను అన్‌పిన్ చేయడానికి, వెనుకకు, హోమ్ బటన్‌లను తాకి &amp; అలాగే పట్టుకోండి"</string>
@@ -844,7 +844,7 @@
     <string name="keyboard_shortcut_group_applications_assist" msgid="771606231466098742">"సహాయకం"</string>
     <string name="keyboard_shortcut_group_applications_browser" msgid="2776211137869809251">"బ్రౌజర్"</string>
     <string name="keyboard_shortcut_group_applications_contacts" msgid="2807268086386201060">"కాంటాక్ట్‌లు"</string>
-    <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ఇమెయిల్"</string>
+    <string name="keyboard_shortcut_group_applications_email" msgid="7852376788894975192">"ఈమెయిల్‌"</string>
     <string name="keyboard_shortcut_group_applications_sms" msgid="6912633831752843566">"SMS"</string>
     <string name="keyboard_shortcut_group_applications_music" msgid="9032078456666204025">"మ్యూజిక్"</string>
     <string name="keyboard_shortcut_group_applications_youtube" msgid="5078136084632450333">"YouTube"</string>
@@ -1090,8 +1090,7 @@
     <string name="controls_media_resume" msgid="1933520684481586053">"కొనసాగించండి"</string>
     <string name="controls_media_settings_button" msgid="5815790345117172504">"సెట్టింగ్‌లు"</string>
     <string name="controls_media_playing_item_description" msgid="4531853311504359098">"<xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g> <xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి ప్లే అవుతోంది"</string>
-    <!-- no translation found for controls_media_seekbar_description (4389621713616214611) -->
-    <skip />
+    <string name="controls_media_seekbar_description" msgid="4389621713616214611">"<xliff:g id="TOTAL_TIME">%2$s</xliff:g>లో <xliff:g id="ELAPSED_TIME">%1$s</xliff:g>"</string>
     <string name="controls_media_smartspace_rec_title" msgid="1699818353932537407">"ప్లే చేయండి"</string>
     <string name="controls_media_smartspace_rec_description" msgid="4136242327044070732">"<xliff:g id="APP_LABEL">%1$s</xliff:g>ను తెరవండి"</string>
     <string name="controls_media_smartspace_rec_item_description" msgid="2189271793070870883">"<xliff:g id="APP_LABEL">%3$s</xliff:g> నుండి <xliff:g id="ARTIST_NAME">%2$s</xliff:g> పాడిన <xliff:g id="SONG_NAME">%1$s</xliff:g>‌ను ప్లే చేయండి"</string>
@@ -1180,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"ప్రస్తుతానికి Wi-Fi ఆటోమేటిక్‌గా కనెక్ట్ అవ్వదు"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"అన్నీ చూడండి"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"నెట్‌వర్క్‌లను మార్చడానికి, ఈథర్‌నెట్‌ను డిస్‌కనెక్ట్ చేయండి"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"పరికర అనుభవాన్ని మెరుగుపరచడానికి, Wi‑Fi ఆఫ్‌లో ఉన్నప్పుడు కూడా, ఏ సమయంలో అయినా ఇప్పటికీ Wi‑Fi నెట్‌వర్క్‌ల కోసం యాప్‌లు, సర్వీస్‌లు స్కాన్ చేయగలవు. మీరు దీనిని Wi‑Fi స్కానింగ్ సెట్టింగ్‌లలో మార్చవచ్చు. "<annotation id="link">"మార్చండి"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"యూజర్‌ను ఎంచుకోండి"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-th/strings.xml b/packages/SystemUI/res/values-th/strings.xml
index a551b19..75314ee 100644
--- a/packages/SystemUI/res/values-th/strings.xml
+++ b/packages/SystemUI/res/values-th/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi จะไม่เชื่อมต่ออัตโนมัติในตอนนี้"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"ดูทั้งหมด"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"ตัดการเชื่อมต่ออีเทอร์เน็ตเพื่อสลับเครือข่าย"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"เพื่อปรับปรุงประสบการณ์การใช้อุปกรณ์ แอปและบริการต่างๆ จะยังคงสแกนหาเครือข่าย Wi‑Fi ได้ทุกเมื่อแม้ว่า Wi‑Fi จะปิดอยู่ คุณเปลี่ยนตัวเลือกนี้ได้ในการตั้งค่าการสแกนหา Wi-Fi "<annotation id="link">"เปลี่ยน"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"เลือกผู้ใช้"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tl/strings.xml b/packages/SystemUI/res/values-tl/strings.xml
index b8604ab..baefb76 100644
--- a/packages/SystemUI/res/values-tl/strings.xml
+++ b/packages/SystemUI/res/values-tl/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Hindi awtomatikong kokonekta ang Wi-Fi sa ngayon"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Tingnan lahat"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Para lumipat ng network, idiskonekta ang ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Para pahusayin ang karanasan sa device, puwede pa ring mag-scan ng mga Wi-Fi network ang mga app at serbisyo anumang oras, kahit habang naka-off ang Wi‑Fi. Mababago mo ito sa mga setting ng pag-scan ng Wi-Fi. "<annotation id="link">"Baguhin"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Pumili ng user"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-tr/strings.xml b/packages/SystemUI/res/values-tr/strings.xml
index 393cbee..905b34c 100644
--- a/packages/SystemUI/res/values-tr/strings.xml
+++ b/packages/SystemUI/res/values-tr/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Şu anda kablosuz ağa otomatik olarak bağlanılamıyor"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Tümünü göster"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ağ değiştirmek için ethernet bağlantısını kesin"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Uygulamalar ve hizmetler, cihaz deneyimini iyileştirmek için Kablosuz özelliği kapalı bile olsa kablosuz ağlar herhangi bir zamanda tarayabilir. Bunu kablosuz ağ taraması ayarlarından değiştirebilirsiniz. "<annotation id="link">"Değiştir"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Kullanıcı seçin"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uk/strings.xml b/packages/SystemUI/res/values-uk/strings.xml
index 0dd178a..7f6f910 100644
--- a/packages/SystemUI/res/values-uk/strings.xml
+++ b/packages/SystemUI/res/values-uk/strings.xml
@@ -1191,5 +1191,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Пристрій не підключатиметься до Wi-Fi автоматично"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Показати все"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Щоб вибрати іншу мережу, від’єднайте кабель Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Щоб користуватися пристроєм було зручніше, додатки й сервіси можуть шукати бездротові мережі, навіть якщо Wi-Fi вимкнено. Це налаштування можна змінити в параметрах пошуку мереж Wi-Fi. "<annotation id="link">"Змінити"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Виберіть користувача"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-ur/strings.xml b/packages/SystemUI/res/values-ur/strings.xml
index bb2409d..4dcfc09 100644
--- a/packages/SystemUI/res/values-ur/strings.xml
+++ b/packages/SystemUI/res/values-ur/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"‏ابھی Wi-Fi خود کار طور پر منسلک نہیں ہوگا"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"سبھی دیکھیں"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"نیٹ ورکس پر سوئچ کرنے کیلئے، ایتھرنیٹ غیر منسلک کریں"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"‏آلے کے تجربے کو بہتر بنانے کے لیے، Wi‑Fi کے آف ہونے پر بھی ایپس اور سروسز کسی بھی وقت Wi‑Fi نیٹ ورکس اسکین کر سکتی ہیں۔ آپ اسے Wi‑Fi اسکیننگ کی ترتیبات میں تبدیل کر سکتے ہیں۔ "<annotation id="link">"تبدیل کریں"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"صارف منتخب کریں"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-uz/strings.xml b/packages/SystemUI/res/values-uz/strings.xml
index afea9f4..5d13542 100644
--- a/packages/SystemUI/res/values-uz/strings.xml
+++ b/packages/SystemUI/res/values-uz/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Wi-Fi hozir avtomatik ulanmaydi"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Hammasi"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Boshqa tarmoqqa almashish uchun Ethernet tarmogʻini uzing"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Qurilma ishlashini yaxshilash uchun ilova va xizmatlar hatto Wi-Fi yoqilmaganda ham istalgan vaqt Wi-Fi tarmoqlarni qidirishi mumkin. Buni taqiqlash uchun Wi-Fi tarmoqlarni qidirish funksiyasini faolsizlantiring. "<annotation id="link">"Sozlamalarni ochish"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Foydalanuvchini tanlang"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-vi/strings.xml b/packages/SystemUI/res/values-vi/strings.xml
index 15abead..810f31d 100644
--- a/packages/SystemUI/res/values-vi/strings.xml
+++ b/packages/SystemUI/res/values-vi/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"Tạm thời, Wi-Fi sẽ không tự động kết nối"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Xem tất cả"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Để chuyển mạng, hãy rút cáp Ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Để cải thiện trải nghiệm khi dùng thiết bị, các ứng dụng và dịch vụ vẫn có thể quét tìm mạng Wi‑Fi bất cứ lúc nào, ngay cả khi Wi‑Fi tắt. Bạn có thể thay đổi chế độ này trong phần cài đặt tính năng Quét tìm Wi‑Fi. "<annotation id="link">"Thay đổi"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Chọn người dùng"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rCN/strings.xml b/packages/SystemUI/res/values-zh-rCN/strings.xml
index 74b1a39..b7a475d 100644
--- a/packages/SystemUI/res/values-zh-rCN/strings.xml
+++ b/packages/SystemUI/res/values-zh-rCN/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"WLAN 暂时无法自动连接"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"查看全部"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"如要切换网络,请断开以太网连接"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"为了提升设备的使用体验,即使 WLAN 已关闭,应用和服务仍可以随时扫描 WLAN 网络。您可以在 WLAN 扫描设置中更改此设置。"<annotation id="link">"更改"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"选择用户"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rHK/strings.xml b/packages/SystemUI/res/values-zh-rHK/strings.xml
index 28e0ae9..df207ad 100644
--- a/packages/SystemUI/res/values-zh-rHK/strings.xml
+++ b/packages/SystemUI/res/values-zh-rHK/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"目前系統不會自動連線至 Wi-Fi"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"顯示全部"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"如要切換網絡,請中斷以太網連線"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"為改善裝置的使用體驗,應用程式和服務仍可隨時掃瞄 Wi-Fi 網絡 (即使 Wi-Fi 已關閉)。您可在 Wi-Fi 掃瞄設定中變更此設定。"<annotation id="link">"變更"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"選取使用者"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zh-rTW/strings.xml b/packages/SystemUI/res/values-zh-rTW/strings.xml
index 1b07cfd..2fb3120 100644
--- a/packages/SystemUI/res/values-zh-rTW/strings.xml
+++ b/packages/SystemUI/res/values-zh-rTW/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"目前不會自動連上 Wi-Fi"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"查看全部"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"如要切換網路,請中斷乙太網路連線"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"為提升裝置的使用體驗,應用程式和服務仍可隨時掃描 Wi‑Fi 網路,即使 Wi-Fi 連線功能處於關閉狀態時亦然。你可以前往「掃描 Wi-Fi」設定進行變更。"<annotation id="link">"變更"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"選取使用者"</string>
 </resources>
diff --git a/packages/SystemUI/res/values-zu/strings.xml b/packages/SystemUI/res/values-zu/strings.xml
index 19e35ef..96dd7ed 100644
--- a/packages/SystemUI/res/values-zu/strings.xml
+++ b/packages/SystemUI/res/values-zu/strings.xml
@@ -1179,5 +1179,6 @@
     <string name="wifi_wont_autoconnect_for_now" msgid="5782282612749867762">"I-Wi-Fi ngeke ixhume ngokuzenzakalelayo okwamanje"</string>
     <string name="see_all_networks" msgid="3773666844913168122">"Bona konke"</string>
     <string name="to_switch_networks_disconnect_ethernet" msgid="6698111101156951955">"Ukuze ushintshe amanethiwekhi, nqamula i-ethernet"</string>
+    <string name="wifi_scan_notify_message" msgid="3753839537448621794">"Ukuze kuthuthukiswe ukuzizwela kwedivayisi, ama-app namasevisi kusengakwazi ukuskena amanethiwekhi we-Wi-Fi noma kunini, ngisho noma i-Wi-Fi ivaliwe, Ungashintsha lokhu kumasethingi Wokuskena i-Wi-Fi. "<annotation id="link">"Shintsha"</annotation></string>
     <string name="qs_user_switch_dialog_title" msgid="3045189293587781366">"Khetha umsebenzisi"</string>
 </resources>
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index 7293f31..db6985d 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -1602,7 +1602,6 @@
 
     <!-- Internet panel related dimensions -->
     <dimen name="internet_dialog_list_margin">12dp</dimen>
-    <dimen name="internet_dialog_list_max_height">662dp</dimen>
 
     <!-- The width of large/content heavy dialogs (e.g. Internet, Media output, etc) -->
     <dimen name="large_dialog_width">@dimen/match_parent</dimen>
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 523b9c8..986f82f 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2878,7 +2878,7 @@
     <!-- Summary for media output group with the active device count [CHAR LIMIT=NONE] -->
     <string name="media_output_dialog_multiple_devices"><xliff:g id="count" example="2">%1$d</xliff:g> devices selected</string>
     <!-- Summary for disconnected status [CHAR LIMIT=50] -->
-    <string name="media_output_dialog_disconnected"><xliff:g id="device_name" example="My device">%1$s</xliff:g> (disconnected)</string>
+    <string name="media_output_dialog_disconnected">(disconnected)</string>
     <!-- Summary for connecting error message [CHAR LIMIT=NONE] -->
     <string name="media_output_dialog_connect_failed">Couldn\'t connect. Try again.</string>
     <!-- Title for pairing item [CHAR LIMIT=60] -->
@@ -3028,6 +3028,8 @@
     <string name="see_all_networks">See all</string>
     <!-- Summary for warning to disconnect ethernet first then switch to other networks. [CHAR LIMIT=60] -->
     <string name="to_switch_networks_disconnect_ethernet">To switch networks, disconnect ethernet</string>
+    <!-- Message to describe "Wi-Fi scan always available feature" when Wi-Fi is off and Wi-Fi scanning is on. [CHAR LIMIT=NONE] -->
+    <string name="wifi_scan_notify_message">To improve device experience, apps and services can still scan for Wi\u2011Fi networks at any time, even when Wi\u2011Fi is off. You can change this in Wi\u2011Fi scanning settings. <annotation id="link">Change</annotation></string>
 
     <!-- Title for User Switch dialog. [CHAR LIMIT=20] -->
     <string name="qs_user_switch_dialog_title">Select user</string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index ff299ea..9bdd572 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -956,10 +956,6 @@
         <item name="android:textColor">?android:attr/textColorPrimary</item>
     </style>
 
-    <style name="Theme.SystemUI.Dialog.Internet">
-        <item name="android:windowBackground">@drawable/internet_dialog_background</item>
-    </style>
-
     <style name="MainSwitch.Settingslib" parent="@android:style/Theme.DeviceDefault">
         <item name="android:switchMinWidth">@dimen/settingslib_min_switch_width</item>
     </style>
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt
new file mode 100644
index 0000000..e072d41
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProvider.kt
@@ -0,0 +1,73 @@
+package com.android.systemui.unfold.util
+
+import android.content.Context
+import android.os.RemoteException
+import android.util.Log
+import android.view.IRotationWatcher
+import android.view.IWindowManager
+import android.view.Surface
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+
+/**
+ * [UnfoldTransitionProgressProvider] that emits transition progress only when the display has
+ * default rotation or 180 degrees opposite rotation (ROTATION_0 or ROTATION_180).
+ * It could be helpful to run the animation only when the display's rotation is perpendicular
+ * to the fold.
+ */
+class NaturalRotationUnfoldProgressProvider(
+    private val context: Context,
+    private val windowManagerInterface: IWindowManager,
+    unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider
+) : UnfoldTransitionProgressProvider {
+
+    private val scopedUnfoldTransitionProgressProvider =
+            ScopedUnfoldTransitionProgressProvider(unfoldTransitionProgressProvider)
+    private val rotationWatcher = RotationWatcher()
+
+    private var isNaturalRotation: Boolean = false
+
+    fun init() {
+        try {
+            windowManagerInterface.watchRotation(rotationWatcher, context.display.displayId)
+        } catch (e: RemoteException) {
+            throw e.rethrowFromSystemServer()
+        }
+
+        onRotationChanged(context.display.rotation)
+    }
+
+    private fun onRotationChanged(rotation: Int) {
+        val isNewRotationNatural = rotation == Surface.ROTATION_0 ||
+                rotation == Surface.ROTATION_180
+
+        if (isNaturalRotation != isNewRotationNatural) {
+            isNaturalRotation = isNewRotationNatural
+            scopedUnfoldTransitionProgressProvider.setReadyToHandleTransition(isNewRotationNatural)
+        }
+    }
+
+    override fun destroy() {
+        try {
+            windowManagerInterface.removeRotationWatcher(rotationWatcher)
+        } catch (e: RemoteException) {
+            e.rethrowFromSystemServer()
+        }
+
+        scopedUnfoldTransitionProgressProvider.destroy()
+    }
+
+    override fun addCallback(listener: TransitionProgressListener) {
+        scopedUnfoldTransitionProgressProvider.addCallback(listener)
+    }
+
+    override fun removeCallback(listener: TransitionProgressListener) {
+        scopedUnfoldTransitionProgressProvider.removeCallback(listener)
+    }
+
+    private inner class RotationWatcher : IRotationWatcher.Stub() {
+        override fun onRotationChanged(rotation: Int) {
+            this@NaturalRotationUnfoldProgressProvider.onRotationChanged(rotation)
+        }
+    }
+}
diff --git a/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java
new file mode 100644
index 0000000..543232d
--- /dev/null
+++ b/packages/SystemUI/shared/src/com/android/systemui/unfold/util/ScopedUnfoldTransitionProgressProvider.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2021 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.unfold.util;
+
+import android.annotation.NonNull;
+import android.annotation.Nullable;
+
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Manages progress listeners that can have smaller lifespan than the unfold animation.
+ * Allows to limit getting transition updates to only when
+ * {@link ScopedUnfoldTransitionProgressProvider#setReadyToHandleTransition} is called
+ * with readyToHandleTransition = true
+ *
+ * If the transition has already started by the moment when the clients are ready to play
+ * the transition then it will report transition started callback and current animation progress.
+ */
+public final class ScopedUnfoldTransitionProgressProvider implements
+        UnfoldTransitionProgressProvider, TransitionProgressListener {
+
+    private static final float PROGRESS_UNSET = -1f;
+
+    @Nullable
+    private UnfoldTransitionProgressProvider mSource;
+
+    private final List<TransitionProgressListener> mListeners = new ArrayList<>();
+
+    private boolean mIsReadyToHandleTransition;
+    private boolean mIsTransitionRunning;
+    private float mLastTransitionProgress = PROGRESS_UNSET;
+
+    public ScopedUnfoldTransitionProgressProvider() {
+        this(null);
+    }
+
+    public ScopedUnfoldTransitionProgressProvider(
+            @Nullable UnfoldTransitionProgressProvider source) {
+        setSourceProvider(source);
+    }
+
+    /**
+     * Sets the source for the unfold transition progress updates,
+     * it replaces current provider if it is already set
+     * @param provider transition provider that emits transition progress updates
+     */
+    public void setSourceProvider(@Nullable UnfoldTransitionProgressProvider provider) {
+        if (mSource != null) {
+            mSource.removeCallback(this);
+        }
+
+        if (provider != null) {
+            mSource = provider;
+            mSource.addCallback(this);
+        } else {
+            mSource = null;
+        }
+    }
+
+    /**
+     * Allows to notify this provide whether the listeners can play the transition or not.
+     * Call this method with readyToHandleTransition = true when all listeners
+     * are ready to consume the transition progress events.
+     * Call it with readyToHandleTransition = false when listeners can't process the events.
+     */
+    public void setReadyToHandleTransition(boolean isReadyToHandleTransition) {
+        if (mIsTransitionRunning) {
+            if (isReadyToHandleTransition) {
+                mListeners.forEach(TransitionProgressListener::onTransitionStarted);
+
+                if (mLastTransitionProgress != PROGRESS_UNSET) {
+                    mListeners.forEach(listener ->
+                            listener.onTransitionProgress(mLastTransitionProgress));
+                }
+            } else {
+                mIsTransitionRunning = false;
+                mListeners.forEach(TransitionProgressListener::onTransitionFinished);
+            }
+        }
+
+        mIsReadyToHandleTransition = isReadyToHandleTransition;
+    }
+
+    @Override
+    public void addCallback(@NonNull TransitionProgressListener listener) {
+        mListeners.add(listener);
+    }
+
+    @Override
+    public void removeCallback(@NonNull TransitionProgressListener listener) {
+        mListeners.remove(listener);
+    }
+
+    @Override
+    public void destroy() {
+        mSource.removeCallback(this);
+    }
+
+    @Override
+    public void onTransitionStarted() {
+        this.mIsTransitionRunning = true;
+        if (mIsReadyToHandleTransition) {
+            mListeners.forEach(TransitionProgressListener::onTransitionStarted);
+        }
+    }
+
+    @Override
+    public void onTransitionProgress(float progress) {
+        if (mIsReadyToHandleTransition) {
+            mListeners.forEach(listener -> listener.onTransitionProgress(progress));
+        }
+
+        mLastTransitionProgress = progress;
+    }
+
+    @Override
+    public void onTransitionFinished() {
+        if (mIsReadyToHandleTransition) {
+            mListeners.forEach(TransitionProgressListener::onTransitionFinished);
+        }
+
+        mIsTransitionRunning = false;
+        mLastTransitionProgress = PROGRESS_UNSET;
+    }
+}
diff --git a/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
index 5b6845f..3a8ee29 100644
--- a/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
+++ b/packages/SystemUI/src-debug/com/android/systemui/flags/FeatureFlagManager.java
@@ -23,11 +23,18 @@
 import android.os.Bundle;
 import android.util.Log;
 
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
 
 import org.json.JSONException;
 import org.json.JSONObject;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Map;
 
@@ -43,7 +50,7 @@
  * To restore a flag back to its default, leave the `--ez value <0|1>` off of the command.
  */
 @SysUISingleton
-public class FeatureFlagManager implements FlagReader, FlagWriter {
+public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
     private static final String TAG = "SysUIFlags";
 
     private static final String SYSPROP_PREFIX = "persist.systemui.flag_";
@@ -58,11 +65,13 @@
     private final Map<Integer, Boolean> mBooleanFlagCache = new HashMap<>();
 
     @Inject
-    public FeatureFlagManager(SystemPropertiesHelper systemPropertiesHelper, Context context) {
+    public FeatureFlagManager(SystemPropertiesHelper systemPropertiesHelper, Context context,
+            DumpManager dumpManager) {
         mSystemPropertiesHelper = systemPropertiesHelper;
 
         IntentFilter filter = new IntentFilter(ACTION_SET_FLAG);
         context.registerReceiver(mReceiver, filter, FLAGS_PERMISSION, null);
+        dumpManager.registerDumpable(TAG, this);
     }
 
     /** Return a {@link BooleanFlag}'s value. */
@@ -186,4 +195,16 @@
             }
         }
     };
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        ArrayList<String> flagStrings = new ArrayList<>(mBooleanFlagCache.size());
+        for (Map.Entry<Integer, Boolean> entry : mBooleanFlagCache.entrySet()) {
+            flagStrings.add("  sysui_flag_" + entry.getKey() + ": " + entry.getValue());
+        }
+        flagStrings.sort(String.CASE_INSENSITIVE_ORDER);
+        for (String flagString : flagStrings) {
+            pw.println(flagString);
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
index 6fd0c82..3d4e896 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitch.java
@@ -89,6 +89,7 @@
 
     private int mClockSwitchYAmount;
     @VisibleForTesting boolean mChildrenAreLaidOut = false;
+    private OnPreDrawListener mPreDrawListener;
 
     public KeyguardClockSwitch(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -284,15 +285,14 @@
         if (mChildrenAreLaidOut) {
             animateClockChange(clockSize == LARGE);
             mDisplayedClockSize = clockSize;
-        } else {
-            getViewTreeObserver().addOnPreDrawListener(new OnPreDrawListener() {
-                @Override
-                public boolean onPreDraw() {
-                    switchToClock(clockSize);
-                    getViewTreeObserver().removeOnPreDrawListener(this);
-                    return true;
-                }
-            });
+        } else if (mPreDrawListener == null) {
+            mPreDrawListener = () -> {
+                switchToClock(clockSize);
+                getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener);
+                mPreDrawListener = null;
+                return true;
+            };
+            getViewTreeObserver().addOnPreDrawListener(mPreDrawListener);
         }
         return true;
     }
@@ -303,6 +303,13 @@
         mChildrenAreLaidOut = true;
     }
 
+    void onViewDetached() {
+        if (mPreDrawListener != null) {
+            getViewTreeObserver().removeOnPreDrawListener(mPreDrawListener);
+            mPreDrawListener = null;
+        }
+    }
+
     public Paint getPaint() {
         return mClockView.getPaint();
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 01976b4..1931c0a 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -238,6 +238,7 @@
         }
         mColorExtractor.removeOnColorsChangedListener(mColorsListener);
         mView.setClockPlugin(null, mStatusBarStateController.getState());
+        mView.onViewDetached();
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
index 11eeac2..099dd5d 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageArea.java
@@ -27,8 +27,10 @@
 import android.util.AttributeSet;
 import android.util.TypedValue;
 import android.view.View;
+import android.view.ViewGroup;
 import android.widget.TextView;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 
@@ -55,6 +57,8 @@
     private ColorStateList mNextMessageColorState = ColorStateList.valueOf(DEFAULT_COLOR);
     private boolean mBouncerVisible;
     private boolean mAltBouncerShowing;
+    private ViewGroup mContainer;
+    private int mTopMargin;
 
     public KeyguardMessageArea(Context context, AttributeSet attrs) {
         super(context, attrs);
@@ -65,6 +69,24 @@
     }
 
     @Override
+    protected void onAttachedToWindow() {
+        super.onAttachedToWindow();
+        mContainer = getRootView().findViewById(R.id.keyguard_message_area_container);
+    }
+
+    void onConfigChanged() {
+        final int newTopMargin = SystemBarUtils.getStatusBarHeight(getContext());
+        if (mTopMargin == newTopMargin) {
+            return;
+        }
+        mTopMargin = newTopMargin;
+        ViewGroup.MarginLayoutParams lp =
+                (ViewGroup.MarginLayoutParams) mContainer.getLayoutParams();
+        lp.topMargin = mTopMargin;
+        mContainer.setLayoutParams(lp);
+    }
+
+    @Override
     public void setNextMessageColor(ColorStateList colorState) {
         mNextMessageColorState = colorState;
     }
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
index 51ded3f..05318bb 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardMessageAreaController.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import android.content.res.ColorStateList;
+import android.content.res.Configuration;
 
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.ConfigurationController.ConfigurationListener;
@@ -48,6 +49,11 @@
 
     private ConfigurationListener mConfigurationListener = new ConfigurationListener() {
         @Override
+        public void onConfigChanged(Configuration newConfig) {
+            mView.onConfigChanged();
+        }
+
+        @Override
         public void onThemeChanged() {
             mView.onThemeChanged();
         }
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index 94b1728..3c80a18 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -695,8 +695,11 @@
     private final AuthController.Callback mAuthControllerCallback = new AuthController.Callback() {
         @Override
         public void onAllAuthenticatorsRegistered() {
-            updateIsUdfpsEnrolled();
-            updateConfiguration();
+            // must be called from the main thread since it may update the views
+            mExecutor.execute(() -> {
+                updateIsUdfpsEnrolled();
+                updateConfiguration();
+            });
         }
     };
 }
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
index 99e122e..7517dee 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/AnalogClockController.java
@@ -91,7 +91,7 @@
         mResources = res;
         mLayoutInflater = inflater;
         mColorExtractor = colorExtractor;
-        mClockPosition = new SmallClockPosition(res);
+        mClockPosition = new SmallClockPosition(inflater.getContext());
     }
 
     private void createViews() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
index fac923c01..1add1a3 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/BubbleClockController.java
@@ -91,7 +91,7 @@
         mResources = res;
         mLayoutInflater = inflater;
         mColorExtractor = colorExtractor;
-        mClockPosition = new SmallClockPosition(res);
+        mClockPosition = new SmallClockPosition(inflater.getContext());
     }
 
     private void createViews() {
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
index 3775628..013cdac 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/ClockManager.java
@@ -41,7 +41,6 @@
 import com.android.systemui.plugins.PluginListener;
 import com.android.systemui.settings.CurrentUserObservable;
 import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.util.InjectionInflationController;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -125,16 +124,16 @@
     private final int mHeight;
 
     @Inject
-    public ClockManager(Context context, InjectionInflationController injectionInflater,
+    public ClockManager(Context context, LayoutInflater layoutInflater,
             PluginManager pluginManager, SysuiColorExtractor colorExtractor,
             @Nullable DockManager dockManager, BroadcastDispatcher broadcastDispatcher) {
-        this(context, injectionInflater, pluginManager, colorExtractor,
+        this(context, layoutInflater, pluginManager, colorExtractor,
                 context.getContentResolver(), new CurrentUserObservable(broadcastDispatcher),
                 new SettingsWrapper(context.getContentResolver()), dockManager);
     }
 
     @VisibleForTesting
-    ClockManager(Context context, InjectionInflationController injectionInflater,
+    ClockManager(Context context, LayoutInflater layoutInflater,
             PluginManager pluginManager, SysuiColorExtractor colorExtractor,
             ContentResolver contentResolver, CurrentUserObservable currentUserObservable,
             SettingsWrapper settingsWrapper, DockManager dockManager) {
@@ -147,7 +146,6 @@
         mPreviewClocks = new AvailableClocks();
 
         Resources res = context.getResources();
-        LayoutInflater layoutInflater = injectionInflater.injectable(LayoutInflater.from(context));
 
         addBuiltinClock(() -> new DefaultClockController(res, layoutInflater, colorExtractor));
 
diff --git a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
index b304074..4e51b98 100644
--- a/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
+++ b/packages/SystemUI/src/com/android/keyguard/clock/SmallClockPosition.java
@@ -16,10 +16,11 @@
 
 package com.android.keyguard.clock;
 
-import android.content.res.Resources;
+import android.content.Context;
 import android.util.MathUtils;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
 
 /**
@@ -40,11 +41,11 @@
      */
     private float mDarkAmount;
 
-    SmallClockPosition(Resources res) {
-        this(res.getDimensionPixelSize(R.dimen.status_bar_height),
-                res.getDimensionPixelSize(R.dimen.keyguard_lock_padding),
-                res.getDimensionPixelSize(R.dimen.keyguard_lock_height),
-                res.getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y)
+    SmallClockPosition(Context context) {
+        this(SystemBarUtils.getStatusBarHeight(context),
+                context.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_padding),
+                context.getResources().getDimensionPixelSize(R.dimen.keyguard_lock_height),
+                context.getResources().getDimensionPixelSize(R.dimen.burn_in_prevention_offset_y)
         );
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/Dependency.java b/packages/SystemUI/src/com/android/systemui/Dependency.java
index c73d19b..4e4034a 100644
--- a/packages/SystemUI/src/com/android/systemui/Dependency.java
+++ b/packages/SystemUI/src/com/android/systemui/Dependency.java
@@ -89,8 +89,12 @@
 import com.android.systemui.statusbar.notification.NotificationFilter;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
 import com.android.systemui.statusbar.notification.logging.NotificationLogger;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
+import com.android.systemui.statusbar.notification.stack.AmbientState;
+import com.android.systemui.statusbar.notification.stack.NotificationSectionsManager;
 import com.android.systemui.statusbar.phone.AutoHideController;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardDismissUtil;
@@ -102,6 +106,7 @@
 import com.android.systemui.statusbar.phone.StatusBarContentInsetsProvider;
 import com.android.systemui.statusbar.phone.StatusBarIconController;
 import com.android.systemui.statusbar.phone.StatusBarWindowController;
+import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.policy.AccessibilityController;
 import com.android.systemui.statusbar.policy.AccessibilityManagerWrapper;
 import com.android.systemui.statusbar.policy.BatteryController;
@@ -360,6 +365,11 @@
     @Inject Lazy<FeatureFlags> mFeatureFlagsLazy;
     @Inject Lazy<StatusBarContentInsetsProvider> mContentInsetsProviderLazy;
     @Inject Lazy<InternetDialogFactory> mInternetDialogFactory;
+    @Inject Lazy<NotificationSectionsManager> mNotificationSectionsManagerLazy;
+    @Inject Lazy<UnlockedScreenOffAnimationController> mUnlockedScreenOffAnimationControllerLazy;
+    @Inject Lazy<AmbientState> mAmbientStateLazy;
+    @Inject Lazy<GroupMembershipManager> mGroupMembershipManagerLazy;
+    @Inject Lazy<GroupExpansionManager> mGroupExpansionManagerLazy;
 
     @Inject
     public Dependency() {
@@ -574,6 +584,12 @@
         mProviders.put(UiEventLogger.class, mUiEventLogger::get);
         mProviders.put(FeatureFlags.class, mFeatureFlagsLazy::get);
         mProviders.put(StatusBarContentInsetsProvider.class, mContentInsetsProviderLazy::get);
+        mProviders.put(NotificationSectionsManager.class, mNotificationSectionsManagerLazy::get);
+        mProviders.put(UnlockedScreenOffAnimationController.class,
+                mUnlockedScreenOffAnimationControllerLazy::get);
+        mProviders.put(AmbientState.class, mAmbientStateLazy::get);
+        mProviders.put(GroupMembershipManager.class, mGroupMembershipManagerLazy::get);
+        mProviders.put(GroupExpansionManager.class, mGroupExpansionManagerLazy::get);
 
         Dependency.setInstance(this);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
index d2566b4..d1739aa 100644
--- a/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/ImageWallpaper.java
@@ -238,9 +238,7 @@
                 Bitmap bitmap = mMiniBitmap;
                 if (bitmap == null) {
                     mLocalColorsToAdd.addAll(regions);
-                    mRenderer.use(b -> {
-                        updateMiniBitmapAndNotify(b);
-                    });
+                    if (mRenderer != null) mRenderer.use(this::updateMiniBitmapAndNotify);
                 } else {
                     computeAndNotifyLocalColors(regions, bitmap);
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
index d8e80fe..0d7551f 100644
--- a/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
+++ b/packages/SystemUI/src/com/android/systemui/accessibility/floatingmenu/AnnotationLinkSpan.java
@@ -30,7 +30,7 @@
 /**
  * A span that turns the text wrapped by annotation tag into the clickable link text.
  */
-class AnnotationLinkSpan extends ClickableSpan {
+public class AnnotationLinkSpan extends ClickableSpan {
     private final Optional<View.OnClickListener> mClickListener;
 
     private AnnotationLinkSpan(View.OnClickListener listener) {
@@ -50,7 +50,7 @@
      * @param linkInfos used to attach the click action into the corresponding span
      * @return the text attached with the span
      */
-    static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) {
+    public static CharSequence linkify(CharSequence text, LinkInfo... linkInfos) {
         final SpannableString msg = new SpannableString(text);
         final Annotation[] spans =
                 msg.getSpans(/* queryStart= */ 0, msg.length(), Annotation.class);
@@ -78,12 +78,12 @@
     /**
      * Data class to store the annotation and the click action.
      */
-    static class LinkInfo {
-        static final String DEFAULT_ANNOTATION = "link";
+    public static class LinkInfo {
+        public static final String DEFAULT_ANNOTATION = "link";
         private final Optional<String> mAnnotation;
         private final Optional<View.OnClickListener> mListener;
 
-        LinkInfo(@NonNull String annotation, View.OnClickListener listener) {
+        public LinkInfo(@NonNull String annotation, View.OnClickListener listener) {
             mAnnotation = Optional.of(annotation);
             mListener = Optional.ofNullable(listener);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index b2eaa2b..3a3f22a 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -889,6 +889,7 @@
         }
 
         if (!mKeyguardUpdateMonitor.isFingerprintDetectionRunning()) {
+            mKeyguardViewManager.showBouncer(true);
             return;
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
index b2a5409..11addf0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollProgressBarDrawable.java
@@ -40,7 +40,7 @@
 
     @Nullable private UdfpsEnrollHelper mEnrollHelper;
     @NonNull private List<UdfpsEnrollProgressBarSegment> mSegments = new ArrayList<>();
-    private int mTotalSteps = 1;
+    private int mTotalSteps = 0;
     private int mProgressSteps = 0;
     private boolean mIsShowingHelp = false;
 
@@ -67,22 +67,19 @@
 
     void onEnrollmentProgress(int remaining, int totalSteps) {
         mTotalSteps = totalSteps;
-        updateState(getProgressSteps(remaining, totalSteps), false /* isShowingHelp */);
+
+        // Show some progress for the initial touch.
+        updateState(Math.max(1, totalSteps - remaining), false /* isShowingHelp */);
     }
 
     void onEnrollmentHelp(int remaining, int totalSteps) {
-        updateState(getProgressSteps(remaining, totalSteps), true /* isShowingHelp */);
+        updateState(Math.max(0, totalSteps - remaining), true /* isShowingHelp */);
     }
 
     void onLastStepAcquired() {
         updateState(mTotalSteps, false /* isShowingHelp */);
     }
 
-    private static int getProgressSteps(int remaining, int totalSteps) {
-        // Show some progress for the initial touch.
-        return Math.max(1, totalSteps - remaining);
-    }
-
     private void updateState(int progressSteps, boolean isShowingHelp) {
         updateProgress(progressSteps);
         updateFillColor(isShowingHelp);
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
index 72da7f4..5a52fd0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlsUiControllerImpl.kt
@@ -120,7 +120,7 @@
     private val onSeedingComplete = Consumer<Boolean> {
         accepted ->
             if (accepted) {
-                selectedStructure = controlsController.get().getFavorites().maxBy {
+                selectedStructure = controlsController.get().getFavorites().maxByOrNull {
                     it.controls.size
                 } ?: EMPTY_STRUCTURE
                 updatePreferences(selectedStructure)
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
index aac03f8..a9a4da8 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SysUIComponent.java
@@ -25,7 +25,6 @@
 import com.android.systemui.keyguard.KeyguardSliceProvider;
 import com.android.systemui.people.PeopleProvider;
 import com.android.systemui.statusbar.policy.ConfigurationController;
-import com.android.systemui.util.InjectionInflationController;
 import com.android.wm.shell.ShellCommandHandler;
 import com.android.wm.shell.TaskViewFactory;
 import com.android.wm.shell.apppairs.AppPairs;
@@ -147,11 +146,6 @@
     InitController getInitController();
 
     /**
-     * ViewInstanceCreator generates all Views that need injection.
-     */
-    InjectionInflationController.ViewInstanceCreator.Factory createViewInstanceCreatorFactory();
-
-    /**
      * Member injection into the supplied argument.
      */
     void inject(SystemUIAppComponentFactory factory);
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
index 0923caaf..50d2dd1 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIDefaultModule.java
@@ -187,9 +187,13 @@
         return new Recents(context, recentsImplementation, commandQueue);
     }
 
-    @Binds
-    abstract DeviceProvisionedController bindDeviceProvisionedController(
-            DeviceProvisionedControllerImpl deviceProvisionedController);
+    @SysUISingleton
+    @Provides
+    static DeviceProvisionedController bindDeviceProvisionedController(
+            DeviceProvisionedControllerImpl deviceProvisionedController) {
+        deviceProvisionedController.init();
+        return deviceProvisionedController;
+    }
 
     @Binds
     abstract KeyguardViewController bindKeyguardViewController(
diff --git a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
index f933128..a4e2572 100644
--- a/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/dagger/SystemUIModule.java
@@ -75,7 +75,6 @@
 import com.android.systemui.statusbar.policy.dagger.StatusBarPolicyModule;
 import com.android.systemui.tuner.dagger.TunerModule;
 import com.android.systemui.user.UserModule;
-import com.android.systemui.util.InjectionInflationController;
 import com.android.systemui.util.concurrency.SysUIConcurrencyModule;
 import com.android.systemui.util.dagger.UtilModule;
 import com.android.systemui.util.sensors.SensorModule;
@@ -216,11 +215,9 @@
 
     @Provides
     @SysUISingleton
-    static StatusBarWindowView providesStatusBarWindowView(Context context,
-            InjectionInflationController injectionInflationController) {
+    static StatusBarWindowView providesStatusBarWindowView(LayoutInflater layoutInflater) {
         StatusBarWindowView view =
-                (StatusBarWindowView) injectionInflationController.injectable(
-                        LayoutInflater.from(context)).inflate(R.layout.super_status_bar,
+                (StatusBarWindowView) layoutInflater.inflate(R.layout.super_status_bar,
                         /* root= */ null);
         if (view == null) {
             throw new IllegalStateException(
diff --git a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
index 9d0591e..5c3e07f 100644
--- a/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
+++ b/packages/SystemUI/src/com/android/systemui/doze/DozeSensors.java
@@ -659,7 +659,7 @@
         @Override
         @AnyThread
         public void onTrigger(TriggerEvent event) {
-            final Sensor sensor = mSensors[mDevicePosture];
+            final Sensor sensor = mSensors[mPosture];
             mDozeLog.traceSensor(mPulseReason);
             mHandler.post(mWakeLock.wrap(() -> {
                 if (DEBUG) Log.d(TAG, "onTrigger: " + triggerEventToString(event));
diff --git a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java
index 85baed4..78f0b5f 100644
--- a/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java
+++ b/packages/SystemUI/src/com/android/systemui/flags/FeatureFlagManager.java
@@ -16,23 +16,48 @@
 
 package com.android.systemui.flags;
 
+import android.util.SparseBooleanArray;
+
+import androidx.annotation.NonNull;
+
+import com.android.systemui.Dumpable;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dump.DumpManager;
+
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
 
 import javax.inject.Inject;
 
 /**
  * Default implementation of the a Flag manager that returns default values for release builds
+ *
+ * There's a version of this file in src-debug which allows overriding, and has documentation about
+ * how to set flags.
  */
 @SysUISingleton
-public class FeatureFlagManager implements FlagReader, FlagWriter {
+public class FeatureFlagManager implements FlagReader, FlagWriter, Dumpable {
+    SparseBooleanArray mAccessedFlags = new SparseBooleanArray();
     @Inject
-    public FeatureFlagManager() {}
+    public FeatureFlagManager(DumpManager dumpManager) {
+        dumpManager.registerDumpable("SysUIFlags", this);
+    }
     public boolean isEnabled(String key, boolean defaultValue) {
         return defaultValue;
     }
     public boolean isEnabled(int key, boolean defaultValue) {
+        mAccessedFlags.append(key, defaultValue);
         return defaultValue;
     }
     public void setEnabled(String key, boolean value) {}
     public void setEnabled(int key, boolean value) {}
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        int size = mAccessedFlags.size();
+        for (int i = 0; i < size; i++) {
+            pw.println("  sysui_flag_" + mAccessedFlags.keyAt(i)
+                    + ": " + mAccessedFlags.valueAt(i));
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
deleted file mode 100644
index b4137fa..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessController.kt
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright (C) 2020 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.animation.Animator
-import android.animation.AnimatorListenerAdapter
-import android.animation.ValueAnimator
-import android.content.res.Resources
-import android.database.ContentObserver
-import android.graphics.Bitmap
-import android.graphics.BitmapFactory
-import android.graphics.Color
-import android.graphics.drawable.ColorDrawable
-import android.hardware.biometrics.BiometricSourceType
-import android.os.Handler
-import android.provider.Settings.System.SCREEN_BRIGHTNESS_FLOAT
-import android.util.MathUtils
-import android.view.View
-import android.view.WindowManager.LayoutParams.BRIGHTNESS_OVERRIDE_NONE
-import android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-import com.android.internal.annotations.VisibleForTesting
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.Dumpable
-import com.android.systemui.R
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.NotificationShadeWindowController
-import com.android.systemui.util.settings.GlobalSettings
-import com.android.systemui.util.settings.SystemSettings
-import java.io.FileDescriptor
-import java.io.PrintWriter
-import java.lang.Float.max
-import java.util.concurrent.TimeUnit
-
-val DEFAULT_ANIMATION_DURATION = TimeUnit.SECONDS.toMillis(4)
-val MAX_SCREEN_BRIGHTNESS = 100 // 0..100
-val MAX_SCRIM_OPACTY = 50 // 0..100
-val DEFAULT_USE_FACE_WALLPAPER = false
-
-/**
- * This class is responsible for ramping up the display brightness (and white overlay) in order
- * to mitigate low light conditions when running face auth without an IR camera.
- */
-@SysUISingleton
-open class FaceAuthScreenBrightnessController(
-    private val notificationShadeWindowController: NotificationShadeWindowController,
-    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
-    private val resources: Resources,
-    private val globalSettings: GlobalSettings,
-    private val systemSettings: SystemSettings,
-    private val mainHandler: Handler,
-    private val dumpManager: DumpManager,
-    private val enabled: Boolean
-) : Dumpable {
-
-    private var userDefinedBrightness: Float = 1f
-    @VisibleForTesting
-    var useFaceAuthWallpaper = globalSettings
-            .getInt("sysui.use_face_auth_wallpaper", if (DEFAULT_USE_FACE_WALLPAPER) 1 else 0) == 1
-    private val brightnessAnimationDuration = globalSettings
-            .getLong("sysui.face_brightness_anim_duration", DEFAULT_ANIMATION_DURATION)
-    private val maxScreenBrightness = globalSettings
-            .getInt("sysui.face_max_brightness", MAX_SCREEN_BRIGHTNESS) / 100f
-    private val maxScrimOpacity = globalSettings
-            .getInt("sysui.face_max_scrim_opacity", MAX_SCRIM_OPACTY) / 100f
-    private val keyguardUpdateCallback = object : KeyguardUpdateMonitorCallback() {
-        override fun onBiometricRunningStateChanged(
-            running: Boolean,
-            biometricSourceType: BiometricSourceType?
-        ) {
-            if (biometricSourceType != BiometricSourceType.FACE) {
-                return
-            }
-            // TODO enable only when receiving a low-light error
-            overridingBrightness = if (enabled) running else false
-        }
-    }
-    private lateinit var whiteOverlay: View
-    private var brightnessAnimator: ValueAnimator? = null
-    private var overridingBrightness = false
-    set(value) {
-        if (field == value) {
-            return
-        }
-        field = value
-        brightnessAnimator?.cancel()
-
-        if (!value) {
-            notificationShadeWindowController.setFaceAuthDisplayBrightness(BRIGHTNESS_OVERRIDE_NONE)
-            if (whiteOverlay.alpha > 0) {
-                brightnessAnimator = createAnimator(whiteOverlay.alpha, 0f).apply {
-                    duration = 200
-                    addUpdateListener {
-                        whiteOverlay.alpha = it.animatedValue as Float
-                    }
-                    addListener(object : AnimatorListenerAdapter() {
-                        override fun onAnimationEnd(animation: Animator?) {
-                            whiteOverlay.visibility = View.INVISIBLE
-                            brightnessAnimator = null
-                        }
-                    })
-                    start()
-                }
-            }
-            return
-        }
-
-        val targetBrightness = max(maxScreenBrightness, userDefinedBrightness)
-        whiteOverlay.visibility = View.VISIBLE
-        brightnessAnimator = createAnimator(0f, 1f).apply {
-            duration = brightnessAnimationDuration
-            addUpdateListener {
-                val progress = it.animatedValue as Float
-                val brightnessProgress = MathUtils.constrainedMap(
-                        userDefinedBrightness, targetBrightness, 0f, 0.5f, progress)
-                val scrimProgress = MathUtils.constrainedMap(
-                        0f, maxScrimOpacity, 0.5f, 1f, progress)
-                notificationShadeWindowController.setFaceAuthDisplayBrightness(brightnessProgress)
-                whiteOverlay.alpha = scrimProgress
-            }
-            addListener(object : AnimatorListenerAdapter() {
-                override fun onAnimationEnd(animation: Animator?) {
-                    brightnessAnimator = null
-                }
-            })
-            start()
-        }
-    }
-
-    @VisibleForTesting
-    open fun createAnimator(start: Float, end: Float) = ValueAnimator.ofFloat(start, end)
-
-    /**
-     * Returns a bitmap that should be used by the lock screen as a wallpaper, if face auth requires
-     * a secure wallpaper.
-     */
-    var faceAuthWallpaper: Bitmap? = null
-    get() {
-        val user = KeyguardUpdateMonitor.getCurrentUser()
-        if (useFaceAuthWallpaper && keyguardUpdateMonitor.isFaceAuthEnabledForUser(user)) {
-            val options = BitmapFactory.Options().apply {
-                inScaled = false
-            }
-            return BitmapFactory.decodeResource(resources, R.drawable.face_auth_wallpaper, options)
-        }
-        return null
-    }
-    private set
-
-    fun attach(overlayView: View) {
-        whiteOverlay = overlayView
-        whiteOverlay.focusable = FLAG_NOT_FOCUSABLE
-        whiteOverlay.background = ColorDrawable(Color.WHITE)
-        whiteOverlay.isEnabled = false
-        whiteOverlay.alpha = 0f
-        whiteOverlay.visibility = View.INVISIBLE
-
-        dumpManager.registerDumpable(this.javaClass.name, this)
-        keyguardUpdateMonitor.registerCallback(keyguardUpdateCallback)
-        systemSettings.registerContentObserver(SCREEN_BRIGHTNESS_FLOAT,
-            object : ContentObserver(mainHandler) {
-                override fun onChange(selfChange: Boolean) {
-                    userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT)
-                }
-            })
-        userDefinedBrightness = systemSettings.getFloat(SCREEN_BRIGHTNESS_FLOAT, 1f)
-    }
-
-    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
-        pw.apply {
-            println("overridingBrightness: $overridingBrightness")
-            println("useFaceAuthWallpaper: $useFaceAuthWallpaper")
-            println("brightnessAnimator: $brightnessAnimator")
-            println("brightnessAnimationDuration: $brightnessAnimationDuration")
-            println("maxScreenBrightness: $maxScreenBrightness")
-            println("userDefinedBrightness: $userDefinedBrightness")
-            println("enabled: $enabled")
-        }
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 3c58079..01a0f27 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -102,7 +102,7 @@
             "persist.wm.enable_remote_keyguard_animation";
 
     private static final int sEnableRemoteKeyguardAnimation =
-            SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 0);
+            SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
 
     /**
      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
index e51b602..2cc564b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardUnlockAnimationController.kt
@@ -62,7 +62,7 @@
  * The dismiss amount is the inverse of the notification panel expansion, which decreases as the
  * lock screen is swiped away.
  */
-const val DISMISS_AMOUNT_SHOW_SURFACE_THRESHOLD = 0.1f
+const val DISMISS_AMOUNT_SHOW_SURFACE_THRESHOLD = 0.25f
 
 /**
  * Dismiss amount at which to complete the keyguard exit animation and hide the keyguard.
@@ -70,7 +70,7 @@
  * The dismiss amount is the inverse of the notification panel expansion, which decreases as the
  * lock screen is swiped away.
  */
-const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.3f
+const val DISMISS_AMOUNT_EXIT_KEYGUARD_THRESHOLD = 0.4f
 
 /**
  * Initiates, controls, and ends the keyguard unlock animation.
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
index 11d4aac..9b0d69b 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/dagger/KeyguardModule.java
@@ -20,9 +20,6 @@
 import android.app.trust.TrustManager;
 import android.content.Context;
 import android.content.pm.PackageManager;
-import android.content.res.Resources;
-import android.hardware.face.FaceManager;
-import android.os.Handler;
 import android.os.PowerManager;
 
 import com.android.internal.widget.LockPatternUtils;
@@ -37,17 +34,14 @@
 import com.android.systemui.classifier.FalsingCollector;
 import com.android.systemui.classifier.FalsingModule;
 import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dagger.qualifiers.UiBackground;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
 import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
-import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.phone.DozeParameters;
 import com.android.systemui.statusbar.phone.KeyguardLiftController;
@@ -59,10 +53,7 @@
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
 import com.android.systemui.util.DeviceConfigProxy;
 import com.android.systemui.util.sensors.AsyncSensorManager;
-import com.android.systemui.util.settings.GlobalSettings;
-import com.android.systemui.util.settings.SystemSettings;
 
-import java.util.Optional;
 import java.util.concurrent.Executor;
 
 import dagger.Lazy;
@@ -150,35 +141,4 @@
         return new KeyguardLiftController(statusBarStateController, asyncSensorManager,
                 keyguardUpdateMonitor, dumpManager);
     }
-
-    @SysUISingleton
-    @Provides
-    static Optional<FaceAuthScreenBrightnessController> provideFaceAuthScreenBrightnessController(
-            Context context,
-            NotificationShadeWindowController notificationShadeWindowController,
-            @Main Resources resources,
-            Handler handler,
-            @Nullable FaceManager faceManager,
-            PackageManager packageManager,
-            KeyguardUpdateMonitor keyguardUpdateMonitor,
-            GlobalSettings globalSetting,
-            SystemSettings systemSettings,
-            DumpManager dumpManager) {
-        if (faceManager == null || !packageManager.hasSystemFeature(PackageManager.FEATURE_FACE)) {
-            return Optional.empty();
-        }
-
-        // Cameras that support "self illumination," via IR for example, don't need low light
-        // environment mitigation.
-        boolean needsLowLightMitigation = faceManager.getSensorPropertiesInternal().stream()
-                .anyMatch((properties) -> !properties.supportsSelfIllumination);
-        if (!needsLowLightMitigation) {
-            return Optional.empty();
-        }
-
-        // currently disabled (doesn't ramp up brightness or use scrim) see b/175918367
-        return Optional.of(new FaceAuthScreenBrightnessController(
-                notificationShadeWindowController, keyguardUpdateMonitor, resources,
-                globalSetting, systemSettings, handler, dumpManager, false));
-    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
index f32dad6..042a337 100644
--- a/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/PlayerViewHolder.kt
@@ -106,6 +106,7 @@
          */
         @JvmStatic fun create(inflater: LayoutInflater, parent: ViewGroup): PlayerViewHolder {
             val mediaView = inflater.inflate(R.layout.media_view, parent, false)
+            mediaView.setLayerType(View.LAYER_TYPE_HARDWARE, null)
             // Because this media view (a TransitionLayout) is used to measure and layout the views
             // in various states before being attached to its parent, we can't depend on the default
             // LAYOUT_DIRECTION_INHERIT to correctly resolve the ltr direction.
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 125b87b..113ba59 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -16,14 +16,10 @@
 
 package com.android.systemui.media.dialog;
 
-import static android.text.Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
-
 import android.graphics.PorterDuff;
 import android.graphics.PorterDuffColorFilter;
 import android.graphics.drawable.Drawable;
-import android.text.SpannableString;
 import android.text.TextUtils;
-import android.text.style.ForegroundColorSpan;
 import android.util.Log;
 import android.view.View;
 import android.view.ViewGroup;
@@ -99,23 +95,6 @@
         return mController.getMediaDevices().size();
     }
 
-    @Override
-    CharSequence getItemTitle(MediaDevice device) {
-        if (device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
-                && !device.isConnected()) {
-            final CharSequence deviceName = device.getName();
-            // Append status to title only for the disconnected Bluetooth device.
-            final SpannableString spannableTitle = new SpannableString(
-                    mContext.getString(R.string.media_output_dialog_disconnected, deviceName));
-            spannableTitle.setSpan(new ForegroundColorSpan(
-                    Utils.getColorAttrDefaultColor(mContext, android.R.attr.textColorSecondary)),
-                    deviceName.length(),
-                    spannableTitle.length(), SPAN_EXCLUSIVE_EXCLUSIVE);
-            return spannableTitle;
-        }
-        return super.getItemTitle(device);
-    }
-
     class MediaDeviceViewHolder extends MediaDeviceBaseViewHolder {
 
         MediaDeviceViewHolder(View view) {
@@ -166,6 +145,14 @@
                             false /* showProgressBar */, false /* showSubtitle */);
                     initSeekbar(device);
                     mCurrentActivePosition = position;
+                } else if (
+                        device.getDeviceType() == MediaDevice.MediaDeviceType.TYPE_BLUETOOTH_DEVICE
+                                && !device.isConnected()) {
+                    setTwoLineLayout(device, false /* bFocused */,
+                            false /* showSeekBar */, false /* showProgressBar */,
+                            true /* showSubtitle */);
+                    mSubTitleText.setText(R.string.media_output_dialog_disconnected);
+                    mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
                 } else {
                     setSingleLineLayout(getItemTitle(device), false /* bFocused */);
                     mContainerLayout.setOnClickListener(v -> onItemClick(v, device));
@@ -175,7 +162,6 @@
 
         @Override
         void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
-            super.onBind(customizedItem, topMargin, bottomMargin);
             if (customizedItem == CUSTOMIZED_ITEM_PAIR_NEW) {
                 mCheckBox.setVisibility(View.GONE);
                 mAddIcon.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
index 1ffc2c4..868193b 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseAdapter.java
@@ -153,9 +153,7 @@
             });
         }
 
-        void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
-            // TODO (b/201718621): clean up method after adjustment
-        }
+        abstract void onBind(int customizedItem, boolean topMargin, boolean bottomMargin);
 
         void setSingleLineLayout(CharSequence title, boolean bFocused) {
             mTwoLineLayout.setVisibility(View.GONE);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
index 6895ef1..26ce645 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -104,8 +104,6 @@
         lp.setFitInsetsIgnoringVisibility(true);
         window.setAttributes(lp);
         window.setContentView(mDialogView);
-        window.setLayout(mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width),
-                ViewGroup.LayoutParams.WRAP_CONTENT);
 
         mHeaderTitle = mDialogView.requireViewById(R.id.header_title);
         mHeaderSubtitle = mDialogView.requireViewById(R.id.header_subtitle);
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
index 11d76db..a201c07 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupAdapter.java
@@ -126,7 +126,6 @@
 
         @Override
         void onBind(int customizedItem, boolean topMargin, boolean bottomMargin) {
-            super.onBind(customizedItem, topMargin, bottomMargin);
             if (customizedItem == CUSTOMIZED_ITEM_GROUP) {
                 setTwoLineLayout(mContext.getText(R.string.media_output_dialog_group),
                         true /* bFocused */, true /* showSeekBar */, false /* showProgressBar */,
diff --git a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
index e3e2367..00124ac 100644
--- a/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
+++ b/packages/SystemUI/src/com/android/systemui/navigationbar/buttons/KeyButtonRipple.java
@@ -37,6 +37,8 @@
 import com.android.systemui.R;
 import com.android.systemui.animation.Interpolators;
 
+import androidx.annotation.Keep;
+
 import java.util.ArrayList;
 import java.util.HashSet;
 
@@ -184,19 +186,27 @@
         }
     }
 
+    /** Gets the glow alpha, used by {@link android.animation.ObjectAnimator} via reflection. */
+    @Keep
     public float getGlowAlpha() {
         return mGlowAlpha;
     }
 
+    /** Sets the glow alpha, used by {@link android.animation.ObjectAnimator} via reflection. */
+    @Keep
     public void setGlowAlpha(float x) {
         mGlowAlpha = x;
         invalidateSelf();
     }
 
+    /** Gets the glow scale, used by {@link android.animation.ObjectAnimator} via reflection. */
+    @Keep
     public float getGlowScale() {
         return mGlowScale;
     }
 
+    /** Sets the glow scale, used by {@link android.animation.ObjectAnimator} via reflection. */
+    @Keep
     public void setGlowScale(float x) {
         mGlowScale = x;
         invalidateSelf();
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
index 1d2e747..eec69f98 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyChipBuilder.kt
@@ -28,7 +28,7 @@
         appsAndTypes = itemsList.groupBy({ it.application }, { it.privacyType })
                 .toList()
                 .sortedWith(compareBy({ -it.second.size }, // Sort by number of AppOps
-                        { it.second.min() })) // Sort by "smallest" AppOpp (Location is largest)
+                        { it.second.minOrNull() })) // Sort by "smallest" AppOpp (Location is largest)
         types = itemsList.map { it.privacyType }.distinct().sorted()
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
index 9e8f6b8..23482677 100644
--- a/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/privacy/PrivacyDialog.kt
@@ -24,7 +24,6 @@
 import android.view.LayoutInflater
 import android.view.View
 import android.view.ViewGroup
-import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
 import android.view.WindowInsets
 import android.widget.ImageView
 import android.widget.TextView
@@ -65,7 +64,6 @@
         window?.apply {
             attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
             attributes.receiveInsetsIgnoringZOrder = true
-            setLayout(context.resources.getDimensionPixelSize(R.dimen.qs_panel_width), WRAP_CONTENT)
             setGravity(Gravity.TOP or Gravity.CENTER_HORIZONTAL)
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
index 1a7a306..7e5ff8a 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/PagedTileLayout.java
@@ -166,6 +166,11 @@
         updateListening();
     }
 
+    @Override
+    public void setSquishinessFraction(float squishinessFraction) {
+        // No-op, paged layouts are not squishy.
+    }
+
     private void updateListening() {
         for (TileLayout tilePage : mPages) {
             tilePage.setListening(tilePage.getParent() != null && mListening);
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
index 90d3448..44d5e21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSAnimator.java
@@ -316,8 +316,8 @@
 
                     if (mQQSTileHeightAnimator == null) {
                         mQQSTileHeightAnimator = new HeightExpansionAnimator(this,
-                                quickTileView.getHeight(), tileView.getHeight());
-                        qqsTileHeight = quickTileView.getHeight();
+                                quickTileView.getMeasuredHeight(), tileView.getMeasuredHeight());
+                        qqsTileHeight = quickTileView.getMeasuredHeight();
                     }
 
                     mQQSTileHeightAnimator.addView(quickTileView);
@@ -380,7 +380,7 @@
                     if (mOtherTilesExpandAnimator == null) {
                         mOtherTilesExpandAnimator =
                                 new HeightExpansionAnimator(
-                                        this, qqsTileHeight, tileView.getHeight());
+                                        this, qqsTileHeight, tileView.getMeasuredHeight());
                     }
                     mOtherTilesExpandAnimator.addView(tileView);
                     tileView.setClipChildren(true);
@@ -658,7 +658,7 @@
         mTranslateWhileExpanding = shouldTranslate;
     }
 
-    static class HeightExpansionAnimator {
+    private static class HeightExpansionAnimator {
         private final List<View> mViews = new ArrayList<>();
         private final ValueAnimator mAnimator;
         private final TouchAnimator.Listener mListener;
@@ -673,9 +673,10 @@
                 int height = (Integer) valueAnimator.getAnimatedValue();
                 for (int i = 0; i < viewCount; i++) {
                     View v = mViews.get(i);
-                    v.setBottom(v.getTop() + height);
                     if (v instanceof HeightOverrideable) {
                         ((HeightOverrideable) v).setHeightOverride(height);
+                    } else {
+                        v.setBottom(v.getTop() + height);
                     }
                 }
                 if (t == 0f) {
@@ -713,9 +714,10 @@
             final int viewsCount = mViews.size();
             for (int i = 0; i < viewsCount; i++) {
                 View v = mViews.get(i);
-                v.setBottom(v.getTop() + v.getMeasuredHeight());
                 if (v instanceof HeightOverrideable) {
                     ((HeightOverrideable) v).resetOverride();
+                } else {
+                    v.setBottom(v.getTop() + v.getMeasuredHeight());
                 }
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
index 3fc4f50..8588ddf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSContainerImpl.java
@@ -32,6 +32,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.qs.customize.QSCustomizer;
+import com.android.systemui.util.Utils;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -155,8 +156,7 @@
             QuickStatusBarHeaderController quickStatusBarHeaderController) {
         mQSPanelContainer.setPaddingRelative(
                 getPaddingStart(),
-                mContext.getResources()
-                        .getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height),
+                Utils.getQsHeaderSystemIconsAreaHeight(mContext),
                 getPaddingEnd(),
                 getPaddingBottom()
         );
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
index 58a942a..d43404b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSDetail.java
@@ -40,6 +40,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.UiEventLogger;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.FontSizeUtils;
 import com.android.systemui.R;
@@ -164,8 +165,7 @@
     public void updateResources() {
         updateDetailText();
         MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams();
-        lp.topMargin = mContext.getResources().getDimensionPixelSize(
-                com.android.internal.R.dimen.quick_qs_offset_height);
+        lp.topMargin = SystemBarUtils.getQuickQsOffsetHeight(mContext);
         setLayoutParams(lp);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
index 7a78601..eeca239 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSFragment.java
@@ -54,7 +54,6 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
-import com.android.systemui.util.InjectionInflationController;
 import com.android.systemui.util.LifecycleFragment;
 import com.android.systemui.util.Utils;
 
@@ -82,6 +81,7 @@
 
     private QSAnimator mQSAnimator;
     private HeightListener mPanelView;
+    private QSSquishinessController mQSSquishinessController;
     protected QuickStatusBarHeader mHeader;
     protected NonInterceptingScrollView mQSPanelScrollView;
     private QSDetail mQSDetail;
@@ -91,11 +91,11 @@
     private QSFooter mFooter;
     private float mLastQSExpansion = -1;
     private float mLastPanelFraction;
+    private float mSquishinessFraction = 1;
     private boolean mQsDisabled;
     private ImageView mQsDragHandler;
 
     private final RemoteInputQuickSettingsDisabler mRemoteInputQuickSettingsDisabler;
-    private final InjectionInflationController mInjectionInflater;
     private final CommandQueue mCommandQueue;
     private final QSDetailDisplayer mQsDetailDisplayer;
     private final MediaHost mQsMediaHost;
@@ -145,7 +145,7 @@
 
     @Inject
     public QSFragment(RemoteInputQuickSettingsDisabler remoteInputQsDisabler,
-            InjectionInflationController injectionInflater, QSTileHost qsTileHost,
+            QSTileHost qsTileHost,
             StatusBarStateController statusBarStateController, CommandQueue commandQueue,
             QSDetailDisplayer qsDetailDisplayer, @Named(QS_PANEL) MediaHost qsMediaHost,
             @Named(QUICK_QS_PANEL) MediaHost qqsMediaHost,
@@ -153,7 +153,6 @@
             QSFragmentComponent.Factory qsComponentFactory,
             FalsingManager falsingManager, DumpManager dumpManager) {
         mRemoteInputQuickSettingsDisabler = remoteInputQsDisabler;
-        mInjectionInflater = injectionInflater;
         mCommandQueue = commandQueue;
         mQsDetailDisplayer = qsDetailDisplayer;
         mQsMediaHost = qsMediaHost;
@@ -170,9 +169,8 @@
     @Override
     public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
             Bundle savedInstanceState) {
-        inflater = mInjectionInflater.injectable(
-                inflater.cloneInContext(new ContextThemeWrapper(getContext(),
-                        R.style.Theme_SystemUI_QuickSettings)));
+        inflater = inflater.cloneInContext(new ContextThemeWrapper(getContext(),
+                R.style.Theme_SystemUI_QuickSettings));
         return inflater.inflate(R.layout.qs_panel, container, false);
     }
 
@@ -214,6 +212,7 @@
 
         mQSDetail.setQsPanel(mQSPanelController, mHeader, mFooter, mFalsingManager);
         mQSAnimator = qsFragmentComponent.getQSAnimator();
+        mQSSquishinessController = qsFragmentComponent.getQSSquishinessController();
 
         mQSCustomizerController = qsFragmentComponent.getQSCustomizerController();
         mQSCustomizerController.init();
@@ -235,7 +234,7 @@
                     boolean sizeChanged = (oldTop - oldBottom) != (top - bottom);
                     if (sizeChanged) {
                         setQsExpansion(mLastQSExpansion, mLastPanelFraction,
-                                mLastHeaderTranslation);
+                                mLastHeaderTranslation, mSquishinessFraction);
                     }
                 });
         mQSPanelController.setUsingHorizontalLayoutChangeListener(
@@ -417,7 +416,8 @@
                 mQSAnimator.setShowCollapsedOnKeyguard(showCollapsed);
             }
             if (!showCollapsed && isKeyguardState()) {
-                setQsExpansion(mLastQSExpansion, mLastPanelFraction, 0);
+                setQsExpansion(mLastQSExpansion, mLastPanelFraction, 0,
+                        mSquishinessFraction);
             }
         }
     }
@@ -498,12 +498,13 @@
             updateShowCollapsedOnKeyguard();
         }
         mFullShadeProgress = progress;
-        setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation);
+        setQsExpansion(mLastQSExpansion, mLastPanelFraction, mLastHeaderTranslation,
+                isTransitioningToFullShade ? progress : mSquishinessFraction);
     }
 
     @Override
     public void setQsExpansion(float expansion, float panelExpansionFraction,
-            float proposedTranslation) {
+            float proposedTranslation, float squishinessFraction) {
         float headerTranslation = mTransitioningToFullShade ? 0 : proposedTranslation;
         float progress = mTransitioningToFullShade ? mFullShadeProgress : panelExpansionFraction;
         setAlphaAnimationProgress(mInSplitShade ? progress : 1);
@@ -521,11 +522,13 @@
         if (expansion == mLastQSExpansion
                 && mLastKeyguardAndExpanded == onKeyguardAndExpanded
                 && mLastViewHeight == currentHeight
-                && mLastHeaderTranslation == headerTranslation) {
+                && mLastHeaderTranslation == headerTranslation
+                && mSquishinessFraction == squishinessFraction) {
             return;
         }
         mLastHeaderTranslation = headerTranslation;
         mLastPanelFraction = panelExpansionFraction;
+        mSquishinessFraction = squishinessFraction;
         mLastQSExpansion = expansion;
         mLastKeyguardAndExpanded = onKeyguardAndExpanded;
         mLastViewHeight = currentHeight;
@@ -561,6 +564,9 @@
         }
         updateQsBounds();
 
+        if (mQSSquishinessController != null) {
+            mQSSquishinessController.setSquishiness(mSquishinessFraction);
+        }
         if (mQSAnimator != null) {
             mQSAnimator.setPosition(expansion);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
index 28aa884..71eb4a2 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanel.java
@@ -41,7 +41,7 @@
 import com.android.systemui.R;
 import com.android.systemui.plugins.qs.DetailAdapter;
 import com.android.systemui.plugins.qs.QSTile;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.tuner.TunerService;
 import com.android.systemui.tuner.TunerService.Tunable;
@@ -69,7 +69,7 @@
     @Nullable
     protected View mBrightnessView;
     @Nullable
-    protected BrightnessSlider mToggleSliderController;
+    protected BrightnessSliderController mToggleSliderController;
 
     private final H mHandler = new H();
     /** Whether or not the QS media player feature is enabled. */
@@ -736,6 +736,11 @@
         void setListening(boolean listening, UiEventLogger uiEventLogger);
 
         /**
+         * Sets a size modifier for the tile. Where 0 means collapsed, and 1 expanded.
+         */
+        void setSquishinessFraction(float squishinessFraction);
+
+        /**
          * Sets the minimum number of rows to show
          *
          * @param minRows the minimum.
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
index 70892a7..6794d5b 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSPanelController.java
@@ -41,7 +41,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.settings.brightness.BrightnessController;
 import com.android.systemui.settings.brightness.BrightnessMirrorHandler;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 import com.android.systemui.tuner.TunerService;
@@ -63,7 +63,7 @@
     private final FalsingManager mFalsingManager;
     private final CommandQueue mCommandQueue;
     private final BrightnessController mBrightnessController;
-    private final BrightnessSlider mBrightnessSlider;
+    private final BrightnessSliderController mBrightnessSliderController;
     private final BrightnessMirrorHandler mBrightnessMirrorHandler;
 
     private boolean mGridContentVisible = true;
@@ -99,8 +99,8 @@
             QSTileRevealController.Factory qsTileRevealControllerFactory,
             DumpManager dumpManager, MetricsLogger metricsLogger, UiEventLogger uiEventLogger,
             QSLogger qsLogger, BrightnessController.Factory brightnessControllerFactory,
-            BrightnessSlider.Factory brightnessSliderFactory, FalsingManager falsingManager,
-            CommandQueue commandQueue) {
+            BrightnessSliderController.Factory brightnessSliderFactory,
+            FalsingManager falsingManager, CommandQueue commandQueue) {
         super(view, qstileHost, qsCustomizerController, usingMediaPlayer, mediaHost,
                 metricsLogger, uiEventLogger, qsLogger, dumpManager);
         mQsSecurityFooter = qsSecurityFooter;
@@ -111,10 +111,10 @@
         mCommandQueue = commandQueue;
         mQsSecurityFooter.setHostEnvironment(qstileHost);
 
-        mBrightnessSlider = brightnessSliderFactory.create(getContext(), mView);
-        mView.setBrightnessView(mBrightnessSlider.getRootView());
+        mBrightnessSliderController = brightnessSliderFactory.create(getContext(), mView);
+        mView.setBrightnessView(mBrightnessSliderController.getRootView());
 
-        mBrightnessController = brightnessControllerFactory.create(mBrightnessSlider);
+        mBrightnessController = brightnessControllerFactory.create(mBrightnessSliderController);
         mBrightnessMirrorHandler = new BrightnessMirrorHandler(mBrightnessController);
     }
 
@@ -125,7 +125,7 @@
         mMediaHost.setShowsOnlyActiveMedia(false);
         mMediaHost.init(MediaHierarchyManager.LOCATION_QS);
         mQsCustomizerController.init();
-        mBrightnessSlider.init();
+        mBrightnessSliderController.init();
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
new file mode 100644
index 0000000..6de8370
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/qs/QSSquishinessController.kt
@@ -0,0 +1,64 @@
+package com.android.systemui.qs
+
+import android.view.ViewGroup
+import com.android.systemui.qs.dagger.QSFragmentModule.QQS_FOOTER
+import com.android.systemui.qs.dagger.QSScope
+import com.android.systemui.qs.tileimpl.HeightOverrideable
+import javax.inject.Inject
+import javax.inject.Named
+
+@QSScope
+class QSSquishinessController @Inject constructor(
+    private val qsTileHost: QSTileHost,
+    @Named(QQS_FOOTER) private val qqsFooterActionsView: FooterActionsView,
+    private val qsAnimator: QSAnimator,
+    private val quickQSPanelController: QuickQSPanelController
+) {
+
+    /**
+     * Fraction from 0 to 1, where 0 is collapsed and 1 expanded.
+     */
+    var squishiness: Float = 1f
+    set(value) {
+        if (field == value) {
+            return
+        }
+        if ((field != 1f && value == 1f) || (field != 0f && value == 0f)) {
+            qsAnimator.requestAnimatorUpdate()
+        }
+        field = value
+        updateSquishiness()
+    }
+
+    /**
+     * Change the height of all tiles and repositions their siblings.
+     */
+    private fun updateSquishiness() {
+        // Start by updating the height of all tiles
+        for (tile in qsTileHost.tiles) {
+            val tileView = quickQSPanelController.getTileView(tile)
+            (tileView as? HeightOverrideable)?.let {
+                it.squishinessFraction = squishiness
+            }
+        }
+
+        // Update tile positions in the layout
+        val tileLayout = quickQSPanelController.tileLayout as TileLayout
+        tileLayout.setSquishinessFraction(squishiness)
+
+        // Calculate how much we should move the footer
+        val tileHeightOffset = tileLayout.height - tileLayout.tilesHeight
+        val footerTopMargin = (qqsFooterActionsView.layoutParams as ViewGroup.MarginLayoutParams)
+                .topMargin
+        val nextTop = tileLayout.bottom - tileHeightOffset + footerTopMargin
+        val amountMoved = nextTop - qqsFooterActionsView.top
+
+        // Move the footer and other siblings (MediaPlayer)
+        (qqsFooterActionsView.parent as ViewGroup?)?.let { parent ->
+            val index = parent.indexOfChild(qqsFooterActionsView)
+            for (i in index until parent.childCount) {
+                parent.getChildAt(i).top += amountMoved
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
index 14374ff..65889d7 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickQSBrightnessController.kt
@@ -18,7 +18,7 @@
 
 import androidx.annotation.VisibleForTesting
 import com.android.systemui.settings.brightness.BrightnessController
-import com.android.systemui.settings.brightness.BrightnessSlider
+import com.android.systemui.settings.brightness.BrightnessSliderController
 import com.android.systemui.settings.brightness.MirroredBrightnessController
 import com.android.systemui.statusbar.policy.BrightnessMirrorController
 import javax.inject.Inject
@@ -33,10 +33,11 @@
 
     @Inject constructor(
         brightnessControllerFactory: BrightnessController.Factory,
-        brightnessSliderFactory: BrightnessSlider.Factory,
+        brightnessSliderControllerFactory: BrightnessSliderController.Factory,
         quickQSPanel: QuickQSPanel
     ) : this(brightnessControllerFactory = {
-            val slider = brightnessSliderFactory.create(quickQSPanel.context, quickQSPanel)
+            val slider = brightnessSliderControllerFactory.create(quickQSPanel.context,
+                    quickQSPanel)
             slider.init()
             quickQSPanel.setBrightnessView(slider.rootView)
             brightnessControllerFactory.create(slider)
diff --git a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
index a81d3c6..071e053 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/QuickStatusBarHeader.java
@@ -34,6 +34,7 @@
 
 import androidx.annotation.NonNull;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.settingslib.Utils;
 import com.android.systemui.R;
 import com.android.systemui.battery.BatteryMeterView;
@@ -240,8 +241,7 @@
         mRoundedCornerPadding = resources.getDimensionPixelSize(
                 R.dimen.rounded_corner_content_padding);
 
-        int qsOffsetHeight = resources.getDimensionPixelSize(
-                com.android.internal.R.dimen.quick_qs_offset_height);
+        int qsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mContext);
 
         mDatePrivacyView.getLayoutParams().height =
                 Math.max(qsOffsetHeight, mDatePrivacyView.getMinimumHeight());
diff --git a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
index 1a890a7..ee5d5ff 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/TileLayout.java
@@ -41,6 +41,8 @@
     private int mMinRows = 1;
     private int mMaxColumns = NO_MAX_COLUMNS;
     protected int mResourceColumns;
+    private float mSquishinessFraction = 1f;
+    private int mLastTileBottom;
 
     public TileLayout(Context context) {
         this(context, null);
@@ -210,10 +212,11 @@
         return mMaxCellHeight;
     }
 
-    protected void layoutTileRecords(int numRecords) {
+    private void layoutTileRecords(int numRecords) {
         final boolean isRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
         int row = 0;
         int column = 0;
+        mLastTileBottom = 0;
 
         // Layout each QS tile.
         final int tilesToLayout = Math.min(numRecords, mRows * mColumns);
@@ -228,7 +231,9 @@
             final int top = getRowTop(row);
             final int left = getColumnStart(isRtl ? mColumns - column - 1 : column);
             final int right = left + mCellWidth;
-            record.tileView.layout(left, top, right, top + record.tileView.getMeasuredHeight());
+            final int bottom = top + record.tileView.getMeasuredHeight();
+            record.tileView.layout(left, top, right, bottom);
+            mLastTileBottom = bottom;
         }
     }
 
@@ -238,7 +243,7 @@
     }
 
     protected int getRowTop(int row) {
-        return row * (mCellHeight + mCellMarginVertical);
+        return (int) (row * (mCellHeight * mSquishinessFraction + mCellMarginVertical));
     }
 
     protected int getColumnStart(int column) {
@@ -264,4 +269,17 @@
         // up.
         return Math.max(mColumns * mRows, 1);
     }
+
+    public int getTilesHeight() {
+        return mLastTileBottom + getPaddingBottom();
+    }
+
+    @Override
+    public void setSquishinessFraction(float squishinessFraction) {
+        if (Float.compare(mSquishinessFraction, squishinessFraction) == 0) {
+            return;
+        }
+        mSquishinessFraction = squishinessFraction;
+        layoutTileRecords(mRecords.size());
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
index 1a6d490..0a45262 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/customize/QSCustomizer.java
@@ -36,6 +36,7 @@
 import com.android.systemui.plugins.qs.QSContainerController;
 import com.android.systemui.qs.QSDetailClipper;
 import com.android.systemui.statusbar.phone.LightBarController;
+import com.android.systemui.util.Utils;
 
 /**
  * Allows full-screen customization of QS, through show() and hide().
@@ -84,8 +85,7 @@
 
     void updateResources() {
         LayoutParams lp = (LayoutParams) mTransparentView.getLayoutParams();
-        lp.height = mContext.getResources()
-                .getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height);
+        lp.height = Utils.getQsHeaderSystemIconsAreaHeight(mContext);
         mTransparentView.setLayoutParams(lp);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
index 8cc0502..63cbc21 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/dagger/QSFragmentComponent.java
@@ -21,6 +21,7 @@
 import com.android.systemui.qs.QSFooter;
 import com.android.systemui.qs.QSFragment;
 import com.android.systemui.qs.QSPanelController;
+import com.android.systemui.qs.QSSquishinessController;
 import com.android.systemui.qs.QuickQSPanelController;
 import com.android.systemui.qs.customize.QSCustomizerController;
 
@@ -57,4 +58,7 @@
 
     /** Construct a {@link QSCustomizerController}. */
     QSCustomizerController getQSCustomizerController();
+
+    /** Construct a {@link QSSquishinessController}. */
+    QSSquishinessController getQSSquishinessController();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
index 866fa09..61d68ec 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/HeightOverrideable.kt
@@ -21,9 +21,8 @@
         const val NO_OVERRIDE = -1
     }
 
-    var heightOverride: Int
+    abstract var heightOverride: Int
+    abstract fun resetOverride()
 
-    fun resetOverride() {
-        heightOverride = NO_OVERRIDE
-    }
+    abstract var squishinessFraction: Float
 }
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
index 222539d..69be3326 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tileimpl/QSTileViewImpl.kt
@@ -42,6 +42,7 @@
 import com.android.settingslib.Utils
 import com.android.systemui.FontSizeUtils
 import com.android.systemui.R
+import com.android.systemui.animation.LaunchableView
 import com.android.systemui.plugins.qs.QSIconView
 import com.android.systemui.plugins.qs.QSTile
 import com.android.systemui.plugins.qs.QSTile.BooleanState
@@ -54,7 +55,7 @@
     context: Context,
     private val _icon: QSIconView,
     private val collapsed: Boolean = false
-) : QSTileView(context), HeightOverrideable {
+) : QSTileView(context), HeightOverrideable, LaunchableView {
 
     companion object {
         private const val INVALID = -1
@@ -68,6 +69,18 @@
     }
 
     override var heightOverride: Int = HeightOverrideable.NO_OVERRIDE
+        set(value) {
+            if (field == value) return
+            field = value
+            updateHeight()
+        }
+
+    override var squishinessFraction: Float = 1f
+        set(value) {
+            if (field == value) return
+            field = value
+            updateHeight()
+        }
 
     private val colorActive = Utils.getColorAttrDefaultColor(context,
             com.android.internal.R.attr.colorAccentPrimary)
@@ -118,6 +131,8 @@
     private var lastStateDescription: CharSequence? = null
     private var tileState = false
     private var lastState = INVALID
+    private var blockVisibilityChanges = false
+    private var lastVisibility = View.VISIBLE
 
     private val locInScreen = IntArray(2)
 
@@ -148,6 +163,11 @@
         updateResources()
     }
 
+    override fun resetOverride() {
+        heightOverride = HeightOverrideable.NO_OVERRIDE
+        updateHeight()
+    }
+
     fun updateResources() {
         FontSizeUtils.updateFontSize(label, R.dimen.qs_tile_text_size)
         FontSizeUtils.updateFontSize(secondaryLabel, R.dimen.qs_tile_text_size)
@@ -218,9 +238,17 @@
 
     override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
         super.onLayout(changed, l, t, r, b)
-        if (heightOverride != HeightOverrideable.NO_OVERRIDE) {
-            bottom = top + heightOverride
-        }
+        updateHeight()
+    }
+
+    private fun updateHeight() {
+        val actualHeight = (if (heightOverride != HeightOverrideable.NO_OVERRIDE) {
+            heightOverride
+        } else {
+            measuredHeight
+        } * squishinessFraction).toInt()
+        bottom = top + actualHeight
+        scrollY = (actualHeight - height) / 2
     }
 
     override fun updateAccessibilityOrder(previousView: View?): View {
@@ -294,6 +322,36 @@
         return sideView
     }
 
+    override fun setShouldBlockVisibilityChanges(block: Boolean) {
+        blockVisibilityChanges = block
+
+        if (block) {
+            lastVisibility = visibility
+        } else {
+            visibility = lastVisibility
+        }
+    }
+
+    override fun setVisibility(visibility: Int) {
+        if (blockVisibilityChanges) {
+            lastVisibility = visibility
+            return
+        }
+
+        super.setVisibility(visibility)
+    }
+
+    override fun setTransitionVisibility(visibility: Int) {
+        if (blockVisibilityChanges) {
+            // View.setTransitionVisibility just sets the visibility flag, so we don't have to save
+            // the transition visibility separately from the normal visibility.
+            lastVisibility = visibility
+            return
+        }
+
+        super.setTransitionVisibility(visibility)
+    }
+
     // Accessibility
 
     override fun onInitializeAccessibilityEvent(event: AccessibilityEvent) {
@@ -459,7 +517,7 @@
     }
 
     private fun setColor(color: Int) {
-        colorBackgroundDrawable.setTint(color)
+        colorBackgroundDrawable.mutate().setTint(color)
         paintColor = color
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
index bc21b2d..80ec0ad 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DeviceControlsTile.kt
@@ -112,20 +112,9 @@
         }
 
         mUiHandler.post {
-            if (keyguardStateController.isUnlocked) {
-                mActivityStarter.startActivity(
-                        intent, true /* dismissShade */, animationController)
-            } else {
-                if (state.state == Tile.STATE_ACTIVE) {
-                    mHost.collapsePanels()
-                    // With an active tile, don't use ActivityStarter so that the activity is
-                    // started without prompting keyguard unlock.
-                    mContext.startActivity(intent)
-                } else {
-                    mActivityStarter.postStartActivityDismissingKeyguard(
-                            intent, 0 /* delay */, animationController)
-                }
-            }
+            val showOverLockscreenWhenLocked = state.state == Tile.STATE_ACTIVE
+            mActivityStarter.startActivity(
+                intent, true /* dismissShade */, animationController, showOverLockscreenWhenLocked)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
index 98d0a72..23b2a76 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/InternetTile.java
@@ -124,7 +124,7 @@
     protected void handleClick(@Nullable View view) {
         mHandler.post(() -> mInternetDialogFactory.create(true,
                 mAccessPointController.canConfigMobileData(),
-                mAccessPointController.canConfigWifi()));
+                mAccessPointController.canConfigWifi(), view));
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
index 11430d9..1dab263 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialog.java
@@ -15,14 +15,10 @@
  */
 package com.android.systemui.qs.tiles.dialog;
 
-import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS;
-
 import static com.android.systemui.Prefs.Key.QS_HAS_TURNED_OFF_MOBILE_DATA;
 
 import android.app.AlertDialog;
 import android.content.Context;
-import android.graphics.Color;
-import android.graphics.drawable.ColorDrawable;
 import android.graphics.drawable.Drawable;
 import android.net.Network;
 import android.net.NetworkCapabilities;
@@ -36,14 +32,12 @@
 import android.telephony.TelephonyManager;
 import android.text.Html;
 import android.text.TextUtils;
+import android.text.method.LinkMovementMethod;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewTreeObserver;
 import android.view.Window;
-import android.view.WindowInsets;
 import android.view.WindowManager;
 import android.widget.FrameLayout;
 import android.widget.ImageView;
@@ -63,12 +57,15 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.Prefs;
 import com.android.systemui.R;
+import com.android.systemui.accessibility.floatingmenu.AnnotationLinkSpan;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
 import com.android.wifitrackerlib.WifiEntry;
 
 import java.util.List;
+import java.util.concurrent.Executor;
 
 /**
  * Dialog for showing mobile network, connected Wi-Fi network and Wi-Fi networks.
@@ -82,7 +79,7 @@
     static final long PROGRESS_DELAY_MS = 2000L;
 
     private final Handler mHandler;
-    private final LinearLayoutManager mLayoutManager;
+    private final Executor mBackgroundExecutor;
 
     @VisibleForTesting
     protected InternetAdapter mAdapter;
@@ -110,6 +107,8 @@
     private LinearLayout mTurnWifiOnLayout;
     private LinearLayout mEthernetLayout;
     private TextView mWifiToggleTitleText;
+    private LinearLayout mWifiScanNotifyLayout;
+    private TextView mWifiScanNotifyText;
     private LinearLayout mSeeAllLayout;
     private RecyclerView mWifiRecyclerView;
     private ImageView mConnectedWifiIcon;
@@ -123,7 +122,6 @@
     private Switch mWiFiToggle;
     private FrameLayout mDoneLayout;
     private Drawable mBackgroundOn;
-    private int mListMaxHeight;
     private int mDefaultDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
     private boolean mCanConfigMobileData;
 
@@ -142,25 +140,17 @@
         mInternetDialogSubTitle.setText(getSubtitleText());
     };
 
-    private final ViewTreeObserver.OnGlobalLayoutListener mInternetListLayoutListener = () -> {
-        // Set max height for list
-        if (mInternetDialogLayout.getHeight() > mListMaxHeight) {
-            ViewGroup.LayoutParams params = mInternetDialogLayout.getLayoutParams();
-            params.height = mListMaxHeight;
-            mInternetDialogLayout.setLayoutParams(params);
-        }
-    };
-
     public InternetDialog(Context context, InternetDialogFactory internetDialogFactory,
             InternetDialogController internetDialogController, boolean canConfigMobileData,
             boolean canConfigWifi, boolean aboveStatusBar, UiEventLogger uiEventLogger,
-            @Main Handler handler) {
-        super(context, R.style.Theme_SystemUI_Dialog_Internet);
+            @Main Handler handler, @Background Executor executor) {
+        super(context);
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialog");
         }
         mContext = context;
         mHandler = handler;
+        mBackgroundExecutor = executor;
         mInternetDialogFactory = internetDialogFactory;
         mInternetDialogController = internetDialogController;
         mSubscriptionManager = mInternetDialogController.getSubscriptionManager();
@@ -170,14 +160,6 @@
         mCanConfigMobileData = canConfigMobileData;
         mCanConfigWifi = canConfigWifi;
 
-        mLayoutManager = new LinearLayoutManager(mContext) {
-            @Override
-            public boolean canScrollVertically() {
-                return false;
-            }
-        };
-        mListMaxHeight = context.getResources().getDimensionPixelSize(
-                R.dimen.internet_dialog_list_max_height);
         mUiEventLogger = uiEventLogger;
         mAdapter = new InternetAdapter(mInternetDialogController);
         if (!aboveStatusBar) {
@@ -195,21 +177,9 @@
         mDialogView = LayoutInflater.from(mContext).inflate(R.layout.internet_connectivity_dialog,
                 null);
         final Window window = getWindow();
-        final WindowManager.LayoutParams layoutParams = window.getAttributes();
-        layoutParams.gravity = Gravity.BOTTOM;
-        // Move down the dialog to overlay the navigation bar.
-        layoutParams.setFitInsetsTypes(
-                layoutParams.getFitInsetsTypes() & ~WindowInsets.Type.navigationBars());
-        layoutParams.setFitInsetsSides(WindowInsets.Side.all());
-        layoutParams.setFitInsetsIgnoringVisibility(true);
-        window.setAttributes(layoutParams);
         window.setContentView(mDialogView);
-        //Only fix the width for large screen or tablet.
-        window.setLayout(mContext.getResources().getDimensionPixelSize(
-                R.dimen.large_dialog_width), ViewGroup.LayoutParams.WRAP_CONTENT);
+
         window.setWindowAnimations(R.style.Animation_InternetDialog);
-        window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
-        window.addFlags(FLAG_LAYOUT_NO_LIMITS);
 
         mInternetDialogLayout = mDialogView.requireViewById(R.id.internet_connectivity_dialog);
         mInternetDialogTitle = mDialogView.requireViewById(R.id.internet_dialog_title);
@@ -220,6 +190,8 @@
         mMobileNetworkLayout = mDialogView.requireViewById(R.id.mobile_network_layout);
         mTurnWifiOnLayout = mDialogView.requireViewById(R.id.turn_on_wifi_layout);
         mWifiToggleTitleText = mDialogView.requireViewById(R.id.wifi_toggle_title);
+        mWifiScanNotifyLayout = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
+        mWifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
         mConnectedWifListLayout = mDialogView.requireViewById(R.id.wifi_connected_layout);
         mConnectedWifiIcon = mDialogView.requireViewById(R.id.wifi_connected_icon);
         mConnectedWifiTitleText = mDialogView.requireViewById(R.id.wifi_connected_title);
@@ -234,14 +206,12 @@
         mMobileDataToggle = mDialogView.requireViewById(R.id.mobile_toggle);
         mWiFiToggle = mDialogView.requireViewById(R.id.wifi_toggle);
         mBackgroundOn = mContext.getDrawable(R.drawable.settingslib_switch_bar_bg_on);
-        mInternetDialogLayout.getViewTreeObserver().addOnGlobalLayoutListener(
-                mInternetListLayoutListener);
         mInternetDialogTitle.setText(getDialogTitleText());
         mInternetDialogTitle.setGravity(Gravity.START | Gravity.CENTER_VERTICAL);
 
         setOnClickListener();
         mTurnWifiOnLayout.setBackground(null);
-        mWifiRecyclerView.setLayoutManager(mLayoutManager);
+        mWifiRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));
         mWifiRecyclerView.setAdapter(mAdapter);
     }
 
@@ -293,7 +263,13 @@
         dismiss();
     }
 
-    void updateDialog() {
+    /**
+     * Update the internet dialog when receiving the callback.
+     *
+     * @param shouldUpdateMobileNetwork {@code true} for update the mobile network layout,
+     * otherwise {@code false}.
+     */
+    void updateDialog(boolean shouldUpdateMobileNetwork) {
         if (DEBUG) {
             Log.d(TAG, "updateDialog");
         }
@@ -303,8 +279,10 @@
             mInternetDialogSubTitle.setText(getSubtitleText());
         }
         updateEthernet();
-        setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular()
-                || mInternetDialogController.isCarrierNetworkActive());
+        if (shouldUpdateMobileNetwork) {
+            setMobileDataLayout(mInternetDialogController.activeNetworkIsCellular()
+                    || mInternetDialogController.isCarrierNetworkActive());
+        }
 
         if (!mCanConfigWifi) {
             return;
@@ -313,8 +291,10 @@
         showProgressBar();
         final boolean isDeviceLocked = mInternetDialogController.isDeviceLocked();
         final boolean isWifiEnabled = mWifiManager.isWifiEnabled();
+        final boolean isWifiScanEnabled = mInternetDialogController.isWifiScanEnabled();
         updateWifiToggle(isWifiEnabled, isDeviceLocked);
         updateConnectedWifi(isWifiEnabled, isDeviceLocked);
+        updateWifiScanNotify(isWifiEnabled, isWifiScanEnabled, isDeviceLocked);
 
         final int visibility = (isDeviceLocked || !isWifiEnabled || mWifiEntriesCount <= 0)
                 ? View.GONE : View.VISIBLE;
@@ -371,7 +351,13 @@
             } else {
                 mMobileSummaryText.setVisibility(View.GONE);
             }
-            mSignalIcon.setImageDrawable(getSignalStrengthDrawable());
+
+            mBackgroundExecutor.execute(() -> {
+                Drawable drawable = getSignalStrengthDrawable();
+                mHandler.post(() -> {
+                    mSignalIcon.setImageDrawable(drawable);
+                });
+            });
             mMobileTitleText.setTextAppearance(isCarrierNetworkConnected
                     ? R.style.TextAppearance_InternetDialog_Active
                     : R.style.TextAppearance_InternetDialog);
@@ -411,6 +397,24 @@
                 mContext.getColor(R.color.connected_network_primary_color));
     }
 
+    @MainThread
+    private void updateWifiScanNotify(boolean isWifiEnabled, boolean isWifiScanEnabled,
+            boolean isDeviceLocked) {
+        if (isWifiEnabled || !isWifiScanEnabled || isDeviceLocked) {
+            mWifiScanNotifyLayout.setVisibility(View.GONE);
+            return;
+        }
+        if (TextUtils.isEmpty(mWifiScanNotifyText.getText())) {
+            final AnnotationLinkSpan.LinkInfo linkInfo = new AnnotationLinkSpan.LinkInfo(
+                    AnnotationLinkSpan.LinkInfo.DEFAULT_ANNOTATION,
+                    v -> mInternetDialogController.launchWifiScanningSetting());
+            mWifiScanNotifyText.setText(AnnotationLinkSpan.linkify(
+                    getContext().getText(R.string.wifi_scan_notify_message), linkInfo));
+            mWifiScanNotifyText.setMovementMethod(LinkMovementMethod.getInstance());
+        }
+        mWifiScanNotifyLayout.setVisibility(View.VISIBLE);
+    }
+
     void onClickConnectedWifi() {
         if (mConnectedWifiEntry == null) {
             return;
@@ -458,10 +462,6 @@
     }
 
     private void setProgressBarVisible(boolean visible) {
-        if (mWifiManager.isWifiEnabled() && mAdapter.mHolderView != null
-                && mAdapter.mHolderView.isAttachedToWindow()) {
-            mIsProgressBarVisible = true;
-        }
         mIsProgressBarVisible = visible;
         mProgressBar.setVisibility(mIsProgressBarVisible ? View.VISIBLE : View.GONE);
         mDivider.setVisibility(mIsProgressBarVisible ? View.GONE : View.VISIBLE);
@@ -508,52 +508,57 @@
 
     @Override
     public void onRefreshCarrierInfo() {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     public void onSimStateChanged() {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     @WorkerThread
     public void onCapabilitiesChanged(Network network, NetworkCapabilities networkCapabilities) {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     @WorkerThread
     public void onLost(Network network) {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     public void onSubscriptionsChanged(int defaultDataSubId) {
         mDefaultDataSubId = defaultDataSubId;
         mTelephonyManager = mTelephonyManager.createForSubscriptionId(mDefaultDataSubId);
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
+    }
+
+    @Override
+    public void onUserMobileDataStateChanged(boolean enabled) {
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     public void onServiceStateChanged(ServiceState serviceState) {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     @WorkerThread
     public void onDataConnectionStateChanged(int state, int networkType) {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     public void onSignalStrengthsChanged(SignalStrength signalStrength) {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
     public void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo) {
-        mHandler.post(() -> updateDialog());
+        mHandler.post(() -> updateDialog(true /* shouldUpdateMobileNetwork */));
     }
 
     @Override
@@ -565,7 +570,7 @@
         mAdapter.setWifiEntries(wifiEntries, mWifiEntriesCount);
         mHandler.post(() -> {
             mAdapter.notifyDataSetChanged();
-            updateDialog();
+            updateDialog(false /* shouldUpdateMobileNetwork */);
         });
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
index b9cd08e..5673136 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogController.java
@@ -71,6 +71,7 @@
 import com.android.settingslib.net.SignalStrengthUtil;
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.systemui.R;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Background;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -78,6 +79,7 @@
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.toast.SystemUIToast;
 import com.android.systemui.toast.ToastFactory;
 import com.android.systemui.util.CarrierConfigTracker;
@@ -103,6 +105,8 @@
     private static final String TAG = "InternetDialogController";
     private static final String ACTION_NETWORK_PROVIDER_SETTINGS =
             "android.settings.NETWORK_PROVIDER_SETTINGS";
+    private static final String ACTION_WIFI_SCANNING_SETTINGS =
+            "android.settings.WIFI_SCANNING_SETTINGS";
     private static final String EXTRA_CHOSEN_WIFI_ENTRY_KEY = "key_chosen_wifientry_key";
     public static final Drawable EMPTY_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);
     public static final int NO_CELL_DATA_TYPE_ICON = 0;
@@ -147,6 +151,9 @@
     private ConnectivityManager.NetworkCallback mConnectivityManagerNetworkCallback;
     private WindowManager mWindowManager;
     private ToastFactory mToastFactory;
+    private SignalDrawable mSignalDrawable;
+    private LocationController mLocationController;
+    private DialogLaunchAnimator mDialogLaunchAnimator;
 
     @VisibleForTesting
     static final float TOAST_PARAMS_HORIZONTAL_WEIGHT = 1.0f;
@@ -196,7 +203,9 @@
             GlobalSettings globalSettings, KeyguardStateController keyguardStateController,
             WindowManager windowManager, ToastFactory toastFactory,
             @Background Handler workerHandler,
-            CarrierConfigTracker carrierConfigTracker) {
+            CarrierConfigTracker carrierConfigTracker,
+            LocationController locationController,
+            DialogLaunchAnimator dialogLaunchAnimator) {
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialogController");
         }
@@ -223,6 +232,9 @@
         mConnectivityManagerNetworkCallback = new DataConnectivityListener();
         mWindowManager = windowManager;
         mToastFactory = toastFactory;
+        mSignalDrawable = new SignalDrawable(mContext);
+        mLocationController = locationController;
+        mDialogLaunchAnimator = dialogLaunchAnimator;
     }
 
     void onStart(@NonNull InternetDialogCallback callback, boolean canConfigWifi) {
@@ -429,10 +441,7 @@
 
     Drawable getSignalStrengthIcon(Context context, int level, int numLevels,
             int iconType, boolean cutOut) {
-        Log.d(TAG, "getSignalStrengthIcon");
-        final SignalDrawable signalDrawable = new SignalDrawable(context);
-        signalDrawable.setLevel(
-                SignalDrawable.getState(level, numLevels, cutOut));
+        mSignalDrawable.setLevel(SignalDrawable.getState(level, numLevels, cutOut));
 
         // Make the network type drawable
         final Drawable networkDrawable =
@@ -441,7 +450,7 @@
                         : context.getResources().getDrawable(iconType, context.getTheme());
 
         // Overlay the two drawables
-        final Drawable[] layers = {networkDrawable, signalDrawable};
+        final Drawable[] layers = {networkDrawable, mSignalDrawable};
         final int iconSize =
                 context.getResources().getDimensionPixelSize(R.dimen.signal_strength_icon_size);
 
@@ -591,18 +600,37 @@
     }
 
     void launchNetworkSetting() {
+        // Dismissing a dialog into its touch surface and starting an activity at the same time
+        // looks bad, so let's make sure the dialog just fades out quickly.
+        mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
         mCallback.dismissDialog();
+
         mActivityStarter.postStartActivityDismissingKeyguard(getSettingsIntent(), 0);
     }
 
     void launchWifiNetworkDetailsSetting(String key) {
         Intent intent = getWifiDetailsSettingsIntent(key);
         if (intent != null) {
+            // Dismissing a dialog into its touch surface and starting an activity at the same time
+            // looks bad, so let's make sure the dialog just fades out quickly.
+            mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
             mCallback.dismissDialog();
+
             mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
         }
     }
 
+    void launchWifiScanningSetting() {
+        // Dismissing a dialog into its touch surface and starting an activity at the same time
+        // looks bad, so let's make sure the dialog just fades out quickly.
+        mDialogLaunchAnimator.disableAllCurrentDialogsExitAnimations();
+        mCallback.dismissDialog();
+
+        final Intent intent = new Intent(ACTION_WIFI_SCANNING_SETTINGS);
+        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+        mActivityStarter.postStartActivityDismissingKeyguard(intent, 0);
+    }
+
     void connectCarrierNetwork() {
         final MergedCarrierEntry mergedCarrierEntry =
                 mAccessPointController.getMergedCarrierEntry();
@@ -780,6 +808,14 @@
         return false;
     }
 
+    @WorkerThread
+    boolean isWifiScanEnabled() {
+        if (!mLocationController.isLocationEnabled()) {
+            return false;
+        }
+        return mWifiManager.isScanAlwaysAvailable();
+    }
+
     static class WifiEntryConnectCallback implements WifiEntry.ConnectCallback {
         final ActivityStarter mActivityStarter;
         final WifiEntry mWifiEntry;
@@ -883,7 +919,8 @@
             TelephonyCallback.DataConnectionStateListener,
             TelephonyCallback.DisplayInfoListener,
             TelephonyCallback.ServiceStateListener,
-            TelephonyCallback.SignalStrengthsListener {
+            TelephonyCallback.SignalStrengthsListener,
+            TelephonyCallback.UserMobileDataStateListener {
 
         @Override
         public void onServiceStateChanged(@NonNull ServiceState serviceState) {
@@ -905,6 +942,11 @@
             mTelephonyDisplayInfo = telephonyDisplayInfo;
             mCallback.onDisplayInfoChanged(telephonyDisplayInfo);
         }
+
+        @Override
+        public void onUserMobileDataStateChanged(boolean enabled) {
+            mCallback.onUserMobileDataStateChanged(enabled);
+        }
     }
 
     private class InternetOnSubscriptionChangedListener
@@ -1009,6 +1051,8 @@
 
         void onSignalStrengthsChanged(SignalStrength signalStrength);
 
+        void onUserMobileDataStateChanged(boolean enabled);
+
         void onDisplayInfoChanged(TelephonyDisplayInfo telephonyDisplayInfo);
 
         void dismissDialog();
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
index 11c6980..93828b3 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/dialog/InternetDialogFactory.kt
@@ -18,9 +18,13 @@
 import android.content.Context
 import android.os.Handler
 import android.util.Log
+import android.view.View
 import com.android.internal.logging.UiEventLogger
+import com.android.systemui.animation.DialogLaunchAnimator
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
+import java.util.concurrent.Executor
 import javax.inject.Inject
 
 private const val TAG = "InternetDialogFactory"
@@ -32,16 +36,23 @@
 @SysUISingleton
 class InternetDialogFactory @Inject constructor(
     @Main private val handler: Handler,
+    @Background private val executor: Executor,
     private val internetDialogController: InternetDialogController,
     private val context: Context,
-    private val uiEventLogger: UiEventLogger
+    private val uiEventLogger: UiEventLogger,
+    private val dialogLaunchAnimator: DialogLaunchAnimator
 ) {
     companion object {
         var internetDialog: InternetDialog? = null
     }
 
-    /** Creates a [InternetDialog]. */
-    fun create(aboveStatusBar: Boolean, canConfigMobileData: Boolean, canConfigWifi: Boolean) {
+    /** Creates a [InternetDialog]. The dialog will be animated from [view] if it is not null. */
+    fun create(
+        aboveStatusBar: Boolean,
+        canConfigMobileData: Boolean,
+        canConfigWifi: Boolean,
+        view: View?
+    ) {
         if (internetDialog != null) {
             if (DEBUG) {
                 Log.d(TAG, "InternetDialog is showing, do not create it twice.")
@@ -49,8 +60,13 @@
             return
         } else {
             internetDialog = InternetDialog(context, this, internetDialogController,
-                    canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler)
-            internetDialog?.show()
+                    canConfigMobileData, canConfigWifi, aboveStatusBar, uiEventLogger, handler,
+                    executor)
+            if (view != null) {
+                dialogLaunchAnimator.showFromView(internetDialog!!, view)
+            } else {
+                internetDialog?.show()
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
index 01afa56..26d1bbd 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/user/UserDialog.kt
@@ -71,10 +71,6 @@
             setType(WindowManager.LayoutParams.TYPE_STATUS_BAR_SUB_PANEL)
             attributes.fitInsetsTypes = attributes.fitInsetsTypes or WindowInsets.Type.statusBars()
             attributes.receiveInsetsIgnoringZOrder = true
-            setLayout(
-                    context.resources.getDimensionPixelSize(R.dimen.notification_panel_width),
-                    ViewGroup.LayoutParams.WRAP_CONTENT
-            )
             setGravity(Gravity.CENTER)
         }
         setContentView(R.layout.qs_user_dialog_content)
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
index acc6ee1..d7d1de0 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessController.java
@@ -51,8 +51,6 @@
 import com.android.systemui.settings.CurrentUserTracker;
 import com.android.systemui.statusbar.policy.BrightnessMirrorController;
 
-import java.util.ArrayList;
-
 import javax.inject.Inject;
 
 public class BrightnessController implements ToggleSlider.Listener, MirroredBrightnessController {
@@ -92,13 +90,9 @@
         @Override
         public void onDisplayChanged(int displayId) {
             mBackgroundHandler.post(mUpdateSliderRunnable);
-            notifyCallbacks();
         }
     };
 
-    private ArrayList<BrightnessStateChangeCallback> mChangeCallbacks =
-            new ArrayList<BrightnessStateChangeCallback>();
-
     private volatile boolean mAutomatic;  // Brightness adjusted automatically using ambient light.
     private volatile boolean mIsVrModeEnabled;
     private boolean mListening;
@@ -114,11 +108,6 @@
         mControl.setMirrorControllerAndMirror(controller);
     }
 
-    public interface BrightnessStateChangeCallback {
-        /** Indicates that some of the brightness settings have changed */
-        void onBrightnessLevelChanged();
-    }
-
     /** ContentObserver to watch brightness */
     private class BrightnessObserver extends ContentObserver {
 
@@ -139,7 +128,6 @@
                 mBackgroundHandler.post(mUpdateModeRunnable);
                 mBackgroundHandler.post(mUpdateSliderRunnable);
             }
-            notifyCallbacks();
         }
 
         public void startObserving() {
@@ -317,14 +305,6 @@
                 Context.VR_SERVICE));
     }
 
-    public void addStateChangedCallback(BrightnessStateChangeCallback cb) {
-        mChangeCallbacks.add(cb);
-    }
-
-    public boolean removeStateChangedCallback(BrightnessStateChangeCallback cb) {
-        return mChangeCallbacks.remove(cb);
-    }
-
     public void registerCallbacks() {
         mBackgroundHandler.post(mStartListeningRunnable);
     }
@@ -375,10 +355,6 @@
                     }
                 });
         }
-
-        for (BrightnessStateChangeCallback cb : mChangeCallbacks) {
-            cb.onBrightnessLevelChanged();
-        }
     }
 
     public void checkRestrictionAndSetEnabled() {
@@ -435,8 +411,12 @@
     }
 
     private void animateSliderTo(int target) {
-        if (!mControlValueInitialized) {
+        if (!mControlValueInitialized || !mControl.isVisible()) {
             // Don't animate the first value since its default state isn't meaningful to users.
+            // We also don't want to animate slider if it's not visible - especially important when
+            // two sliders are active at the same time in split shade (one in QS and one in QQS),
+            // as this negatively affects transition between them and they share mirror slider -
+            // animating it from two different sources causes janky motion
             mControl.setValue(target);
             mControlValueInitialized = true;
         }
@@ -455,13 +435,6 @@
         mSliderAnimator.start();
     }
 
-    private void notifyCallbacks() {
-        final int size = mChangeCallbacks.size();
-        for (int i = 0; i < size; i++) {
-            mChangeCallbacks.get(i).onBrightnessLevelChanged();
-        }
-    }
-
     /** Factory for creating a {@link BrightnessController}. */
     public static class Factory {
         private final Context mContext;
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
index 8fc831a..c9c1a9b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessDialog.java
@@ -41,14 +41,14 @@
 public class BrightnessDialog extends Activity {
 
     private BrightnessController mBrightnessController;
-    private final BrightnessSlider.Factory mToggleSliderFactory;
+    private final BrightnessSliderController.Factory mToggleSliderFactory;
     private final BroadcastDispatcher mBroadcastDispatcher;
     private final Handler mBackgroundHandler;
 
     @Inject
     public BrightnessDialog(
             BroadcastDispatcher broadcastDispatcher,
-            BrightnessSlider.Factory factory,
+            BrightnessSliderController.Factory factory,
             @Background Handler bgHandler) {
         mBroadcastDispatcher = broadcastDispatcher;
         mToggleSliderFactory = factory;
@@ -77,7 +77,7 @@
         // The brightness mirror container is INVISIBLE by default.
         frame.setVisibility(View.VISIBLE);
 
-        BrightnessSlider controller = mToggleSliderFactory.create(this, frame);
+        BrightnessSliderController controller = mToggleSliderFactory.create(this, frame);
         controller.init();
         frame.addView(controller.getRootView(), MATCH_PARENT, WRAP_CONTENT);
 
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
similarity index 89%
rename from packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
rename to packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
index b0e320a..6c8190a 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderController.java
@@ -44,7 +44,8 @@
  *
  * @see BrightnessMirrorController
  */
-public class BrightnessSlider extends ViewController<BrightnessSliderView> implements ToggleSlider {
+public class BrightnessSliderController extends ViewController<BrightnessSliderView> implements
+        ToggleSlider {
 
     private Listener mListener;
     private ToggleSlider mMirror;
@@ -69,7 +70,7 @@
         }
     };
 
-    BrightnessSlider(
+    BrightnessSliderController(
             BrightnessSliderView brightnessSliderView,
             FalsingManager falsingManager) {
         super(brightnessSliderView);
@@ -184,6 +185,15 @@
         mView.setVisibility(View.VISIBLE);
     }
 
+    @Override
+    public boolean isVisible() {
+        // this should be called rarely - once or twice per slider's value change, but not for
+        // every value change when user slides finger - only the final one.
+        // If view is not visible this call is quick (around 50 µs) as it sees parent is not visible
+        // otherwise it's slightly longer (70 µs) because there are more checks to be done
+        return mView.isVisibleToUser();
+    }
+
     private final SeekBar.OnSeekBarChangeListener mSeekListener =
             new SeekBar.OnSeekBarChangeListener() {
         @Override
@@ -222,7 +232,7 @@
     };
 
     /**
-     * Creates a {@link BrightnessSlider} with its associated view.
+     * Creates a {@link BrightnessSliderController} with its associated view.
      */
     public static class Factory {
 
@@ -240,11 +250,11 @@
          * @param viewRoot the {@link ViewGroup} that will contain the hierarchy. The inflated
          *                 hierarchy will not be attached
          */
-        public BrightnessSlider create(Context context, @Nullable ViewGroup viewRoot) {
+        public BrightnessSliderController create(Context context, @Nullable ViewGroup viewRoot) {
             int layout = getLayout();
             BrightnessSliderView root = (BrightnessSliderView) LayoutInflater.from(context)
                     .inflate(layout, viewRoot, false);
-            return new BrightnessSlider(root, mFalsingManager);
+            return new BrightnessSliderController(root, mFalsingManager);
         }
 
         /** Get the layout to inflate based on what slider to use */
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
index 15aa2b7..0e037ad 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/BrightnessSliderView.java
@@ -60,6 +60,7 @@
     @Override
     protected void onFinishInflate() {
         super.onFinishInflate();
+        setLayerType(LAYER_TYPE_HARDWARE, null);
 
         mSlider = requireViewById(R.id.slider);
         mSlider.setAccessibilityLabel(getContentDescription().toString());
diff --git a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
index 5de22d4..648e33b 100644
--- a/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
+++ b/packages/SystemUI/src/com/android/systemui/settings/brightness/ToggleSlider.java
@@ -38,4 +38,5 @@
 
     void showView();
     void hideView();
+    boolean isVisible();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index db7d5c1..856052e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -19,8 +19,8 @@
 import static android.app.admin.DevicePolicyManager.ACTION_DEVICE_POLICY_MANAGER_STATE_CHANGED;
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
 
 import android.app.ActivityManager;
 import android.app.KeyguardManager;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
index 0b93fff..51a66aa 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShelf.java
@@ -30,6 +30,7 @@
 import android.view.animation.PathInterpolator;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
@@ -114,7 +115,7 @@
 
     private void initDimens() {
         Resources res = getResources();
-        mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         mPaddingBetweenElements = res.getDimensionPixelSize(R.dimen.notification_divider_height);
 
         ViewGroup.LayoutParams layoutParams = getLayoutParams();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index 6da981b..cbb3aba 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -28,7 +28,6 @@
 import android.animation.ObjectAnimator;
 import android.animation.ValueAnimator;
 import android.os.SystemProperties;
-import android.os.Trace;
 import android.text.format.DateFormat;
 import android.util.FloatProperty;
 import android.util.Log;
@@ -182,7 +181,6 @@
         }
 
         synchronized (mListeners) {
-            Trace.beginSection(TAG + "#setState(" + StatusBarState.toShortString(state) + ")");
             String tag = getClass().getSimpleName() + "#setState(" + state + ")";
             DejankUtils.startDetectingBlockingIpcs(tag);
             for (RankedListener rl : new ArrayList<>(mListeners)) {
@@ -200,7 +198,6 @@
                 rl.mListener.onStatePostChange();
             }
             DejankUtils.stopDetectingBlockingIpcs(tag);
-            Trace.endSection();
         }
 
         return true;
@@ -265,14 +262,12 @@
         mIsDozing = isDozing;
 
         synchronized (mListeners) {
-            Trace.beginSection(TAG + "#setDozing(" + isDozing + ")");
             String tag = getClass().getSimpleName() + "#setIsDozing";
             DejankUtils.startDetectingBlockingIpcs(tag);
             for (RankedListener rl : new ArrayList<>(mListeners)) {
                 rl.mListener.onDozingChanged(isDozing);
             }
             DejankUtils.stopDetectingBlockingIpcs(tag);
-            Trace.endSection();
         }
 
         return true;
@@ -338,14 +333,12 @@
         mDozeAmount = dozeAmount;
         float interpolatedAmount = mDozeInterpolator.getInterpolation(dozeAmount);
         synchronized (mListeners) {
-            Trace.beginSection(TAG + "#setDozeAmount");
             String tag = getClass().getSimpleName() + "#setDozeAmount";
             DejankUtils.startDetectingBlockingIpcs(tag);
             for (RankedListener rl : new ArrayList<>(mListeners)) {
                 rl.mListener.onDozeAmountChanged(mDozeAmount, interpolatedAmount);
             }
             DejankUtils.stopDetectingBlockingIpcs(tag);
-            Trace.endSection();
         }
     }
 
@@ -476,13 +469,11 @@
     public void setPulsing(boolean pulsing) {
         if (mPulsing != pulsing) {
             mPulsing = pulsing;
-            Trace.beginSection(TAG + "#setPulsing(" + pulsing + ")");
             synchronized (mListeners) {
                 for (RankedListener rl : new ArrayList<>(mListeners)) {
                     rl.mListener.onPulsingChanged(pulsing);
                 }
             }
-            Trace.endSection();
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
index d9b0ee7..daae43f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/connectivity/NetworkControllerImpl.java
@@ -332,8 +332,7 @@
         deviceProvisionedController.addCallback(new DeviceProvisionedListener() {
             @Override
             public void onUserSetupChanged() {
-                setUserSetupComplete(deviceProvisionedController.isUserSetup(
-                        deviceProvisionedController.getCurrentUser()));
+                setUserSetupComplete(deviceProvisionedController.isCurrentUserSetup());
             }
         });
 
@@ -812,7 +811,8 @@
                 break;
             case Settings.Panel.ACTION_INTERNET_CONNECTIVITY:
                 mMainHandler.post(() -> mInternetDialogFactory.create(true,
-                        mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi()));
+                        mAccessPoints.canConfigMobileData(), mAccessPoints.canConfigWifi(),
+                        null /* view */));
                 break;
             default:
                 int subId = intent.getIntExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index bacb85a..4e5bc8e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -188,13 +188,23 @@
 
         val ssView = plugin.getView(parent)
         ssView.registerDataProvider(plugin)
+
         ssView.setIntentStarter(object : BcSmartspaceDataPlugin.IntentStarter {
-            override fun startIntent(v: View?, i: Intent?) {
-                activityStarter.startActivity(i, true /* dismissShade */)
+            override fun startIntent(view: View, intent: Intent, showOnLockscreen: Boolean) {
+                activityStarter.startActivity(
+                    intent,
+                    true, /* dismissShade */
+                    null, /* launch animator - looks bad with the transparent smartspace bg */
+                    showOnLockscreen
+                )
             }
 
-            override fun startPendingIntent(pi: PendingIntent?) {
-                activityStarter.startPendingIntentDismissingKeyguard(pi)
+            override fun startPendingIntent(pi: PendingIntent, showOnLockscreen: Boolean) {
+                if (showOnLockscreen) {
+                    pi.send()
+                } else {
+                    activityStarter.startPendingIntentDismissingKeyguard(pi)
+                }
             }
         })
         ssView.setFalsingManager(falsingManager)
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
index fd0476b..37eacad 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ListEntry.java
@@ -36,7 +36,7 @@
     private final ListAttachState mPreviousAttachState = ListAttachState.create();
     private final ListAttachState mAttachState = ListAttachState.create();
 
-    ListEntry(String key, long creationTime) {
+    protected ListEntry(String key, long creationTime) {
         mKey = key;
         mCreationTime = creationTime;
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
index 277b4ac..dfdc548 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotifCollection.java
@@ -523,7 +523,9 @@
         }
     }
 
-    private void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry) {
+    private void onEndLifetimeExtension(
+            @NonNull NotifLifetimeExtender extender,
+            @NonNull NotificationEntry entry) {
         Assert.isMainThread();
         if (!mAttached) {
             return;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
index 94ee868..66d019e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/NotificationEntry.java
@@ -31,7 +31,7 @@
 import static android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_STATUS_BAR;
 
 import static com.android.systemui.statusbar.notification.collection.NotifCollection.REASON_NOT_CANCELED;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_ALERTING;
 
 import static java.util.Objects.requireNonNull;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
index e26fa04..3730524 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilder.java
@@ -52,6 +52,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifStabilityManager;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable;
 import com.android.systemui.statusbar.notification.collection.notifcollection.CollectionReadyForBuildListener;
+import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
 import com.android.systemui.util.Assert;
 import com.android.systemui.util.time.SystemClock;
 
@@ -78,6 +79,8 @@
     private final SystemClock mSystemClock;
     private final ShadeListBuilderLogger mLogger;
     private final NotificationInteractionTracker mInteractionTracker;
+    // used exclusivly by ShadeListBuilder#notifySectionEntriesUpdated
+    private final ArrayList<ListEntry> mTempSectionMembers = new ArrayList<>();
 
     private List<ListEntry> mNotifList = new ArrayList<>();
     private List<ListEntry> mNewNotifList = new ArrayList<>();
@@ -356,7 +359,7 @@
         // section by our list of custom comparators
         dispatchOnBeforeSort(mReadOnlyNotifList);
         mPipelineState.incrementTo(STATE_SORTING);
-        sortList();
+        sortListAndNotifySections();
 
         // Step 7: Lock in our group structure and log anything that's changed since the last run
         mPipelineState.incrementTo(STATE_FINALIZING);
@@ -382,6 +385,22 @@
         mIterationCount++;
     }
 
+    private void notifySectionEntriesUpdated() {
+        NotifSection currentSection = null;
+        mTempSectionMembers.clear();
+        for (int i = 0; i < mNotifList.size(); i++) {
+            ListEntry currentEntry = mNotifList.get(i);
+            if (currentSection != currentEntry.getSection()) {
+                if (currentSection != null) {
+                    currentSection.getSectioner().onEntriesUpdated(mTempSectionMembers);
+                    mTempSectionMembers.clear();
+                }
+                currentSection = currentEntry.getSection();
+            }
+            mTempSectionMembers.add(currentEntry);
+        }
+    }
+
     /**
      * Points mNotifList to the list stored in mNewNotifList.
      * Reuses the (emptied) mNotifList as mNewNotifList.
@@ -713,14 +732,14 @@
         }
     }
 
-    private void sortList() {
+    private void sortListAndNotifySections() {
         // Assign sections to top-level elements and sort their children
         for (ListEntry entry : mNotifList) {
             NotifSection section = applySections(entry);
             if (entry instanceof GroupEntry) {
                 GroupEntry parent = (GroupEntry) entry;
                 for (NotificationEntry child : parent.getChildren()) {
-                    child.getAttachState().setSection(section);
+                    setEntrySection(child, section);
                 }
                 parent.sortChildren(sChildComparator);
             }
@@ -728,6 +747,9 @@
 
         // Finally, sort all top-level elements
         mNotifList.sort(mTopLevelComparator);
+
+        // notify sections since the list is sorted now
+        notifySectionEntriesUpdated();
     }
 
     private void freeEmptyGroups() {
@@ -936,11 +958,18 @@
             }
         }
 
-        entry.getAttachState().setSection(finalSection);
-
+        setEntrySection(entry, finalSection);
         return finalSection;
     }
 
+    private void setEntrySection(ListEntry entry, NotifSection finalSection) {
+        entry.getAttachState().setSection(finalSection);
+        NotificationEntry representativeEntry = entry.getRepresentativeEntry();
+        if (representativeEntry != null && finalSection != null) {
+            representativeEntry.setBucket(finalSection.getBucket());
+        }
+    }
+
     @NonNull
     private NotifSection findSection(ListEntry entry) {
         for (int i = 0; i < mNotifSections.size(); i++) {
@@ -1019,13 +1048,13 @@
         void onRenderList(@NonNull List<ListEntry> entries);
     }
 
-    private static final NotifSectioner DEFAULT_SECTIONER =
-            new NotifSectioner("UnknownSection") {
-                @Override
-                public boolean isInSection(ListEntry entry) {
-                    return true;
-                }
-            };
+    private static final NotifSectioner DEFAULT_SECTIONER = new NotifSectioner("UnknownSection",
+            NotificationPriorityBucketKt.BUCKET_UNKNOWN) {
+        @Override
+        public boolean isInSection(ListEntry entry) {
+            return true;
+        }
+    };
 
     private static final int MIN_CHILDREN_FOR_GROUP = 2;
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
index 3a87f68..301b185 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/AppOpsCoordinator.java
@@ -30,6 +30,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifFilter;
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
+import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
 import javax.inject.Inject;
@@ -102,7 +103,8 @@
     /**
      * Puts foreground service notifications into its own section.
      */
-    private final NotifSectioner mNotifSectioner = new NotifSectioner("ForegroundService") {
+    private final NotifSectioner mNotifSectioner = new NotifSectioner("ForegroundService",
+            NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE) {
         @Override
         public boolean isInSection(ListEntry entry) {
             NotificationEntry notificationEntry = entry.getRepresentativeEntry();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
index f0eb084..c385836 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ConversationCoordinator.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.statusbar.notification.dagger.PeopleHeader
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier
 import com.android.systemui.statusbar.notification.people.PeopleNotificationIdentifier.Companion.TYPE_NON_PERSON
+import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
 import javax.inject.Inject
 
 /**
@@ -45,10 +46,12 @@
         }
     }
 
-    val sectioner = object : NotifSectioner("People") {
+    val sectioner = object : NotifSectioner("People", BUCKET_PEOPLE) {
         override fun isInSection(entry: ListEntry): Boolean =
                 isConversation(entry.representativeEntry!!)
-        override fun getHeaderNodeController() = peopleHeaderController
+        override fun getHeaderNodeController() =
+                // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and peopleHeaderController
+                if (RankingCoordinator.SHOW_ALL_SECTIONS) peopleHeaderController else null
     }
 
     override fun attach(pipeline: NotifPipeline) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
new file mode 100644
index 0000000..8948969
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinator.kt
@@ -0,0 +1,126 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.util.ArraySet
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+import com.android.systemui.statusbar.notification.row.NotificationGuts
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewListener
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import javax.inject.Inject
+
+private const val TAG = "GutsCoordinator"
+
+/**
+ * Coordinates the guts displayed by the [NotificationGutsManager] with the pipeline.
+ * Specifically, this just adds the lifetime extension necessary to keep guts from disappearing.
+ */
+@SysUISingleton
+class GutsCoordinator @Inject constructor(
+    private val notifGutsViewManager: NotifGutsViewManager,
+    private val logger: GutsCoordinatorLogger,
+    dumpManager: DumpManager
+) : Coordinator, Dumpable {
+
+    /** Keys of any Notifications for which we've been told the guts are open  */
+    private val notifsWithOpenGuts = ArraySet<String>()
+
+    /** Keys of any Notifications we've extended the lifetime for, based on guts  */
+    private val notifsExtendingLifetime = ArraySet<String>()
+
+    /** Callback for ending lifetime extension  */
+    private var onEndLifetimeExtensionCallback: OnEndLifetimeExtensionCallback? = null
+
+    init {
+        dumpManager.registerDumpable(TAG, this)
+    }
+
+    override fun attach(pipeline: NotifPipeline) {
+        notifGutsViewManager.setGutsListener(mGutsListener)
+        pipeline.addNotificationLifetimeExtender(mLifetimeExtender)
+    }
+
+    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<String>) {
+        pw.println("  notifsWithOpenGuts: ${notifsWithOpenGuts.size}")
+        for (key in notifsWithOpenGuts) {
+            pw.println("   * $key")
+        }
+        pw.println("  notifsExtendingLifetime: ${notifsExtendingLifetime.size}")
+        for (key in notifsExtendingLifetime) {
+            pw.println("   * $key")
+        }
+        pw.println("  onEndLifetimeExtensionCallback: $onEndLifetimeExtensionCallback")
+    }
+
+    private val mLifetimeExtender: NotifLifetimeExtender = object : NotifLifetimeExtender {
+        override fun getName(): String {
+            return TAG
+        }
+
+        override fun setCallback(callback: OnEndLifetimeExtensionCallback) {
+            onEndLifetimeExtensionCallback = callback
+        }
+
+        override fun shouldExtendLifetime(entry: NotificationEntry, reason: Int): Boolean {
+            val isShowingGuts = isCurrentlyShowingGuts(entry)
+            if (isShowingGuts) {
+                notifsExtendingLifetime.add(entry.key)
+            }
+            return isShowingGuts
+        }
+
+        override fun cancelLifetimeExtension(entry: NotificationEntry) {
+            notifsExtendingLifetime.remove(entry.key)
+        }
+    }
+
+    private val mGutsListener: NotifGutsViewListener = object : NotifGutsViewListener {
+        override fun onGutsOpen(entry: NotificationEntry, guts: NotificationGuts) {
+            logger.logGutsOpened(entry.key, guts)
+            if (guts.isLeavebehind) {
+                // leave-behind guts should not extend the lifetime of the notification
+                closeGutsAndEndLifetimeExtension(entry)
+            } else {
+                notifsWithOpenGuts.add(entry.key)
+            }
+        }
+
+        override fun onGutsClose(entry: NotificationEntry) {
+            logger.logGutsClosed(entry.key)
+            closeGutsAndEndLifetimeExtension(entry)
+        }
+    }
+
+    private fun isCurrentlyShowingGuts(entry: ListEntry) =
+            notifsWithOpenGuts.contains(entry.key)
+
+    private fun closeGutsAndEndLifetimeExtension(entry: NotificationEntry) {
+        notifsWithOpenGuts.remove(entry.key)
+        if (notifsExtendingLifetime.remove(entry.key)) {
+            onEndLifetimeExtensionCallback?.onEndLifetimeExtension(mLifetimeExtender, entry)
+        }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
new file mode 100644
index 0000000..e8f352f
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorLogger.kt
@@ -0,0 +1,32 @@
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import com.android.systemui.statusbar.notification.row.NotificationGuts
+import javax.inject.Inject
+
+private const val TAG = "GutsCoordinator"
+
+class GutsCoordinatorLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+
+    fun logGutsOpened(key: String, guts: NotificationGuts) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = key
+            str2 = guts.gutsContent::class.simpleName
+            bool1 = guts.isLeavebehind
+        }, {
+            "Guts of type $str2 (leave behind: $bool1) opened for class $str1"
+        })
+    }
+
+    fun logGutsClosed(key: String) {
+        buffer.log(TAG, LogLevel.DEBUG, {
+            str1 = key
+        }, {
+            "Guts closed for class $str1"
+        })
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
index 6e98c27..8c8a8a9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/HeadsUpCoordinator.java
@@ -19,7 +19,8 @@
 import static com.android.systemui.statusbar.NotificationRemoteInputManager.FORCE_REMOTE_INPUT_HISTORY;
 import static com.android.systemui.statusbar.notification.interruption.HeadsUpController.alertAgain;
 
-import android.annotation.Nullable;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
 
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.statusbar.NotificationRemoteInputManager;
@@ -34,6 +35,7 @@
 import com.android.systemui.statusbar.notification.dagger.IncomingHeader;
 import com.android.systemui.statusbar.notification.interruption.HeadsUpViewBinder;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
+import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
 import com.android.systemui.statusbar.policy.HeadsUpManager;
 import com.android.systemui.statusbar.policy.OnHeadsUpChangedListener;
 
@@ -163,17 +165,17 @@
 
     private final NotifLifetimeExtender mLifetimeExtender = new NotifLifetimeExtender() {
         @Override
-        public String getName() {
+        public @NonNull String getName() {
             return TAG;
         }
 
         @Override
-        public void setCallback(OnEndLifetimeExtensionCallback callback) {
+        public void setCallback(@NonNull OnEndLifetimeExtensionCallback callback) {
             mEndLifetimeExtension = callback;
         }
 
         @Override
-        public boolean shouldExtendLifetime(NotificationEntry entry, int reason) {
+        public boolean shouldExtendLifetime(@NonNull NotificationEntry entry, int reason) {
             boolean isShowingHun = isCurrentlyShowingHun(entry);
             if (isShowingHun) {
                 mNotifExtendingLifetime = entry;
@@ -182,7 +184,7 @@
         }
 
         @Override
-        public void cancelLifetimeExtension(NotificationEntry entry) {
+        public void cancelLifetimeExtension(@NonNull NotificationEntry entry) {
             if (Objects.equals(mNotifExtendingLifetime, entry)) {
                 mNotifExtendingLifetime = null;
             }
@@ -196,7 +198,8 @@
         }
     };
 
-    private final NotifSectioner mNotifSectioner = new NotifSectioner("HeadsUp") {
+    private final NotifSectioner mNotifSectioner = new NotifSectioner("HeadsUp",
+            NotificationPriorityBucketKt.BUCKET_HEADS_UP) {
         @Override
         public boolean isInSection(ListEntry entry) {
             return isCurrentlyShowingHun(entry);
@@ -205,7 +208,11 @@
         @Nullable
         @Override
         public NodeController getHeaderNodeController() {
-            return mIncomingHeaderController;
+            // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mIncomingHeaderController
+            if (RankingCoordinator.SHOW_ALL_SECTIONS) {
+                return mIncomingHeaderController;
+            }
+            return null;
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
index 25b2019..9305900 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/NotifCoordinators.java
@@ -57,10 +57,13 @@
             DeviceProvisionedCoordinator deviceProvisionedCoordinator,
             BubbleCoordinator bubbleCoordinator,
             HeadsUpCoordinator headsUpCoordinator,
+            GutsCoordinator gutsCoordinator,
             ConversationCoordinator conversationCoordinator,
             PreparationCoordinator preparationCoordinator,
             MediaCoordinator mediaCoordinator,
+            ShadeEventCoordinator shadeEventCoordinator,
             SmartspaceDedupingCoordinator smartspaceDedupingCoordinator,
+            ViewConfigCoordinator viewConfigCoordinator,
             VisualStabilityCoordinator visualStabilityCoordinator) {
         dumpManager.registerDumpable(TAG, this);
 
@@ -73,6 +76,8 @@
         mCoordinators.add(bubbleCoordinator);
         mCoordinators.add(conversationCoordinator);
         mCoordinators.add(mediaCoordinator);
+        mCoordinators.add(shadeEventCoordinator);
+        mCoordinators.add(viewConfigCoordinator);
         mCoordinators.add(visualStabilityCoordinator);
 
         if (featureFlags.isSmartspaceDedupingEnabled()) {
@@ -81,6 +86,7 @@
 
         if (featureFlags.isNewNotifPipelineRenderingEnabled()) {
             mCoordinators.add(headsUpCoordinator);
+            mCoordinators.add(gutsCoordinator);
             mCoordinators.add(preparationCoordinator);
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
index 6da4d8b..1a6a63a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinator.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.notification.collection.coordinator;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 
 import com.android.systemui.dagger.SysUISingleton;
@@ -27,8 +28,12 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
 import com.android.systemui.statusbar.notification.collection.render.NodeController;
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 import com.android.systemui.statusbar.notification.dagger.AlertingHeader;
 import com.android.systemui.statusbar.notification.dagger.SilentHeader;
+import com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt;
+
+import java.util.List;
 
 import javax.inject.Inject;
 
@@ -41,9 +46,11 @@
  */
 @SysUISingleton
 public class RankingCoordinator implements Coordinator {
+    public static final boolean SHOW_ALL_SECTIONS = false;
     private final StatusBarStateController mStatusBarStateController;
     private final HighPriorityProvider mHighPriorityProvider;
-    private final NodeController mSilentHeaderController;
+    private final NodeController mSilentNodeController;
+    private final SectionHeaderController mSilentHeaderController;
     private final NodeController mAlertingHeaderController;
 
     @Inject
@@ -51,10 +58,12 @@
             StatusBarStateController statusBarStateController,
             HighPriorityProvider highPriorityProvider,
             @AlertingHeader NodeController alertingHeaderController,
-            @SilentHeader NodeController silentHeaderController) {
+            @SilentHeader SectionHeaderController silentHeaderController,
+            @SilentHeader NodeController silentNodeController) {
         mStatusBarStateController = statusBarStateController;
         mHighPriorityProvider = highPriorityProvider;
         mAlertingHeaderController = alertingHeaderController;
+        mSilentNodeController = silentNodeController;
         mSilentHeaderController = silentHeaderController;
     }
 
@@ -74,7 +83,8 @@
         return mSilentNotifSectioner;
     }
 
-    private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting") {
+    private final NotifSectioner mAlertingNotifSectioner = new NotifSectioner("Alerting",
+            NotificationPriorityBucketKt.BUCKET_ALERTING) {
         @Override
         public boolean isInSection(ListEntry entry) {
             return mHighPriorityProvider.isHighPriority(entry);
@@ -83,11 +93,16 @@
         @Nullable
         @Override
         public NodeController getHeaderNodeController() {
-            return mAlertingHeaderController;
+            // TODO: remove SHOW_ALL_SECTIONS, this redundant method, and mAlertingHeaderController
+            if (SHOW_ALL_SECTIONS) {
+                return mAlertingHeaderController;
+            }
+            return null;
         }
     };
 
-    private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent") {
+    private final NotifSectioner mSilentNotifSectioner = new NotifSectioner("Silent",
+            NotificationPriorityBucketKt.BUCKET_SILENT) {
         @Override
         public boolean isInSection(ListEntry entry) {
             return !mHighPriorityProvider.isHighPriority(entry);
@@ -96,7 +111,19 @@
         @Nullable
         @Override
         public NodeController getHeaderNodeController() {
-            return mSilentHeaderController;
+            return mSilentNodeController;
+        }
+
+        @Nullable
+        @Override
+        public void onEntriesUpdated(@NonNull List<ListEntry> entries) {
+            for (int i = 0; i < entries.size(); i++) {
+                if (entries.get(i).getRepresentativeEntry().getSbn().isClearable()) {
+                    mSilentHeaderController.setClearSectionEnabled(true);
+                    return;
+                }
+            }
+            mSilentHeaderController.setClearSectionEnabled(false);
         }
     };
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
new file mode 100644
index 0000000..f9648a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinator.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.service.notification.NotificationListenerService
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.statusbar.notification.collection.ListEntry
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource
+import javax.inject.Inject
+
+/**
+ * A coordinator which provides callbacks to a view surfaces for various events relevant to the
+ * shade, such as when the user removes a notification, or when the shade is emptied.
+ */
+@SysUISingleton
+class ShadeEventCoordinator @Inject internal constructor(
+    private val mLogger: ShadeEventCoordinatorLogger
+) : Coordinator, NotifShadeEventSource {
+    private var mNotifRemovedByUserCallback: Runnable? = null
+    private var mShadeEmptiedCallback: Runnable? = null
+    private var mEntryRemoved = false
+    private var mEntryRemovedByUser = false
+
+    override fun attach(pipeline: NotifPipeline) {
+        pipeline.addCollectionListener(mNotifCollectionListener)
+        pipeline.addOnBeforeRenderListListener(this::onBeforeRenderList)
+    }
+
+    private val mNotifCollectionListener = object : NotifCollectionListener {
+        override fun onEntryRemoved(entry: NotificationEntry, reason: Int) {
+            mEntryRemoved = true
+            mEntryRemovedByUser =
+                    reason == NotificationListenerService.REASON_CLICK ||
+                    reason == NotificationListenerService.REASON_CANCEL_ALL ||
+                    reason == NotificationListenerService.REASON_CANCEL
+        }
+    }
+
+    override fun setNotifRemovedByUserCallback(callback: Runnable) {
+        check(mNotifRemovedByUserCallback == null) { "mNotifRemovedByUserCallback already set" }
+        mNotifRemovedByUserCallback = callback
+    }
+
+    override fun setShadeEmptiedCallback(callback: Runnable) {
+        check(mShadeEmptiedCallback == null) { "mShadeEmptiedCallback already set" }
+        mShadeEmptiedCallback = callback
+    }
+
+    private fun onBeforeRenderList(entries: List<ListEntry>) {
+        if (mEntryRemoved && entries.isEmpty()) {
+            mLogger.logShadeEmptied()
+            mShadeEmptiedCallback?.run()
+        }
+        if (mEntryRemoved && mEntryRemovedByUser) {
+            mLogger.logNotifRemovedByUser()
+            mNotifRemovedByUserCallback?.run()
+        }
+        mEntryRemoved = false
+        mEntryRemovedByUser = false
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
new file mode 100644
index 0000000..c687e1b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorLogger.kt
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import com.android.systemui.log.LogBuffer
+import com.android.systemui.log.LogLevel
+import com.android.systemui.log.dagger.NotificationLog
+import javax.inject.Inject
+
+private const val TAG = "ShadeEventCoordinator"
+
+/** Logger for the [ShadeEventCoordinator] */
+class ShadeEventCoordinatorLogger @Inject constructor(
+    @NotificationLog private val buffer: LogBuffer
+) {
+
+    fun logShadeEmptied() {
+        buffer.log(TAG, LogLevel.DEBUG, { }, { "Shade emptied" })
+    }
+
+    fun logNotifRemovedByUser() {
+        buffer.log(TAG, LogLevel.DEBUG, { }, { "Notification removed by user" })
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
new file mode 100644
index 0000000..df1132b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/coordinator/ViewConfigCoordinator.kt
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import com.android.internal.widget.MessagingGroup
+import com.android.internal.widget.MessagingMessage
+import com.android.keyguard.KeyguardUpdateMonitor
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.statusbar.NotificationLockscreenUserManager.UserChangedListener
+import com.android.systemui.statusbar.NotificationLockscreenUserManagerImpl
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.row.NotificationGutsManager
+import com.android.systemui.statusbar.policy.ConfigurationController
+import javax.inject.Inject
+
+/**
+ * A coordinator which ensures that notifications within the new pipeline are correctly inflated
+ * for the current uiMode and screen properties; additionally deferring those changes when a user
+ * change is in progress until that process has completed.
+ */
+@SysUISingleton
+class ViewConfigCoordinator @Inject internal constructor(
+    configurationController: ConfigurationController,
+    lockscreenUserManager: NotificationLockscreenUserManagerImpl,
+    featureFlags: FeatureFlags,
+    private val mGutsManager: NotificationGutsManager,
+    private val mKeyguardUpdateMonitor: KeyguardUpdateMonitor
+) : Coordinator, UserChangedListener, ConfigurationController.ConfigurationListener {
+
+    private var mReinflateNotificationsOnUserSwitched = false
+    private var mDispatchUiModeChangeOnUserSwitched = false
+    private var mPipeline: NotifPipeline? = null
+
+    init {
+        if (featureFlags.isNewNotifPipelineRenderingEnabled) {
+            lockscreenUserManager.addUserChangedListener(this)
+            configurationController.addCallback(this)
+        }
+    }
+
+    override fun attach(pipeline: NotifPipeline) {
+        mPipeline = pipeline
+    }
+
+    override fun onDensityOrFontScaleChanged() {
+        MessagingMessage.dropCache()
+        MessagingGroup.dropCache()
+        if (!mKeyguardUpdateMonitor.isSwitchingUser) {
+            updateNotificationsOnDensityOrFontScaleChanged()
+        } else {
+            mReinflateNotificationsOnUserSwitched = true
+        }
+    }
+
+    override fun onUiModeChanged() {
+        if (!mKeyguardUpdateMonitor.isSwitchingUser) {
+            updateNotificationsOnUiModeChanged()
+        } else {
+            mDispatchUiModeChangeOnUserSwitched = true
+        }
+    }
+
+    override fun onThemeChanged() {
+        onDensityOrFontScaleChanged()
+    }
+
+    override fun onUserChanged(userId: Int) {
+        if (mReinflateNotificationsOnUserSwitched) {
+            updateNotificationsOnDensityOrFontScaleChanged()
+            mReinflateNotificationsOnUserSwitched = false
+        }
+        if (mDispatchUiModeChangeOnUserSwitched) {
+            updateNotificationsOnUiModeChanged()
+            mDispatchUiModeChangeOnUserSwitched = false
+        }
+    }
+
+    private fun updateNotificationsOnUiModeChanged() {
+        mPipeline?.allNotifs?.forEach { entry ->
+            val row = entry.row
+            row?.onUiModeChanged()
+        }
+    }
+
+    private fun updateNotificationsOnDensityOrFontScaleChanged() {
+        mPipeline?.allNotifs?.forEach { entry ->
+            entry.onDensityOrFontScaleChanged()
+            val exposedGuts = entry.areGutsExposed()
+            if (exposedGuts) {
+                mGutsManager.onDensityOrFontScaleChanged(entry)
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationPresenterExtensions.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationPresenterExtensions.java
new file mode 100644
index 0000000..4ee08ed
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/legacy/LegacyNotificationPresenterExtensions.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.legacy;
+
+import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
+
+import android.service.notification.StatusBarNotification;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+
+import com.android.internal.statusbar.NotificationVisibility;
+import com.android.systemui.statusbar.notification.NotificationEntryListener;
+import com.android.systemui.statusbar.notification.NotificationEntryManager;
+import com.android.systemui.statusbar.notification.collection.NotificationEntry;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
+
+import org.jetbrains.annotations.NotNull;
+
+import javax.inject.Inject;
+
+/**
+ * This is some logic extracted from the
+ * {@link com.android.systemui.statusbar.phone.StatusBarNotificationPresenter}
+ * into a class that implements a new-pipeline interface so that the new pipeline can implement it
+ * correctly.
+ *
+ * Specifically, this is the logic which updates notifications when uiMode and screen properties
+ * change, and which closes the shade when the last notification disappears.
+ */
+public class LegacyNotificationPresenterExtensions implements NotifShadeEventSource {
+    private static final String TAG = "LegacyNotifPresenter";
+    private final NotificationEntryManager mEntryManager;
+    private boolean mEntryListenerAdded;
+    private Runnable mShadeEmptiedCallback;
+    private Runnable mNotifRemovedByUserCallback;
+
+    @Inject
+    public LegacyNotificationPresenterExtensions(NotificationEntryManager entryManager) {
+        mEntryManager = entryManager;
+    }
+
+    private void ensureEntryListenerAdded() {
+        if (mEntryListenerAdded) return;
+        mEntryListenerAdded = true;
+        mEntryManager.addNotificationEntryListener(new NotificationEntryListener() {
+            @Override
+            public void onEntryRemoved(
+                    @NotNull NotificationEntry entry,
+                    NotificationVisibility visibility,
+                    boolean removedByUser,
+                    int reason) {
+                StatusBarNotification old = entry.getSbn();
+                if (SPEW) {
+                    Log.d(TAG, "removeNotification key=" + entry.getKey()
+                            + " old=" + old + " reason=" + reason);
+                }
+
+                if (old != null && !mEntryManager.hasActiveNotifications()) {
+                    if (mShadeEmptiedCallback != null) mShadeEmptiedCallback.run();
+                }
+                if (removedByUser) {
+                    if (mNotifRemovedByUserCallback != null) mNotifRemovedByUserCallback.run();
+                }
+            }
+        });
+    }
+
+    @Override
+    public void setNotifRemovedByUserCallback(@NonNull Runnable callback) {
+        if (mNotifRemovedByUserCallback != null) {
+            throw new IllegalStateException("mNotifRemovedByUserCallback already set");
+        }
+        mNotifRemovedByUserCallback = callback;
+        ensureEntryListenerAdded();
+    }
+
+    @Override
+    public void setShadeEmptiedCallback(@NonNull Runnable callback) {
+        if (mShadeEmptiedCallback != null) {
+            throw new IllegalStateException("mShadeEmptiedCallback already set");
+        }
+        mShadeEmptiedCallback = callback;
+        ensureEntryListenerAdded();
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
index c9fc992..6424e37 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/NotifSection.kt
@@ -18,14 +18,17 @@
 
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
 import com.android.systemui.statusbar.notification.collection.render.NodeController
+import com.android.systemui.statusbar.notification.stack.PriorityBucket
 
 data class NotifSection(
     val sectioner: NotifSectioner,
     val index: Int
 ) {
     val label: String
-        get() = "Section($index, \"${sectioner.name}\")"
+        get() = "Section($index, $bucket, \"${sectioner.name}\")"
 
     val headerController: NodeController?
         get() = sectioner.headerNodeController
+
+    @PriorityBucket val bucket: Int = sectioner.bucket
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
index c8982d3..ef9ee11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/listbuilder/pluggable/NotifSectioner.java
@@ -22,13 +22,28 @@
 import com.android.systemui.statusbar.notification.collection.ShadeListBuilder;
 import com.android.systemui.statusbar.notification.collection.render.NodeController;
 import com.android.systemui.statusbar.notification.collection.render.NodeSpec;
+import com.android.systemui.statusbar.notification.stack.PriorityBucket;
+
+import java.util.List;
 
 /**
- * Pluggable for participating in notif sectioning. See {@link ShadeListBuilder#setSections}.
+ * Pluggable for participating in notif sectioning. See {@link ShadeListBuilder#setSectioners}.
  */
 public abstract class NotifSectioner extends Pluggable<NotifSectioner> {
-    protected NotifSectioner(String name) {
+    @PriorityBucket
+    private final int mBucket;
+
+    protected NotifSectioner(String name, @PriorityBucket int bucket) {
         super(name);
+        mBucket = bucket;
+    }
+
+    /**
+     * @return the "bucket" value to apply to entries in this section
+     */
+    @PriorityBucket
+    public final int getBucket() {
+        return mBucket;
     }
 
     /**
@@ -46,4 +61,10 @@
     public @Nullable NodeController getHeaderNodeController() {
         return null;
     }
+
+    /**
+     * Notify of children of this section being updated
+     * @param entries of this section that are borrowed (must clone to store)
+     */
+    public void onEntriesUpdated(List<ListEntry> entries) {}
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
index f8fe067..2fe3bd6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/notifcollection/NotifLifetimeExtender.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.statusbar.notification.collection.notifcollection;
 
+import androidx.annotation.NonNull;
+
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifCollection.CancellationReason;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
@@ -26,14 +28,14 @@
  */
 public interface NotifLifetimeExtender {
     /** Name to associate with this extender (for the purposes of debugging) */
-    String getName();
+    @NonNull String getName();
 
     /**
      * Called on the extender immediately after it has been registered. The extender should hang on
      * to this callback and execute it whenever it no longer needs to extend the lifetime of a
      * notification.
      */
-    void setCallback(OnEndLifetimeExtensionCallback callback);
+    void setCallback(@NonNull OnEndLifetimeExtensionCallback callback);
 
     /**
      * Called by the NotifCollection whenever a notification has been retracted (by the app) or
@@ -43,7 +45,7 @@
      * called on all lifetime extenders even if earlier ones return true (in other words, multiple
      * lifetime extenders can be extending a notification at the same time).
      */
-    boolean shouldExtendLifetime(NotificationEntry entry, @CancellationReason int reason);
+    boolean shouldExtendLifetime(@NonNull NotificationEntry entry, @CancellationReason int reason);
 
     /**
      * Called by the NotifCollection to inform a lifetime extender that its extension of a notif
@@ -51,7 +53,7 @@
      * lifetime extension). The extender should clean up any references it has to the notif in
      * question.
      */
-    void cancelLifetimeExtension(NotificationEntry entry);
+    void cancelLifetimeExtension(@NonNull NotificationEntry entry);
 
     /** Callback for notifying the NotifCollection that a lifetime extension has expired.*/
     interface OnEndLifetimeExtensionCallback {
@@ -59,6 +61,8 @@
          * Stop extending the lifetime of `entry` with `extender` and then immediately re-evaluates
          * whether to continue lifetime extending this notification or to remove it.
          */
-        void onEndLifetimeExtension(NotifLifetimeExtender extender, NotificationEntry entry);
+        void onEndLifetimeExtension(
+                @NonNull NotifLifetimeExtender extender,
+                @NonNull NotificationEntry entry);
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt
new file mode 100644
index 0000000..129f6b1
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewListener.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.collection.render
+
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.row.NotificationGuts
+
+/**
+ * Interface for listening to guts open and close events.
+ */
+interface NotifGutsViewListener {
+    /** A notification's guts are being opened */
+    fun onGutsOpen(entry: NotificationEntry, guts: NotificationGuts)
+
+    /** A notification's guts are being closed */
+    fun onGutsClose(entry: NotificationEntry)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt
new file mode 100644
index 0000000..0260f89
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifGutsViewManager.kt
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.collection.render
+
+/** A type which provides open and close guts events to a single listener */
+interface NotifGutsViewManager {
+    /**
+     * @param listener the object that will listen to open and close guts events
+     */
+    fun setGutsListener(listener: NotifGutsViewListener?)
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
new file mode 100644
index 0000000..e24f6a0
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/NotifShadeEventSource.kt
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.collection.render
+
+/**
+ * This is an object which provides callbacks for certain important events related to the
+ * notification shade, such as notifications being removed by the user, or the shade becoming empty.
+ */
+interface NotifShadeEventSource {
+    /**
+     * Registers a callback to be invoked when the last notification has been removed from
+     * the shade for any reason
+     */
+    fun setShadeEmptiedCallback(callback: Runnable)
+
+    /**
+     * Registers a callback to be invoked when a notification has been removed from
+     * the shade by a user action
+     */
+    fun setNotifRemovedByUserCallback(callback: Runnable)
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
index 1311e3e..8c15647 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/collection/render/SectionHeaderController.kt
@@ -33,7 +33,8 @@
 interface SectionHeaderController {
     fun reinflateView(parent: ViewGroup)
     val headerView: SectionHeaderView?
-    fun setOnClearAllClickListener(listener: View.OnClickListener)
+    fun setClearSectionEnabled(enabled: Boolean)
+    fun setOnClearSectionClickListener(listener: View.OnClickListener)
 }
 
 @SectionHeaderScope
@@ -46,6 +47,7 @@
 ) : NodeController, SectionHeaderController {
 
     private var _view: SectionHeaderView? = null
+    private var clearAllButtonEnabled = false
     private var clearAllClickListener: View.OnClickListener? = null
     private val onHeaderClickListener = View.OnClickListener {
         activityStarter.startActivity(
@@ -76,12 +78,18 @@
             parent.addView(inflated, oldPos)
         }
         _view = inflated
+        _view?.setClearSectionButtonEnabled(clearAllButtonEnabled)
     }
 
     override val headerView: SectionHeaderView?
         get() = _view
 
-    override fun setOnClearAllClickListener(listener: View.OnClickListener) {
+    override fun setClearSectionEnabled(enabled: Boolean) {
+        clearAllButtonEnabled = enabled
+        _view?.setClearSectionButtonEnabled(enabled)
+    }
+
+    override fun setOnClearSectionClickListener(listener: View.OnClickListener) {
         clearAllClickListener = listener
         _view?.setOnClearAllClickListener(listener)
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
index 94f5c44..540216c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/dagger/NotificationsModule.java
@@ -45,10 +45,12 @@
 import com.android.systemui.statusbar.notification.collection.NotifCollection;
 import com.android.systemui.statusbar.notification.collection.NotifInflaterImpl;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
+import com.android.systemui.statusbar.notification.collection.coordinator.ShadeEventCoordinator;
 import com.android.systemui.statusbar.notification.collection.coordinator.VisualStabilityCoordinator;
 import com.android.systemui.statusbar.notification.collection.inflation.NotifInflater;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinder;
 import com.android.systemui.statusbar.notification.collection.inflation.OnUserInteractionCallbackImpl;
+import com.android.systemui.statusbar.notification.collection.legacy.LegacyNotificationPresenterExtensions;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
 import com.android.systemui.statusbar.notification.collection.legacy.OnUserInteractionCallbackImplLegacy;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
@@ -58,6 +60,8 @@
 import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManagerImpl;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
 import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManagerImpl;
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.init.NotificationsControllerImpl;
 import com.android.systemui.statusbar.notification.init.NotificationsControllerStub;
@@ -89,7 +93,7 @@
 /**
  * Dagger Module for classes found within the com.android.systemui.statusbar.notification package.
  */
-@Module(includes = { NotificationSectionHeadersModule.class })
+@Module(includes = {NotificationSectionHeadersModule.class})
 public interface NotificationsModule {
     @Binds
     StackScrollAlgorithm.SectionProvider bindSectionProvider(
@@ -169,6 +173,14 @@
                 dumpManager);
     }
 
+    /** Provides an instance of {@link NotifGutsViewManager} */
+    @SysUISingleton
+    @Provides
+    static NotifGutsViewManager provideNotifGutsViewManager(
+            NotificationGutsManager notificationGutsManager) {
+        return notificationGutsManager;
+    }
+
     /** Provides an instance of {@link VisualStabilityManager} */
     @SysUISingleton
     @Provides
@@ -262,6 +274,20 @@
     }
 
     /**
+     * Provide the active implementation for presenting notifications.
+     */
+    @Provides
+    @SysUISingleton
+    static NotifShadeEventSource provideNotifShadeEventSource(
+            FeatureFlags featureFlags,
+            Lazy<ShadeEventCoordinator> shadeEventCoordinatorLazy,
+            Lazy<LegacyNotificationPresenterExtensions> legacyNotificationPresenterExtensionsLazy) {
+        return featureFlags.isNewNotifPipelineRenderingEnabled()
+                ? shadeEventCoordinatorLazy.get()
+                : legacyNotificationPresenterExtensionsLazy.get();
+    }
+
+    /**
      * Provide a dismissal callback that's triggered when a user manually dismissed a notification
      * from the notification shade or it gets auto-cancelled by click.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
index c147023..9faef1b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/logging/NotificationPanelLogger.java
@@ -16,12 +16,12 @@
 
 package com.android.systemui.statusbar.notification.logging;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_FOREGROUND_SERVICE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_HEADS_UP;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_HEADS_UP;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
 
 import android.annotation.Nullable;
 import android.service.notification.StatusBarNotification;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
index 0d8e850..02b1210 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/ExpandableNotificationRow.java
@@ -1249,6 +1249,7 @@
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
+        super.onConfigurationChanged(newConfig);
         if (mMenuRow != null && mMenuRow.getMenuView() != null) {
             mMenuRow.onConfigurationChanged();
         }
@@ -3201,13 +3202,6 @@
         }
     }
 
-    /** Sets whether dismiss gestures are right-to-left (instead of left-to-right). */
-    public void setDismissRtl(boolean dismissRtl) {
-        if (mMenuRow != null) {
-            mMenuRow.setDismissRtl(dismissRtl);
-        }
-    }
-
     private static class NotificationViewState extends ExpandableViewState {
 
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
index 7eec95a..8e02d9f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationGutsManager.java
@@ -65,6 +65,8 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewListener;
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager;
 import com.android.systemui.statusbar.notification.dagger.NotificationsModule;
 import com.android.systemui.statusbar.notification.row.NotificationInfo.CheckSaveListener;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
@@ -83,7 +85,8 @@
  * Handles various NotificationGuts related tasks, such as binding guts to a row, opening and
  * closing guts, and keeping track of the currently exposed notification guts.
  */
-public class NotificationGutsManager implements Dumpable, NotificationLifetimeExtender {
+public class NotificationGutsManager implements Dumpable, NotificationLifetimeExtender,
+        NotifGutsViewManager {
     private static final String TAG = "NotificationGutsManager";
 
     // Must match constant in Settings. Used to highlight preferences when linking to Settings.
@@ -123,7 +126,6 @@
     private final Optional<BubblesManager> mBubblesManagerOptional;
     private Runnable mOpenRunnable;
     private final INotificationManager mNotificationManager;
-    private final NotificationEntryManager mNotificationEntryManager;
     private final PeopleSpaceWidgetManager mPeopleSpaceWidgetManager;
     private final LauncherApps mLauncherApps;
     private final ShortcutManager mShortcutManager;
@@ -131,6 +133,7 @@
     private final UiEventLogger mUiEventLogger;
     private final ShadeController mShadeController;
     private final AppWidgetManager mAppWidgetManager;
+    private NotifGutsViewListener mGutsListener;
 
     /**
      * Injected constructor. See {@link NotificationsModule}.
@@ -161,7 +164,6 @@
         mAccessibilityManager = accessibilityManager;
         mHighPriorityProvider = highPriorityProvider;
         mNotificationManager = notificationManager;
-        mNotificationEntryManager = notificationEntryManager;
         mPeopleSpaceWidgetManager = peopleSpaceWidgetManager;
         mLauncherApps = launcherApps;
         mShortcutManager = shortcutManager;
@@ -258,10 +260,10 @@
     @VisibleForTesting
     protected boolean bindGuts(final ExpandableNotificationRow row,
             NotificationMenuRowPlugin.MenuItem item) {
-        StatusBarNotification sbn = row.getEntry().getSbn();
+        NotificationEntry entry = row.getEntry();
 
         row.setGutsView(item);
-        row.setTag(sbn.getPackageName());
+        row.setTag(entry.getSbn().getPackageName());
         row.getGuts().setClosedListener((NotificationGuts g) -> {
             row.onGutsClosed();
             if (!g.willBeRemoved() && !row.isRemoved()) {
@@ -272,7 +274,10 @@
                 mNotificationGutsExposed = null;
                 mGutsMenuItem = null;
             }
-            String key = sbn.getKey();
+            if (mGutsListener != null) {
+                mGutsListener.onGutsClose(entry);
+            }
+            String key = entry.getKey();
             if (key.equals(mKeyToRemoveOnGutsClosed)) {
                 mKeyToRemoveOnGutsClosed = null;
                 if (mNotificationLifetimeFinishedCallback != null) {
@@ -650,6 +655,10 @@
                         needsFalsingProtection,
                         row::onGutsOpened);
 
+                if (mGutsListener != null) {
+                    mGutsListener.onGutsOpen(row.getEntry(), guts);
+                }
+
                 row.closeRemoteInput();
                 mListContainer.onHeightChanged(row, true /* needsAnimation */);
                 mGutsMenuItem = menuItem;
@@ -695,10 +704,17 @@
     @Override
     public void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
         pw.println("NotificationGutsManager state:");
-        pw.print("  mKeyToRemoveOnGutsClosed: ");
+        pw.print("  mKeyToRemoveOnGutsClosed (legacy): ");
         pw.println(mKeyToRemoveOnGutsClosed);
     }
 
+    /**
+     * @param gutsListener the listener for open and close guts events
+     */
+    public void setGutsListener(NotifGutsViewListener gutsListener) {
+        mGutsListener = gutsListener;
+    }
+
     public interface OnSettingsClickListener {
         public void onSettingsClick(String key);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
index d59318e..3a37fb4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/row/NotificationMenuRow.java
@@ -85,7 +85,6 @@
     private ArrayList<MenuItem> mRightMenuItems;
     private final Map<View, MenuItem> mMenuItemsByView = new ArrayMap<>();
     private OnMenuEventListener mMenuListener;
-    private boolean mDismissRtl;
 
     private ValueAnimator mFadeAnimator;
     private boolean mAnimating;
@@ -790,14 +789,6 @@
         return getParent().canViewBeDismissed();
     }
 
-    @Override
-    public void setDismissRtl(boolean dismissRtl) {
-        mDismissRtl = dismissRtl;
-        if (mMenuContainer != null) {
-            createMenuViews(true);
-        }
-    }
-
     public static class NotificationMenuItem implements MenuItem {
         View mMenuView;
         GutsContent mGutsContent;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
new file mode 100644
index 0000000..31f4857
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationPriorityBucket.kt
@@ -0,0 +1,25 @@
+package com.android.systemui.statusbar.notification.stack
+
+import android.annotation.IntDef
+
+/**
+ * For now, declare the available notification buckets (sections) here so that other
+ * presentation code can decide what to do based on an entry's buckets
+ */
+@Retention(AnnotationRetention.SOURCE)
+@IntDef(
+        prefix = ["BUCKET_"],
+        value = [
+            BUCKET_UNKNOWN, BUCKET_MEDIA_CONTROLS, BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE,
+            BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT
+        ]
+)
+annotation class PriorityBucket
+
+const val BUCKET_UNKNOWN = 0
+const val BUCKET_MEDIA_CONTROLS = 1
+const val BUCKET_HEADS_UP = 2
+const val BUCKET_FOREGROUND_SERVICE = 3
+const val BUCKET_PEOPLE = 4
+const val BUCKET_ALERTING = 5
+const val BUCKET_SILENT = 6
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
index ab39de0..bc172ce 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSection.java
@@ -16,7 +16,7 @@
 
 package com.android.systemui.statusbar.notification.stack;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
 
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
index 45ce20a..5f157a7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManager.kt
@@ -16,7 +16,6 @@
 package com.android.systemui.statusbar.notification.stack
 
 import android.annotation.ColorInt
-import android.annotation.IntDef
 import android.annotation.LayoutRes
 import android.util.Log
 import android.view.LayoutInflater
@@ -350,7 +349,7 @@
         silentHeaderView?.run {
             val hasActiveClearableNotifications = this@NotificationSectionsManager.parent
                     .hasActiveClearableNotifications(NotificationStackScrollLayout.ROWS_GENTLE)
-            setAreThereDismissableGentleNotifs(hasActiveClearableNotifications)
+            setClearSectionButtonEnabled(hasActiveClearableNotifications)
         }
     }
 
@@ -448,25 +447,3 @@
         private const val DEBUG = false
     }
 }
-
-/**
- * For now, declare the available notification buckets (sections) here so that other
- * presentation code can decide what to do based on an entry's buckets
- */
-@Retention(AnnotationRetention.SOURCE)
-@IntDef(
-        prefix = ["BUCKET_"],
-        value = [
-            BUCKET_UNKNOWN, BUCKET_MEDIA_CONTROLS, BUCKET_HEADS_UP, BUCKET_FOREGROUND_SERVICE,
-            BUCKET_PEOPLE, BUCKET_ALERTING, BUCKET_SILENT
-        ]
-)
-annotation class PriorityBucket
-
-const val BUCKET_UNKNOWN = 0
-const val BUCKET_MEDIA_CONTROLS = 1
-const val BUCKET_HEADS_UP = 2
-const val BUCKET_FOREGROUND_SERVICE = 3
-const val BUCKET_PEOPLE = 4
-const val BUCKET_ALERTING = 5
-const val BUCKET_SILENT = 6
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 3e67f7e..6aa5f07 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -17,9 +17,8 @@
 package com.android.systemui.statusbar.notification.stack;
 
 import static com.android.internal.jank.InteractionJankMonitor.CUJ_NOTIFICATION_SHADE_SCROLL_FLING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
 import static com.android.systemui.statusbar.notification.stack.StackStateAnimator.ANIMATION_DURATION_SWIPE;
-import static com.android.systemui.util.InjectionInflationController.VIEW_CONTEXT;
 import static com.android.systemui.util.Utils.shouldUseSplitNotificationShade;
 
 import static java.lang.annotation.RetentionPolicy.SOURCE;
@@ -72,8 +71,10 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.graphics.ColorUtils;
 import com.android.internal.jank.InteractionJankMonitor;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.keyguard.KeyguardSliceView;
 import com.android.settingslib.Utils;
+import com.android.systemui.Dependency;
 import com.android.systemui.Dumpable;
 import com.android.systemui.ExpandHelper;
 import com.android.systemui.R;
@@ -120,9 +121,6 @@
 import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 
-import javax.inject.Inject;
-import javax.inject.Named;
-
 /**
  * A layout which handles a dynamic amount of notifications and presents them in a scrollable stack.
  */
@@ -163,7 +161,6 @@
     private final Paint mBackgroundPaint = new Paint();
     private final boolean mShouldDrawNotificationBackground;
     private boolean mHighPriorityBeforeSpeedBump;
-    private boolean mDismissRtl;
 
     private float mExpandedHeight;
     private int mOwnScrollY;
@@ -566,24 +563,17 @@
     @Nullable
     private OnClickListener mManageButtonClickListener;
 
-    @Inject
-    public NotificationStackScrollLayout(
-            @Named(VIEW_CONTEXT) Context context,
-            AttributeSet attrs,
-            NotificationSectionsManager notificationSectionsManager,
-            GroupMembershipManager groupMembershipManager,
-            GroupExpansionManager groupExpansionManager,
-            AmbientState ambientState,
-            UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
+    public NotificationStackScrollLayout(Context context, AttributeSet attrs) {
         super(context, attrs, 0, 0);
         Resources res = getResources();
-        mSectionsManager = notificationSectionsManager;
-        mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
+        mSectionsManager = Dependency.get(NotificationSectionsManager.class);
+        mUnlockedScreenOffAnimationController =
+                Dependency.get(UnlockedScreenOffAnimationController.class);
         updateSplitNotificationShade();
         mSectionsManager.initialize(this, LayoutInflater.from(context));
         mSections = mSectionsManager.createSectionsForBuckets();
 
-        mAmbientState = ambientState;
+        mAmbientState = Dependency.get(AmbientState.class);
         mBgColor = Utils.getColorAttr(mContext, android.R.attr.colorBackgroundFloating)
                 .getDefaultColor();
         int minHeight = res.getDimensionPixelSize(R.dimen.notification_min_height);
@@ -609,8 +599,8 @@
             mDebugPaint.setTextSize(25f);
         }
         mClearAllEnabled = res.getBoolean(R.bool.config_enableNotificationsClearAll);
-        mGroupMembershipManager = groupMembershipManager;
-        mGroupExpansionManager = groupExpansionManager;
+        mGroupMembershipManager = Dependency.get(GroupMembershipManager.class);
+        mGroupExpansionManager = Dependency.get(GroupExpansionManager.class);
         setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES);
     }
 
@@ -622,16 +612,6 @@
         addView(mFgsSectionView, -1);
     }
 
-    void updateDismissRtlSetting(boolean dismissRtl) {
-        mDismissRtl = dismissRtl;
-        for (int i = 0; i < getChildCount(); i++) {
-            View child = getChildAt(i);
-            if (child instanceof ExpandableNotificationRow) {
-                ((ExpandableNotificationRow) child).setDismissRtl(dismissRtl);
-            }
-        }
-    }
-
     /**
      * Set the overexpansion of the panel to be applied to the view.
      */
@@ -673,6 +653,10 @@
         return 0f;
     }
 
+    public float getNotificationSquishinessFraction() {
+        return mStackScrollAlgorithm.getNotificationSquishinessFraction(mAmbientState);
+    }
+
     void reinflateViews() {
         inflateFooterView();
         inflateEmptyShadeView();
@@ -947,7 +931,7 @@
                 res.getDimensionPixelSize(R.dimen.notification_divider_height));
         mMinTopOverScrollToEscape = res.getDimensionPixelSize(
                 R.dimen.min_top_overscroll_to_qs);
-        mStatusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         mBottomMargin = res.getDimensionPixelSize(R.dimen.notification_panel_margin_bottom);
         mMinimumPaddings = res.getDimensionPixelSize(R.dimen.notification_side_paddings);
         mQsTilePadding = res.getDimensionPixelOffset(R.dimen.qs_tile_margin_horizontal);
@@ -958,8 +942,7 @@
         mCornerRadius = res.getDimensionPixelSize(R.dimen.notification_corner_radius);
         mHeadsUpInset = mStatusBarHeight + res.getDimensionPixelSize(
                 R.dimen.heads_up_status_bar_padding);
-        mQsScrollBoundaryPosition = res.getDimensionPixelSize(
-                com.android.internal.R.dimen.quick_qs_offset_height);
+        mQsScrollBoundaryPosition = SystemBarUtils.getQuickQsOffsetHeight(mContext);
     }
 
     void updateSidePadding(int viewWidth) {
@@ -1717,7 +1700,7 @@
         super.onConfigurationChanged(newConfig);
         Resources res = getResources();
         updateSplitNotificationShade();
-        mStatusBarHeight = res.getDimensionPixelOffset(R.dimen.status_bar_height);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         float densityScale = res.getDisplayMetrics().density;
         mSwipeHelper.setDensityScale(densityScale);
         float pagingTouchSlop = ViewConfiguration.get(getContext()).getScaledPagingTouchSlop();
@@ -2921,7 +2904,6 @@
         updateChronometerForChild(child);
         if (child instanceof ExpandableNotificationRow) {
             ExpandableNotificationRow row = (ExpandableNotificationRow) child;
-            row.setDismissRtl(mDismissRtl);
             row.setDismissUsingRowTranslationX(mDismissUsingRowTranslationX);
 
         }
@@ -5278,10 +5260,6 @@
         mController.getNoticationRoundessManager().setAnimatedChildren(mChildrenToAddAnimated);
     }
 
-    public NotificationStackScrollLayoutController getController() {
-        return mController;
-    }
-
     void addSwipedOutView(View v) {
         mSwipedOutViews.add(v);
     }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index b226aec..03fc767 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -783,9 +783,6 @@
         mTunerService.addTunable(
                 (key, newValue) -> {
                     switch (key) {
-                        case Settings.Secure.NOTIFICATION_DISMISS_RTL:
-                            mView.updateDismissRtlSetting("1".equals(newValue));
-                            break;
                         case Settings.Secure.NOTIFICATION_HISTORY_ENABLED:
                             updateFooter();
                             break;
@@ -795,7 +792,6 @@
                     }
                 },
                 HIGH_PRIORITY,
-                Settings.Secure.NOTIFICATION_DISMISS_RTL,
                 Settings.Secure.NOTIFICATION_HISTORY_ENABLED);
 
         mKeyguardMediaController.setVisibilityChangedListener(visible -> {
@@ -810,14 +806,15 @@
             return Unit.INSTANCE;
         });
 
-        // callback is invoked synchronously, updating mView immediately
+        // attach callback, and then call it to update mView immediately
         mDeviceProvisionedController.addCallback(mDeviceProvisionedListener);
+        mDeviceProvisionedListener.onDeviceProvisionedChanged();
 
         if (mView.isAttachedToWindow()) {
             mOnAttachStateChangeListener.onViewAttachedToWindow(mView);
         }
         mView.addOnAttachStateChangeListener(mOnAttachStateChangeListener);
-        mSilentHeaderController.setOnClearAllClickListener(v -> clearSilentNotifications());
+        mSilentHeaderController.setOnClearSectionClickListener(v -> clearSilentNotifications());
     }
 
     private boolean isInVisibleLocation(NotificationEntry entry) {
@@ -1077,6 +1074,10 @@
         mView.setOnStackYChanged(onStackYChanged);
     }
 
+    public float getNotificationSquishinessFraction() {
+        return mView.getNotificationSquishinessFraction();
+    }
+
     public float calculateAppearFractionBypass() {
         return mView.calculateAppearFractionBypass();
     }
@@ -1300,6 +1301,9 @@
     }
 
     public void updateSectionBoundaries(String reason) {
+        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+            return;
+        }
         mView.updateSectionBoundaries(reason);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
index 99ec7548..baf09c7 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/SectionHeaderView.java
@@ -85,8 +85,12 @@
         return true;
     }
 
-    void setAreThereDismissableGentleNotifs(boolean areThereDismissableGentleNotifs) {
-        mClearAllButton.setVisibility(areThereDismissableGentleNotifs ? View.VISIBLE : View.GONE);
+    /**
+     * Show the clear section [X] button
+     * @param enabled
+     */
+    public void setClearSectionButtonEnabled(boolean enabled) {
+        mClearAllButton.setVisibility(enabled ? View.VISIBLE : View.GONE);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
index 0accce8..015edb8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/StackScrollAlgorithm.java
@@ -26,6 +26,7 @@
 
 import androidx.annotation.VisibleForTesting;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
 import com.android.systemui.animation.ShadeInterpolation;
 import com.android.systemui.statusbar.NotificationShelf;
@@ -77,7 +78,7 @@
                 R.dimen.notification_divider_height);
         mCollapsedSize = res.getDimensionPixelSize(R.dimen.notification_min_height);
         mClipNotificationScrollToTop = res.getBoolean(R.bool.config_clipNotificationScrollToTop);
-        int statusBarHeight = res.getDimensionPixelSize(R.dimen.status_bar_height);
+        int statusBarHeight = SystemBarUtils.getStatusBarHeight(context);
         mHeadsUpInset = statusBarHeight + res.getDimensionPixelSize(
                 R.dimen.heads_up_status_bar_padding);
         mPinnedZTranslationExtra = res.getDimensionPixelSize(
@@ -109,6 +110,15 @@
         getNotificationChildrenStates(algorithmState, ambientState);
     }
 
+    /**
+     * How expanded or collapsed notifications are when pulling down the shade.
+     * @param ambientState Current ambient state.
+     * @return 0 when fully collapsed, 1 when expanded.
+     */
+    public float getNotificationSquishinessFraction(AmbientState ambientState) {
+        return getExpansionFractionWithoutShelf(mTempAlgorithmState, ambientState);
+    }
+
     private void resetChildViewStates() {
         int numChildren = mHostView.getChildCount();
         for (int i = 0; i < numChildren; i++) {
@@ -363,7 +373,6 @@
 
         final float stackHeight = ambientState.getStackHeight()  - shelfHeight - scrimPadding;
         final float stackEndHeight = ambientState.getStackEndHeight() - shelfHeight - scrimPadding;
-
         return stackHeight / stackEndHeight;
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
index 5f402d0..c81196d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpManagerPhone.java
@@ -26,6 +26,7 @@
 import androidx.collection.ArraySet;
 
 import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
@@ -137,9 +138,8 @@
 
     private void updateResources() {
         Resources resources = mContext.getResources();
-        mHeadsUpInset =
-                resources.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height)
-                        + resources.getDimensionPixelSize(R.dimen.heads_up_status_bar_padding);
+        mHeadsUpInset = SystemBarUtils.getStatusBarHeight(mContext)
+                + resources.getDimensionPixelSize(R.dimen.heads_up_status_bar_padding);
     }
 
     ///////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
index c639eec..e26f75f 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBottomAreaView.java
@@ -1078,10 +1078,14 @@
                 .addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK)
                 .putExtra(ControlsUiController.EXTRA_ANIMATE, true);
 
+        ActivityLaunchAnimator.Controller controller =
+                v != null ? ActivityLaunchAnimator.Controller.fromView(v, null /* cujType */)
+                        : null;
         if (mControlsComponent.getVisibility() == AVAILABLE) {
-            mContext.startActivity(intent);
+            mActivityStarter.startActivity(intent, true /* dismissShade */, controller,
+                    true /* showOverLockscreenWhenLocked */);
         } else {
-            mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */);
+            mActivityStarter.postStartActivityDismissingKeyguard(intent, 0 /* delay */, controller);
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index a090ac3..353868b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -30,6 +30,7 @@
 import android.view.ViewGroup;
 import android.view.WindowInsets;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.keyguard.KeyguardHostViewController;
 import com.android.keyguard.KeyguardRootViewController;
 import com.android.keyguard.KeyguardSecurityModel;
@@ -44,6 +45,7 @@
 import com.android.systemui.keyguard.DismissCallbackRegistry;
 import com.android.systemui.shared.system.SysUiStatsLog;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.util.ListenerSet;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -83,11 +85,11 @@
     private final Runnable mRemoveViewRunnable = this::removeView;
     private final KeyguardBypassController mKeyguardBypassController;
     private KeyguardHostViewController mKeyguardViewController;
-    private final List<KeyguardResetCallback> mResetCallbacks = new ArrayList<>();
+    private final ListenerSet<KeyguardResetCallback> mResetCallbacks = new ListenerSet<>();
     private final Runnable mResetRunnable = ()-> {
         if (mKeyguardViewController != null) {
             mKeyguardViewController.resetSecurityContainer();
-            for (KeyguardResetCallback callback : new ArrayList<>(mResetCallbacks)) {
+            for (KeyguardResetCallback callback : mResetCallbacks) {
                 callback.onKeyguardReset();
             }
         }
@@ -467,8 +469,7 @@
         mKeyguardViewController.init();
 
         mContainer.addView(mRoot, mContainer.getChildCount());
-        mStatusBarHeight = mRoot.getResources().getDimensionPixelOffset(
-                com.android.systemui.R.dimen.status_bar_height);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         setVisibility(View.INVISIBLE);
 
         final WindowInsets rootInsets = mRoot.getRootWindowInsets();
@@ -602,7 +603,7 @@
     }
 
     public void addKeyguardResetCallback(KeyguardResetCallback callback) {
-        mResetCallbacks.add(callback);
+        mResetCallbacks.addIfAbsent(callback);
     }
 
     public void removeKeyguardResetCallback(KeyguardResetCallback callback) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index e368aad..4f3bbdb 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -195,12 +195,21 @@
                 1.0f /* panelExpansion */, 1.0f /* darkAmount */);
         result.clockAlpha = getClockAlpha(y);
         result.stackScrollerPadding = getStackScrollerPadding(y);
-        result.stackScrollerPaddingExpanded = mBypassEnabled ? mUnlockedStackScrollerPadding
-                : getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+        result.stackScrollerPaddingExpanded = getStackScrollerPaddingExpanded();
         result.clockX = (int) interpolate(0, burnInPreventionOffsetX(), mDarkAmount);
         result.clockScale = interpolate(getBurnInScale(), 1.0f, 1.0f - mDarkAmount);
     }
 
+    private int getStackScrollerPaddingExpanded() {
+        if (mBypassEnabled) {
+            return mUnlockedStackScrollerPadding;
+        } else if (mIsSplitShade) {
+            return getClockY(1.0f, mDarkAmount);
+        } else {
+            return getClockY(1.0f, mDarkAmount) + mKeyguardStatusHeight;
+        }
+    }
+
     private int getStackScrollerPadding(int clockYPosition) {
         if (mBypassEnabled) {
             return (int) (mUnlockedStackScrollerPadding + mOverStretchAmount);
@@ -212,8 +221,13 @@
     }
 
     public float getMinStackScrollerPadding() {
-        return mBypassEnabled ? mUnlockedStackScrollerPadding
-                : mMinTopMargin + mKeyguardStatusHeight;
+        if (mBypassEnabled) {
+            return mUnlockedStackScrollerPadding;
+        } else if (mIsSplitShade) {
+            return mMinTopMargin;
+        } else {
+            return mMinTopMargin + mKeyguardStatusHeight;
+        }
     }
 
     private int getExpandedPreferredClockY() {
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 fe154d2..03f3b0c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardStatusBarView.java
@@ -18,6 +18,7 @@
 
 import static com.android.systemui.DejankUtils.whitelistIpcs;
 import static com.android.systemui.ScreenDecorations.DisplayCutoutView.boundsFromDirection;
+import static com.android.systemui.util.Utils.getStatusBarHeaderHeightKeyguard;
 
 import android.annotation.ColorInt;
 import android.content.Context;
@@ -162,11 +163,8 @@
     }
 
     private void updateKeyguardStatusBarHeight() {
-        final int waterfallTop =
-                mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
         MarginLayoutParams lp =  (MarginLayoutParams) getLayoutParams();
-        lp.height =  getResources().getDimensionPixelSize(
-                R.dimen.status_bar_header_height_keyguard) + waterfallTop;
+        lp.height = getStatusBarHeaderHeightKeyguard(mContext);
         setLayoutParams(lp);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
index 2a13e6b..e565a44 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/LockscreenWallpaper.java
@@ -45,7 +45,6 @@
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.dump.DumpManager;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
 import com.android.systemui.statusbar.NotificationMediaManager;
 
 import libcore.io.IoUtils;
@@ -53,7 +52,6 @@
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Objects;
-import java.util.Optional;
 
 import javax.inject.Inject;
 
@@ -70,7 +68,6 @@
     private final WallpaperManager mWallpaperManager;
     private final KeyguardUpdateMonitor mUpdateMonitor;
     private final Handler mH;
-    private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
 
     private boolean mCached;
     private Bitmap mCache;
@@ -86,14 +83,12 @@
             KeyguardUpdateMonitor keyguardUpdateMonitor,
             DumpManager dumpManager,
             NotificationMediaManager mediaManager,
-            Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
             @Main Handler mainHandler) {
         dumpManager.registerDumpable(getClass().getSimpleName(), this);
         mWallpaperManager = wallpaperManager;
         mCurrentUserId = ActivityManager.getCurrentUser();
         mUpdateMonitor = keyguardUpdateMonitor;
         mMediaManager = mediaManager;
-        mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
         mH = mainHandler;
 
         if (iWallpaperManager != null) {
@@ -132,14 +127,6 @@
             return LoaderResult.success(null);
         }
 
-        Bitmap faceAuthWallpaper = null;
-        if (mFaceAuthScreenBrightnessController.isPresent()) {
-            faceAuthWallpaper = mFaceAuthScreenBrightnessController.get().getFaceAuthWallpaper();
-            if (faceAuthWallpaper != null) {
-                return LoaderResult.success(faceAuthWallpaper);
-            }
-        }
-
         // Prefer the selected user (when specified) over the current user for the FLAG_SET_LOCK
         // wallpaper.
         final int lockWallpaperUserId =
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
index f1bc64b..3fe393d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -94,6 +94,7 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.internal.util.LatencyTracker;
 import com.android.keyguard.KeyguardStatusView;
 import com.android.keyguard.KeyguardStatusViewController;
@@ -437,7 +438,6 @@
 
     private boolean mPulsing;
     private boolean mUserSetupComplete;
-    private int mQsNotificationTopPadding;
     private boolean mHideIconsDuringLaunchAnimation = true;
     private int mStackScrollerMeasuringPass;
     private ArrayList<Consumer<ExpandableNotificationRow>>
@@ -890,10 +890,8 @@
         super.loadDimens();
         mFlingAnimationUtils = mFlingAnimationUtilsBuilder.get()
                 .setMaxLengthSeconds(0.4f).build();
-        mStatusBarMinHeight = mResources.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
-        mStatusBarHeaderHeightKeyguard = mResources.getDimensionPixelSize(
-                R.dimen.status_bar_header_height_keyguard);
+        mStatusBarMinHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
+        mStatusBarHeaderHeightKeyguard = Utils.getStatusBarHeaderHeightKeyguard(mView.getContext());
         mQsPeekHeight = mResources.getDimensionPixelSize(R.dimen.qs_peek_height);
         mClockPositionAlgorithm.loadDimens(mResources);
         mQsFalsingThreshold = mResources.getDimensionPixelSize(R.dimen.qs_falsing_threshold);
@@ -903,8 +901,7 @@
                 R.dimen.keyguard_indication_bottom_padding);
         mShelfHeight = mResources.getDimensionPixelSize(R.dimen.notification_shelf_height);
         mDarkIconSize = mResources.getDimensionPixelSize(R.dimen.status_bar_icon_drawing_size_dark);
-        int statusbarHeight = mResources.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
+        int statusbarHeight = SystemBarUtils.getStatusBarHeight(mView.getContext());
         mHeadsUpInset = statusbarHeight + mResources.getDimensionPixelSize(
                 R.dimen.heads_up_status_bar_padding);
         mDistanceForQSFullShadeTransition = mResources.getDimensionPixelSize(
@@ -973,10 +970,8 @@
     }
 
     public void updateResources() {
-        mQuickQsOffsetHeight = mResources.getDimensionPixelSize(
-                com.android.internal.R.dimen.quick_qs_offset_height);
-        mSplitShadeStatusBarHeight =
-                mResources.getDimensionPixelSize(R.dimen.split_shade_header_height);
+        mQuickQsOffsetHeight = SystemBarUtils.getQuickQsOffsetHeight(mView.getContext());
+        mSplitShadeStatusBarHeight = Utils.getSplitShadeStatusBarHeight(mView.getContext());
         int qsWidth = mResources.getDimensionPixelSize(R.dimen.qs_panel_width);
         int panelWidth = mResources.getDimensionPixelSize(R.dimen.notification_panel_width);
         mShouldUseSplitNotificationShade =
@@ -1002,6 +997,7 @@
             constraintSet.connect(
                     R.id.notification_stack_scroller, START,
                     R.id.qs_edge_guideline, START);
+            constraintSet.constrainHeight(R.id.split_shade_status_bar, mSplitShadeStatusBarHeight);
         } else {
             constraintSet.connect(R.id.qs_frame, END, PARENT_ID, END);
             constraintSet.connect(R.id.notification_stack_scroller, START, PARENT_ID, START);
@@ -2221,7 +2217,8 @@
     private void updateQsExpansion() {
         if (mQs == null) return;
         float qsExpansionFraction = computeQsExpansionFraction();
-        mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation());
+        mQs.setQsExpansion(qsExpansionFraction, getExpandedFraction(), getHeaderTranslation(),
+                mNotificationStackScrollLayoutController.getNotificationSquishinessFraction());
         mMediaHierarchyManager.setQsExpansion(qsExpansionFraction);
         int qsPanelBottomY = calculateQsBottomPosition(qsExpansionFraction);
         mScrimController.setQsPosition(qsExpansionFraction, qsPanelBottomY);
@@ -2379,7 +2376,7 @@
                     // qsTranslation should only be positive during pulse expansion because it's
                     // already translating in from the top
                     qsTranslation = Math.max(0, (top - mQs.getHeader().getHeight()) / 2.0f);
-                } else {
+                } else if (!mShouldUseSplitNotificationShade) {
                     qsTranslation = (top - mQs.getHeader().getHeight()) * QS_PARALLAX_AMOUNT;
                 }
             }
@@ -4380,9 +4377,16 @@
                     }
                 }
             } else {
-                mKeyguardStatusBarViewController.updateViewState(
-                        /* alpha= */ 1f,
-                        keyguardShowing ? View.VISIBLE : View.INVISIBLE);
+                final boolean animatingUnlockedShadeToKeyguard = oldState == SHADE
+                        && statusBarState == KEYGUARD
+                        && mUnlockedScreenOffAnimationController.isScreenOffAnimationPlaying();
+                if (!animatingUnlockedShadeToKeyguard) {
+                    // Only make the status bar visible if we're not animating the screen off, since
+                    // we only want to be showing the clock/notifications during the animation.
+                    mKeyguardStatusBarViewController.updateViewState(
+                            /* alpha= */ 1f,
+                            keyguardShowing ? View.VISIBLE : View.INVISIBLE);
+                }
                 if (keyguardShowing && oldState != mBarState) {
                     if (mQs != null) {
                         mQs.hideImmediately();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
index 9d06d2b..36bd31b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewController.java
@@ -56,7 +56,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.tuner.TunerService;
-import com.android.systemui.util.InjectionInflationController;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
@@ -68,7 +67,6 @@
  */
 public class NotificationShadeWindowViewController {
     private static final String TAG = "NotifShadeWindowVC";
-    private final InjectionInflationController mInjectionInflationController;
     private final NotificationWakeUpCoordinator mCoordinator;
     private final PulseExpansionHandler mPulseExpansionHandler;
     private final DynamicPrivacyController mDynamicPrivacyController;
@@ -116,7 +114,6 @@
 
     @Inject
     public NotificationShadeWindowViewController(
-            InjectionInflationController injectionInflationController,
             NotificationWakeUpCoordinator coordinator,
             PulseExpansionHandler pulseExpansionHandler,
             DynamicPrivacyController dynamicPrivacyController,
@@ -141,7 +138,6 @@
             NotificationStackScrollLayoutController notificationStackScrollLayoutController,
             StatusBarKeyguardViewManager statusBarKeyguardViewManager,
             LockIconViewController lockIconViewController) {
-        mInjectionInflationController = injectionInflationController;
         mCoordinator = coordinator;
         mPulseExpansionHandler = pulseExpansionHandler;
         mDynamicPrivacyController = dynamicPrivacyController;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
index ac8ebd9..e5296af 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -396,6 +396,12 @@
                     expand = false;
                 } else if (onKeyguard) {
                     expand = true;
+                } else if (mKeyguardStateController.isKeyguardFadingAway()) {
+                    // If we're in the middle of dismissing the keyguard, don't expand due to the
+                    // cancelled gesture. Gesture cancellation during an unlock is expected in some
+                    // situations, such keeping your finger down while swiping to unlock to an app
+                    // that is locked in landscape (the rotation will cancel the touch event).
+                    expand = false;
                 } else {
                     // If we get a cancel, put the shade back to the state it was in when the
                     // gesture started
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
index 7b110a0..d19ed28 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarPolicy.java
@@ -604,8 +604,7 @@
 
     @Override
     public void onUserSetupChanged() {
-        boolean userSetup = mProvisionedController.isUserSetup(
-                mProvisionedController.getCurrentUser());
+        boolean userSetup = mProvisionedController.isCurrentUserSetup();
         if (mCurrentUserSetup == userSetup) return;
         mCurrentUserSetup = userSetup;
         updateAlarm();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
index 06a31c9..883313b 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarView.java
@@ -35,6 +35,7 @@
 import android.view.accessibility.AccessibilityEvent;
 import android.widget.LinearLayout;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.Dependency;
 import com.android.systemui.R;
 import com.android.systemui.plugins.DarkIconDispatcher;
@@ -223,7 +224,7 @@
         final int waterfallTopInset =
                 mDisplayCutout == null ? 0 : mDisplayCutout.getWaterfallInsets().top;
         ViewGroup.LayoutParams layoutParams = getLayoutParams();
-        mStatusBarHeight = getResources().getDimensionPixelSize(R.dimen.status_bar_height);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         layoutParams.height = mStatusBarHeight - waterfallTopInset;
 
         int statusBarPaddingTop = getResources().getDimensionPixelSize(
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
index e27f458..de21e73 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewController.kt
@@ -18,25 +18,28 @@
 import android.graphics.Point
 import android.view.View
 import android.view.ViewGroup
+import android.view.ViewTreeObserver
 import com.android.systemui.R
 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
 import com.android.systemui.statusbar.CommandQueue
+import com.android.systemui.unfold.UNFOLD_STATUS_BAR
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
 import com.android.systemui.util.ViewController
+import javax.inject.Inject
+import javax.inject.Named
+import dagger.Lazy
 
 /** Controller for [PhoneStatusBarView].  */
-class PhoneStatusBarViewController(
+class PhoneStatusBarViewController private constructor(
     view: PhoneStatusBarView,
-    statusBarMoveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
+    @Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider?,
+    private val moveFromCenterAnimationController: StatusBarMoveFromCenterAnimationController?,
     touchEventHandler: PhoneStatusBarView.TouchEventHandler,
 ) : ViewController<PhoneStatusBarView>(view) {
 
-    override fun onViewAttached() {}
-    override fun onViewDetached() {}
-
-    init {
-        mView.setTouchEventHandler(touchEventHandler)
-
-        statusBarMoveFromCenterAnimationController?.let { animationController ->
+    override fun onViewAttached() {
+        moveFromCenterAnimationController?.let { animationController ->
             val statusBarLeftSide: View = mView.findViewById(R.id.status_bar_left_side)
             val systemIconArea: ViewGroup = mView.findViewById(R.id.system_icon_area)
 
@@ -46,15 +49,33 @@
                 systemIconArea
             )
 
-            animationController.init(viewsToAnimate, viewCenterProvider)
+            mView.viewTreeObserver.addOnPreDrawListener(object :
+                ViewTreeObserver.OnPreDrawListener {
+                override fun onPreDraw(): Boolean {
+                    animationController.onViewsReady(viewsToAnimate, viewCenterProvider)
+                    mView.viewTreeObserver.removeOnPreDrawListener(this)
+                    return true
+                }
+            })
 
             mView.addOnLayoutChangeListener { _, left, _, right, _, oldLeft, _, oldRight, _ ->
                 val widthChanged = right - left != oldRight - oldLeft
                 if (widthChanged) {
-                    statusBarMoveFromCenterAnimationController.onStatusBarWidthChanged()
+                    moveFromCenterAnimationController.onStatusBarWidthChanged()
                 }
             }
         }
+
+        progressProvider?.setReadyToHandleTransition(true)
+    }
+
+    override fun onViewDetached() {
+        progressProvider?.setReadyToHandleTransition(false)
+        moveFromCenterAnimationController?.onViewDetached()
+    }
+
+    init {
+        mView.setTouchEventHandler(touchEventHandler)
     }
 
     fun setImportantForAccessibility(mode: Int) {
@@ -92,4 +113,23 @@
             outPoint.y = viewY + view.height / 2
         }
     }
+
+    class Factory @Inject constructor(
+        @Named(UNFOLD_STATUS_BAR)
+        private val progressProvider: Lazy<ScopedUnfoldTransitionProgressProvider>,
+        private val moveFromCenterController: Lazy<StatusBarMoveFromCenterAnimationController>,
+        private val unfoldConfig: UnfoldTransitionConfig,
+    ) {
+        fun create(
+            view: PhoneStatusBarView,
+            touchEventHandler: PhoneStatusBarView.TouchEventHandler
+        ): PhoneStatusBarViewController {
+            return PhoneStatusBarViewController(
+                view,
+                if (unfoldConfig.isEnabled) progressProvider.get() else null,
+                if (unfoldConfig.isEnabled) moveFromCenterController.get() else null,
+                touchEventHandler
+            )
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
index a7ecd06..8732891 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SplitShadeHeaderController.kt
@@ -41,15 +41,28 @@
     private val iconManager: StatusBarIconController.IconManager
     private val qsCarrierGroupController: QSCarrierGroupController
     private var visible = false
+        set(value) {
+            if (field == value) {
+                return
+            }
+            field = value
+            updateListeners()
+        }
 
     var shadeExpanded = false
         set(value) {
+            if (field == value) {
+                return
+            }
             field = value
             updateVisibility()
         }
 
     var splitShadeMode = false
         set(value) {
+            if (field == value) {
+                return
+            }
             field = value
             updateVisibility()
         }
@@ -78,15 +91,20 @@
     }
 
     private fun updateVisibility() {
-        val shouldBeVisible = shadeExpanded && splitShadeMode
-        if (visible != shouldBeVisible) {
-            visible = shouldBeVisible
-            statusBar.visibility = if (shouldBeVisible) View.VISIBLE else View.GONE
-            updateListeners(shouldBeVisible)
+        val visibility = if (!splitShadeMode) {
+            View.GONE
+        } else if (shadeExpanded) {
+            View.VISIBLE
+        } else {
+            View.INVISIBLE
+        }
+        if (statusBar.visibility != visibility) {
+            statusBar.visibility = visibility
+            visible = visibility == View.VISIBLE
         }
     }
 
-    private fun updateListeners(visible: Boolean) {
+    private fun updateListeners() {
         qsCarrierGroupController.setListening(visible)
         if (visible) {
             statusBarIconController.addIconGroup(iconManager)
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 caa0dbe..4ad2af4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -174,7 +174,7 @@
 import com.android.systemui.qs.QSPanelController;
 import com.android.systemui.recents.ScreenPinningRequest;
 import com.android.systemui.scrim.ScrimView;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.AutoHideUiElement;
 import com.android.systemui.statusbar.BackDropView;
@@ -207,6 +207,7 @@
 import com.android.systemui.statusbar.notification.NotificationLaunchAnimatorControllerProvider;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
@@ -233,6 +234,7 @@
 import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
 import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
 import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.MessageRouter;
@@ -525,6 +527,7 @@
     private QSPanelController mQSPanelController;
 
     private final OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
+    private final PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
     KeyguardIndicationController mKeyguardIndicationController;
 
     private View mReportRejectedTouch;
@@ -533,18 +536,19 @@
 
     private final int[] mAbsPos = new int[2];
 
+    private final NotifShadeEventSource mNotifShadeEventSource;
     protected final NotificationEntryManager mEntryManager;
     private final NotificationGutsManager mGutsManager;
     private final NotificationLogger mNotificationLogger;
     private final NotificationViewHierarchyManager mViewHierarchyManager;
     private final KeyguardViewMediator mKeyguardViewMediator;
     protected final NotificationInterruptStateProvider mNotificationInterruptStateProvider;
-    private final BrightnessSlider.Factory mBrightnessSliderFactory;
+    private final BrightnessSliderController.Factory mBrightnessSliderFactory;
     private final FeatureFlags mFeatureFlags;
     private final UnfoldTransitionConfig mUnfoldTransitionConfig;
     private final Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimation;
+    private final Lazy<NaturalRotationUnfoldProgressProvider> mNaturalUnfoldProgressProvider;
     private final Lazy<UnfoldTransitionWallpaperController> mUnfoldWallpaperController;
-    private final Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimation;
     private final WallpaperController mWallpaperController;
     private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
     private final MessageRouter mMessageRouter;
@@ -716,6 +720,7 @@
             FalsingManager falsingManager,
             FalsingCollector falsingCollector,
             BroadcastDispatcher broadcastDispatcher,
+            NotifShadeEventSource notifShadeEventSource,
             NotificationEntryManager notificationEntryManager,
             NotificationGutsManager notificationGutsManager,
             NotificationLogger notificationLogger,
@@ -772,17 +777,18 @@
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             OperatorNameViewController.Factory operatorNameViewControllerFactory,
+            PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
             PhoneStatusBarPolicy phoneStatusBarPolicy,
             KeyguardIndicationController keyguardIndicationController,
             DemoModeController demoModeController,
             Lazy<NotificationShadeDepthController> notificationShadeDepthControllerLazy,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
             NotificationIconAreaController notificationIconAreaController,
-            BrightnessSlider.Factory brightnessSliderFactory,
+            BrightnessSliderController.Factory brightnessSliderFactory,
             UnfoldTransitionConfig unfoldTransitionConfig,
             Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
             Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
-            Lazy<StatusBarMoveFromCenterAnimationController> statusBarUnfoldAnimationController,
+            Lazy<NaturalRotationUnfoldProgressProvider> naturalRotationUnfoldProgressProvider,
             WallpaperController wallpaperController,
             OngoingCallController ongoingCallController,
             SystemStatusAnimationScheduler animationScheduler,
@@ -812,6 +818,7 @@
         mKeyguardStateController = keyguardStateController;
         mHeadsUpManager = headsUpManagerPhone;
         mOperatorNameViewControllerFactory = operatorNameViewControllerFactory;
+        mPhoneStatusBarViewControllerFactory = phoneStatusBarViewControllerFactory;
         mKeyguardIndicationController = keyguardIndicationController;
         mStatusBarTouchableRegionManager = statusBarTouchableRegionManager;
         mDynamicPrivacyController = dynamicPrivacyController;
@@ -819,6 +826,7 @@
         mFalsingCollector = falsingCollector;
         mFalsingManager = falsingManager;
         mBroadcastDispatcher = broadcastDispatcher;
+        mNotifShadeEventSource = notifShadeEventSource;
         mEntryManager = notificationEntryManager;
         mGutsManager = notificationGutsManager;
         mNotificationLogger = notificationLogger;
@@ -879,9 +887,9 @@
         mBrightnessSliderFactory = brightnessSliderFactory;
         mUnfoldTransitionConfig = unfoldTransitionConfig;
         mUnfoldLightRevealOverlayAnimation = unfoldLightRevealOverlayAnimation;
+        mNaturalUnfoldProgressProvider = naturalRotationUnfoldProgressProvider;
         mUnfoldWallpaperController = unfoldTransitionWallpaperController;
         mWallpaperController = wallpaperController;
-        mMoveFromCenterAnimation = statusBarUnfoldAnimationController;
         mOngoingCallController = ongoingCallController;
         mAnimationScheduler = animationScheduler;
         mStatusBarLocationPublisher = locationPublisher;
@@ -1077,6 +1085,7 @@
         if (mUnfoldTransitionConfig.isEnabled()) {
             mUnfoldLightRevealOverlayAnimation.get().init();
             mUnfoldWallpaperController.get().init();
+            mNaturalUnfoldProgressProvider.get().init();
         }
 
         mPluginManager.addPluginListener(
@@ -1178,16 +1187,9 @@
 
                     mNotificationPanelViewController.setBar(mStatusBarView);
 
-                    StatusBarMoveFromCenterAnimationController moveFromCenterAnimation = null;
-                    if (mUnfoldTransitionConfig.isEnabled()) {
-                        moveFromCenterAnimation = mMoveFromCenterAnimation.get();
-                    }
-                    mPhoneStatusBarViewController =
-                            new PhoneStatusBarViewController(
-                                    mStatusBarView,
-                                    moveFromCenterAnimation,
-                                    mNotificationPanelViewController.getStatusBarTouchEventHandler()
-                            );
+                    mPhoneStatusBarViewController = mPhoneStatusBarViewControllerFactory
+                            .create(mStatusBarView, mNotificationPanelViewController
+                                    .getStatusBarTouchEventHandler());
                     mPhoneStatusBarViewController.init();
 
                     mBatteryMeterViewController = new BatteryMeterViewController(
@@ -1218,7 +1220,7 @@
                     // TODO (b/136993073) Separate notification shade and status bar
                     mHeadsUpAppearanceController = new HeadsUpAppearanceController(
                             mNotificationIconAreaController, mHeadsUpManager,
-                            mStackScroller.getController(),
+                            mStackScrollerController,
                             mStatusBarStateController, mKeyguardBypassController,
                             mKeyguardStateController, mWakeUpCoordinator, mCommandQueue,
                             mNotificationPanelViewController, mStatusBarView);
@@ -1508,6 +1510,7 @@
                 mDynamicPrivacyController,
                 mKeyguardStateController,
                 mKeyguardIndicationController,
+                mFeatureFlags,
                 this /* statusBar */,
                 mShadeController,
                 mLockscreenShadeTransitionController,
@@ -1515,6 +1518,7 @@
                 mViewHierarchyManager,
                 mLockscreenUserManager,
                 mStatusBarStateController,
+                mNotifShadeEventSource,
                 mEntryManager,
                 mMediaManager,
                 mGutsManager,
@@ -4340,10 +4344,9 @@
     private final DeviceProvisionedListener mUserSetupObserver = new DeviceProvisionedListener() {
         @Override
         public void onUserSetupChanged() {
-            final boolean userSetup = mDeviceProvisionedController.isUserSetup(
-                    mDeviceProvisionedController.getCurrentUser());
-            Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for user "
-                    + mDeviceProvisionedController.getCurrentUser());
+            final boolean userSetup = mDeviceProvisionedController.isCurrentUserSetup();
+            Log.d(TAG, "mUserSetupObserver - DeviceProvisionedListener called for "
+                    + "current user");
             if (MULTIUSER_DEBUG) {
                 Log.d(TAG, String.format("User setup changed: userSetup=%s mUserSetup=%s",
                         userSetup, mUserSetup));
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
index 5bfb236..6ae8331 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProvider.kt
@@ -25,6 +25,7 @@
 import android.view.View.LAYOUT_DIRECTION_RTL
 import android.view.WindowMetrics
 import androidx.annotation.VisibleForTesting
+import com.android.internal.policy.SystemBarUtils
 import com.android.systemui.Dumpable
 import com.android.systemui.R
 import com.android.systemui.dagger.SysUISingleton
@@ -155,18 +156,21 @@
         val isRtl = rotatedResources.configuration.layoutDirection == LAYOUT_DIRECTION_RTL
         val roundedCornerPadding = rotatedResources
                 .getDimensionPixelSize(R.dimen.rounded_corner_content_padding)
-        val minDotWidth = if (isPrivacyDotEnabled)
+        val minDotPadding = if (isPrivacyDotEnabled)
                 rotatedResources.getDimensionPixelSize(R.dimen.ongoing_appops_dot_min_padding)
             else 0
+        val dotWidth = if (isPrivacyDotEnabled)
+                rotatedResources.getDimensionPixelSize(R.dimen.ongoing_appops_dot_diameter)
+            else 0
 
         val minLeft: Int
         val minRight: Int
         if (isRtl) {
-            minLeft = max(minDotWidth, roundedCornerPadding)
+            minLeft = max(minDotPadding, roundedCornerPadding)
             minRight = roundedCornerPadding
         } else {
             minLeft = roundedCornerPadding
-            minRight = max(minDotWidth, roundedCornerPadding)
+            minRight = max(minDotPadding, roundedCornerPadding)
         }
 
         return calculateInsetsForRotationWithRotatedResources(
@@ -174,9 +178,11 @@
                 targetRotation,
                 dc,
                 context.resources.configuration.windowConfiguration.maxBounds,
-                rotatedResources.getDimensionPixelSize(R.dimen.status_bar_height),
+                SystemBarUtils.getStatusBarHeight(context),
                 minLeft,
-                minRight)
+                minRight,
+                isRtl,
+                dotWidth)
     }
 
     fun getStatusBarPaddingTop(@Rotation rotation: Int? = null): Int {
@@ -245,10 +251,13 @@
  *
  * @param currentRotation current device rotation
  * @param targetRotation rotation for which to calculate the status bar content rect
- * @param displayCutout [DisplayCutout] for the curren display. possibly null
+ * @param displayCutout [DisplayCutout] for the current display. possibly null
  * @param windowMetrics [WindowMetrics] for the current window
  * @param statusBarHeight height of the status bar for the target rotation
- * @param roundedCornerPadding from rounded_corner_content_padding
+ * @param minLeft the minimum padding to enforce on the left
+ * @param minRight the minimum padding to enforce on the right
+ * @param isRtl current layout direction is Right-To-Left or not
+ * @param dotWidth privacy dot image width (0 if privacy dot is disabled)
  *
  * @see [RotationUtils#getResourcesForRotation]
  */
@@ -259,7 +268,9 @@
     maxBounds: Rect,
     statusBarHeight: Int,
     minLeft: Int,
-    minRight: Int
+    minRight: Int,
+    isRtl: Boolean,
+    dotWidth: Int
 ): Rect {
     /*
     TODO: Check if this is ever used for devices with no rounded corners
@@ -278,6 +289,8 @@
             maxBounds.height(),
             minLeft,
             minRight,
+            isRtl,
+            dotWidth,
             targetRotation,
             currentRotation)
 
@@ -295,6 +308,8 @@
  * @param cHeight display height in our current rotation
  * @param minLeft the minimum padding to enforce on the left
  * @param minRight the minimum padding to enforce on the right
+ * @param isRtl current layout direction is Right-To-Left or not
+ * @param dotWidth privacy dot image width (0 if privacy dot is disabled)
  * @param targetRotation the rotation for which to calculate margins
  * @param currentRotation the rotation from which the display cutout was generated
  *
@@ -310,6 +325,8 @@
     cHeight: Int,
     minLeft: Int,
     minRight: Int,
+    isRtl: Boolean,
+    dotWidth: Int,
     @Rotation targetRotation: Int,
     @Rotation currentRotation: Int
 ): Rect {
@@ -344,13 +361,16 @@
         }
 
         if (cutoutRect.touchesLeftEdge(relativeRotation, cWidth, cHeight)) {
-
-            val l = max(minLeft, cutoutRect.logicalWidth(relativeRotation))
-            leftMargin = max(l, leftMargin)
+            var logicalWidth = cutoutRect.logicalWidth(relativeRotation)
+            if (isRtl) logicalWidth += dotWidth
+            leftMargin = max(logicalWidth, leftMargin)
         } else if (cutoutRect.touchesRightEdge(relativeRotation, cWidth, cHeight)) {
-            val logicalWidth = cutoutRect.logicalWidth(relativeRotation)
-            rightMargin = max(minRight, logicalWidth)
+            var logicalWidth = cutoutRect.logicalWidth(relativeRotation)
+            if (!isRtl) logicalWidth += dotWidth
+            rightMargin = max(rightMargin, logicalWidth)
         }
+        // TODO(b/203626889): Fix the scenario when config_mainBuiltInDisplayCutoutRectApproximation
+        //                    is very close to but not directly touch edges.
     }
 
     return Rect(leftMargin, 0, logicalDisplayWidth - rightMargin, sbHeight)
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 07489a9..cac66a3 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -51,7 +51,6 @@
 import com.android.systemui.DejankUtils;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dock.DockManager;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.navigationbar.NavigationBarView;
 import com.android.systemui.navigationbar.NavigationModeController;
@@ -70,7 +69,6 @@
 import java.io.PrintWriter;
 import java.util.ArrayList;
 import java.util.Objects;
-import java.util.Optional;
 
 import javax.inject.Inject;
 
@@ -109,7 +107,6 @@
     private final ConfigurationController mConfigurationController;
     private final NavigationModeController mNavigationModeController;
     private final NotificationShadeWindowController mNotificationShadeWindowController;
-    private final Optional<FaceAuthScreenBrightnessController> mFaceAuthScreenBrightnessController;
     private final KeyguardBouncer.Factory mKeyguardBouncerFactory;
     private final WakefulnessLifecycle mWakefulnessLifecycle;
     private final UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
@@ -242,7 +239,6 @@
             DockManager dockManager,
             NotificationShadeWindowController notificationShadeWindowController,
             KeyguardStateController keyguardStateController,
-            Optional<FaceAuthScreenBrightnessController> faceAuthScreenBrightnessController,
             NotificationMediaManager notificationMediaManager,
             KeyguardBouncer.Factory keyguardBouncerFactory,
             WakefulnessLifecycle wakefulnessLifecycle,
@@ -260,7 +256,6 @@
         mKeyguardUpdateManager = keyguardUpdateMonitor;
         mStatusBarStateController = sysuiStatusBarStateController;
         mDockManager = dockManager;
-        mFaceAuthScreenBrightnessController = faceAuthScreenBrightnessController;
         mKeyguardBouncerFactory = keyguardBouncerFactory;
         mWakefulnessLifecycle = wakefulnessLifecycle;
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
@@ -285,11 +280,6 @@
         mNotificationContainer = notificationContainer;
         mKeyguardMessageAreaController = mKeyguardMessageAreaFactory.create(
             KeyguardMessageArea.findSecurityMessageDisplay(container));
-        mFaceAuthScreenBrightnessController.ifPresent((it) -> {
-            View overlay = new View(mContext);
-            container.addView(overlay);
-            it.attach(overlay);
-        });
 
         registerListeners();
     }
@@ -917,7 +907,7 @@
 
     @Override
     public boolean bouncerIsOrWillBeShowing() {
-        return mBouncer.isShowing() || mBouncer.getShowingSoon();
+        return isBouncerShowing() || mBouncer.getShowingSoon();
     }
 
     public boolean isFullscreenBouncer() {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
index 8af03aa..8ef186c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarMoveFromCenterAnimationController.kt
@@ -20,43 +20,54 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator
 import com.android.systemui.shared.animation.UnfoldMoveFromCenterAnimator.ViewCenterProvider
-import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UNFOLD_STATUS_BAR
 import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
 import javax.inject.Inject
+import javax.inject.Named
 
 @SysUISingleton
 class StatusBarMoveFromCenterAnimationController @Inject constructor(
-    private val unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider,
-    private val windowManager: WindowManager
+    @Named(UNFOLD_STATUS_BAR) private val progressProvider: ScopedUnfoldTransitionProgressProvider,
+    private val windowManager: WindowManager,
 ) {
 
-    private lateinit var moveFromCenterAnimator: UnfoldMoveFromCenterAnimator
+    private val transitionListener = TransitionListener()
+    private var moveFromCenterAnimator: UnfoldMoveFromCenterAnimator? = null
 
-    fun init(viewsToAnimate: Array<View>, viewCenterProvider: ViewCenterProvider) {
+    fun onViewsReady(viewsToAnimate: Array<View>, viewCenterProvider: ViewCenterProvider) {
         moveFromCenterAnimator = UnfoldMoveFromCenterAnimator(windowManager,
             viewCenterProvider = viewCenterProvider)
 
-        unfoldTransitionProgressProvider.addCallback(object : TransitionProgressListener {
-            override fun onTransitionStarted() {
-                moveFromCenterAnimator.updateDisplayProperties()
+        moveFromCenterAnimator?.updateDisplayProperties()
 
-                viewsToAnimate.forEach {
-                    moveFromCenterAnimator.registerViewForAnimation(it)
-                }
-            }
+        viewsToAnimate.forEach {
+            moveFromCenterAnimator?.registerViewForAnimation(it)
+        }
 
-            override fun onTransitionFinished() {
-                moveFromCenterAnimator.onTransitionFinished()
-                moveFromCenterAnimator.clearRegisteredViews()
-            }
+        progressProvider.addCallback(transitionListener)
+    }
 
-            override fun onTransitionProgress(progress: Float) {
-                moveFromCenterAnimator.onTransitionProgress(progress)
-            }
-        })
+    fun onViewDetached() {
+        progressProvider.removeCallback(transitionListener)
+        moveFromCenterAnimator?.clearRegisteredViews()
+        moveFromCenterAnimator = null
     }
 
     fun onStatusBarWidthChanged() {
-        moveFromCenterAnimator.updateViewPositions()
+        moveFromCenterAnimator?.updateDisplayProperties()
+        moveFromCenterAnimator?.updateViewPositions()
+    }
+
+    private inner class TransitionListener : TransitionProgressListener {
+        override fun onTransitionProgress(progress: Float) {
+            moveFromCenterAnimator?.onTransitionProgress(progress)
+        }
+
+        override fun onTransitionFinished() {
+            // Reset translations when transition is stopped/cancelled
+            // (e.g. the transition could be cancelled mid-way when rotating the screen)
+            moveFromCenterAnimator?.onTransitionProgress(1f)
+        }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
index c655964..cf9b2c6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenter.java
@@ -17,9 +17,7 @@
 import static com.android.systemui.statusbar.phone.StatusBar.CLOSE_PANEL_WHEN_EMPTIED;
 import static com.android.systemui.statusbar.phone.StatusBar.DEBUG;
 import static com.android.systemui.statusbar.phone.StatusBar.MULTIUSER_DEBUG;
-import static com.android.systemui.statusbar.phone.StatusBar.SPEW;
 
-import android.annotation.Nullable;
 import android.app.KeyguardManager;
 import android.content.Context;
 import android.os.RemoteException;
@@ -36,7 +34,6 @@
 
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
 import com.android.internal.statusbar.IStatusBarService;
-import com.android.internal.statusbar.NotificationVisibility;
 import com.android.internal.widget.MessagingGroup;
 import com.android.internal.widget.MessagingMessage;
 import com.android.keyguard.KeyguardUpdateMonitor;
@@ -44,6 +41,7 @@
 import com.android.systemui.ForegroundServiceNotificationListener;
 import com.android.systemui.InitController;
 import com.android.systemui.R;
+import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
 import com.android.systemui.statusbar.CommandQueue;
@@ -59,10 +57,10 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.AboveShelfObserver;
 import com.android.systemui.statusbar.notification.DynamicPrivacyController;
-import com.android.systemui.statusbar.notification.NotificationEntryListener;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.inflation.NotificationRowBinderImpl;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -88,6 +86,7 @@
     private final NotificationViewHierarchyManager mViewHierarchyManager;
     private final NotificationLockscreenUserManager mLockscreenUserManager;
     private final SysuiStatusBarStateController mStatusBarStateController;
+    private final NotifShadeEventSource mNotifShadeEventSource;
     private final NotificationEntryManager mEntryManager;
     private final NotificationMediaManager mMediaManager;
     private final NotificationGutsManager mGutsManager;
@@ -100,6 +99,7 @@
     private final DozeScrimController mDozeScrimController;
     private final ScrimController mScrimController;
     private final KeyguardIndicationController mKeyguardIndicationController;
+    private final FeatureFlags mFeatureFlags;
     private final StatusBar mStatusBar;
     private final ShadeController mShadeController;
     private final LockscreenShadeTransitionController mShadeTransitionController;
@@ -127,6 +127,7 @@
             DynamicPrivacyController dynamicPrivacyController,
             KeyguardStateController keyguardStateController,
             KeyguardIndicationController keyguardIndicationController,
+            FeatureFlags featureFlags,
             StatusBar statusBar,
             ShadeController shadeController,
             LockscreenShadeTransitionController shadeTransitionController,
@@ -134,6 +135,7 @@
             NotificationViewHierarchyManager notificationViewHierarchyManager,
             NotificationLockscreenUserManager lockscreenUserManager,
             SysuiStatusBarStateController sysuiStatusBarStateController,
+            NotifShadeEventSource notifShadeEventSource,
             NotificationEntryManager notificationEntryManager,
             NotificationMediaManager notificationMediaManager,
             NotificationGutsManager notificationGutsManager,
@@ -148,6 +150,7 @@
         mHeadsUpManager = headsUp;
         mDynamicPrivacyController = dynamicPrivacyController;
         mKeyguardIndicationController = keyguardIndicationController;
+        mFeatureFlags = featureFlags;
         // TODO: use KeyguardStateController#isOccluded to remove this dependency
         mStatusBar = statusBar;
         mShadeController = shadeController;
@@ -156,6 +159,7 @@
         mViewHierarchyManager = notificationViewHierarchyManager;
         mLockscreenUserManager = lockscreenUserManager;
         mStatusBarStateController = sysuiStatusBarStateController;
+        mNotifShadeEventSource = notifShadeEventSource;
         mEntryManager = notificationEntryManager;
         mMediaManager = notificationMediaManager;
         mGutsManager = notificationGutsManager;
@@ -186,30 +190,18 @@
                 mNotificationPanel.createRemoteInputDelegate());
 
         initController.addPostInitTask(() -> {
-            NotificationEntryListener notificationEntryListener = new NotificationEntryListener() {
-                @Override
-                public void onEntryRemoved(
-                        @Nullable NotificationEntry entry,
-                        NotificationVisibility visibility,
-                        boolean removedByUser,
-                        int reason) {
-                    StatusBarNotificationPresenter.this.onNotificationRemoved(
-                            entry.getKey(), entry.getSbn(), reason);
-                    if (removedByUser) {
-                        maybeEndAmbientPulse();
-                    }
-                }
-            };
-
             mKeyguardIndicationController.init();
             mViewHierarchyManager.setUpWithPresenter(this,
                     stackScrollerController.getNotificationListContainer());
-            mEntryManager.setUpWithPresenter(this);
-            mEntryManager.addNotificationEntryListener(notificationEntryListener);
-            mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
-            mEntryManager.addNotificationLifetimeExtender(mGutsManager);
-            mEntryManager.addNotificationLifetimeExtenders(
-                    remoteInputManager.getLifetimeExtenders());
+            mNotifShadeEventSource.setShadeEmptiedCallback(this::maybeClosePanelForShadeEmptied);
+            mNotifShadeEventSource.setNotifRemovedByUserCallback(this::maybeEndAmbientPulse);
+            if (!mFeatureFlags.isNewNotifPipelineRenderingEnabled()) {
+                mEntryManager.setUpWithPresenter(this);
+                mEntryManager.addNotificationLifetimeExtender(mHeadsUpManager);
+                mEntryManager.addNotificationLifetimeExtender(mGutsManager);
+                mEntryManager.addNotificationLifetimeExtenders(
+                        remoteInputManager.getLifetimeExtenders());
+            }
             notificationInterruptStateProvider.addSuppressor(mInterruptSuppressor);
             mLockscreenUserManager.setUpWithPresenter(this);
             mMediaManager.setUpWithPresenter(this);
@@ -226,8 +218,21 @@
         configurationController.addCallback(this);
     }
 
+    /** Called when the shade has been emptied to attempt to close the shade */
+    private void maybeClosePanelForShadeEmptied() {
+        if (CLOSE_PANEL_WHEN_EMPTIED
+                && !mNotificationPanel.isTracking()
+                && !mNotificationPanel.isQsExpanded()
+                && mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
+                && !isCollapsing()) {
+            mStatusBarStateController.setState(StatusBarState.KEYGUARD);
+        }
+    }
+
     @Override
     public void onDensityOrFontScaleChanged() {
+        // TODO(b/145659174): Remove legacy pipeline code
+        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
         MessagingMessage.dropCache();
         MessagingGroup.dropCache();
         if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
@@ -239,8 +244,10 @@
 
     @Override
     public void onUiModeChanged() {
+        // TODO(b/145659174): Remove legacy pipeline code
+        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
         if (!mKeyguardUpdateMonitor.isSwitchingUser()) {
-            updateNotificationOnUiModeChanged();
+            updateNotificationsOnUiModeChanged();
         } else {
             mDispatchUiModeChangeOnUserSwitched = true;
         }
@@ -251,7 +258,9 @@
         onDensityOrFontScaleChanged();
     }
 
-    private void updateNotificationOnUiModeChanged() {
+    private void updateNotificationsOnUiModeChanged() {
+        // TODO(b/145659174): Remove legacy pipeline code
+        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
         List<NotificationEntry> userNotifications =
                 mEntryManager.getActiveNotificationsForCurrentUser();
         for (int i = 0; i < userNotifications.size(); i++) {
@@ -264,6 +273,8 @@
     }
 
     private void updateNotificationsOnDensityOrFontScaleChanged() {
+        // TODO(b/145659174): Remove legacy pipeline code
+        if (mFeatureFlags.isNewNotifPipelineRenderingEnabled()) return;
         List<NotificationEntry> userNotifications =
                 mEntryManager.getActiveNotificationsForCurrentUser();
         for (int i = 0; i < userNotifications.size(); i++) {
@@ -276,6 +287,7 @@
         }
     }
 
+
     @Override
     public boolean isCollapsing() {
         return mNotificationPanel.isCollapsing()
@@ -308,21 +320,6 @@
         mNotificationPanel.updateNotificationViews(reason);
     }
 
-    private void onNotificationRemoved(String key, StatusBarNotification old, int reason) {
-        if (SPEW) Log.d(TAG, "removeNotification key=" + key + " old=" + old);
-
-        if (old != null && CLOSE_PANEL_WHEN_EMPTIED && !hasActiveNotifications()
-                && !mNotificationPanel.isTracking() && !mNotificationPanel.isQsExpanded()
-                && mStatusBarStateController.getState() == StatusBarState.SHADE_LOCKED
-                        && !isCollapsing()) {
-                mStatusBarStateController.setState(StatusBarState.KEYGUARD);
-        }
-    }
-
-    public boolean hasActiveNotifications() {
-        return mEntryManager.hasActiveNotifications();
-    }
-
     @Override
     public void onUserSwitched(int newUserId) {
         // Begin old BaseStatusBar.userSwitched
@@ -335,7 +332,7 @@
             mReinflateNotificationsOnUserSwitched = false;
         }
         if (mDispatchUiModeChangeOnUserSwitched) {
-            updateNotificationOnUiModeChanged();
+            updateNotificationsOnUiModeChanged();
             mDispatchUiModeChangeOnUserSwitched = false;
         }
         updateNotificationViews("user switched");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
index eb405e9..b742394 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarTouchableRegionManager.java
@@ -29,6 +29,7 @@
 import android.view.ViewTreeObserver.OnComputeInternalInsetsListener;
 import android.view.WindowInsets;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.Dumpable;
 import com.android.systemui.R;
 import com.android.systemui.ScreenDecorations;
@@ -172,8 +173,7 @@
         Resources resources = mContext.getResources();
         mDisplayCutoutTouchableRegionSize = resources.getDimensionPixelSize(
                 com.android.internal.R.dimen.display_cutout_touchable_region_size);
-        mStatusBarHeight =
-                resources.getDimensionPixelSize(com.android.internal.R.dimen.status_bar_height);
+        mStatusBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
     }
 
     /**
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
index 235a8e8..9d2dbc1 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowController.java
@@ -40,6 +40,7 @@
 import android.view.ViewGroup;
 import android.view.WindowManager;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
@@ -86,8 +87,7 @@
         mResources = resources;
 
         if (mBarHeight < 0) {
-            mBarHeight = mResources.getDimensionPixelSize(
-                    com.android.internal.R.dimen.status_bar_height);
+            mBarHeight = SystemBarUtils.getStatusBarHeight(mContext);
         }
     }
 
@@ -96,12 +96,11 @@
     }
 
     /**
-     * Rereads the status_bar_height from configuration and reapplys the current state if the height
+     * Rereads the status bar height and reapplys the current state if the height
      * is different.
      */
     public void refreshStatusBarHeight() {
-        int heightFromConfig = mResources.getDimensionPixelSize(
-                com.android.internal.R.dimen.status_bar_height);
+        int heightFromConfig = SystemBarUtils.getStatusBarHeight(mContext);
 
         if (mBarHeight != heightFromConfig) {
             mBarHeight = heightFromConfig;
@@ -139,29 +138,20 @@
     private WindowManager.LayoutParams getBarLayoutParamsForRotation(int rotation) {
         int height = mBarHeight;
         if (INSETS_LAYOUT_GENERALIZATION) {
-            Rect displayBounds = mWindowManager.getCurrentWindowMetrics().getBounds();
-            int defaultAndUpsideDownHeight;
-            int theOtherHeight;
-            if (displayBounds.width() > displayBounds.height()) {
-                defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height_landscape);
-                theOtherHeight = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height_portrait);
-            } else {
-                defaultAndUpsideDownHeight = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height_portrait);
-                theOtherHeight = mContext.getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height_landscape);
-            }
             switch (rotation) {
                 case ROTATION_UNDEFINED:
                 case Surface.ROTATION_0:
                 case Surface.ROTATION_180:
-                    height = defaultAndUpsideDownHeight;
+                    height = SystemBarUtils.getStatusBarHeightForRotation(
+                            mContext, Surface.ROTATION_0);
                     break;
                 case Surface.ROTATION_90:
+                    height = SystemBarUtils.getStatusBarHeightForRotation(
+                            mContext, Surface.ROTATION_90);
+                    break;
                 case Surface.ROTATION_270:
-                    height = theOtherHeight;
+                    height = SystemBarUtils.getStatusBarHeightForRotation(
+                            mContext, Surface.ROTATION_270);
                     break;
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
index 9415d50..18aa689 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -22,7 +22,11 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.os.Bundle;
+import android.os.SystemProperties;
 import android.os.UserHandle;
+import android.util.TypedValue;
+import android.view.ViewGroup;
 import android.view.Window;
 import android.view.WindowInsets.Type;
 import android.view.WindowManager;
@@ -45,6 +49,10 @@
  * and dismisses itself when it receives the broadcast.
  */
 public class SystemUIDialog extends AlertDialog implements ListenableDialog {
+    // TODO(b/203389579): Remove this once the dialog width on large screens has been agreed on.
+    private static final String FLAG_TABLET_DIALOG_WIDTH =
+            "persist.systemui.flag_tablet_dialog_width";
+
     private final Context mContext;
     private final DismissReceiver mDismissReceiver;
     private final Set<DialogListener> mDialogListeners = new LinkedHashSet<>();
@@ -66,6 +74,41 @@
     }
 
     @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+
+        // Set the dialog window size.
+        getWindow().setLayout(getDialogWidth(), ViewGroup.LayoutParams.WRAP_CONTENT);
+    }
+
+    private int getDialogWidth() {
+        boolean isOnTablet =
+                mContext.getResources().getConfiguration().smallestScreenWidthDp >= 600;
+        if (!isOnTablet) {
+            return ViewGroup.LayoutParams.MATCH_PARENT;
+        }
+
+        int flagValue = SystemProperties.getInt(FLAG_TABLET_DIALOG_WIDTH, 0);
+        if (flagValue == -1) {
+            // The width of bottom sheets (624dp).
+            return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 624,
+                    mContext.getResources().getDisplayMetrics()));
+        } else if (flagValue == -2) {
+            // The suggested small width for all dialogs (348dp)
+            return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 348,
+                    mContext.getResources().getDisplayMetrics()));
+        } else if (flagValue > 0) {
+            // Any given width.
+            return Math.round(
+                    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, flagValue,
+                            mContext.getResources().getDisplayMetrics()));
+        } else {
+            // By default we use the same width as the notification shade in portrait mode (504dp).
+            return mContext.getResources().getDimensionPixelSize(R.dimen.large_dialog_width);
+        }
+    }
+
+    @Override
     protected void onStart() {
         super.onStart();
         mDismissReceiver.register();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
index f3f3325..cddde64 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationController.kt
@@ -145,22 +145,26 @@
                 .setDuration(duration.toLong())
                 .setInterpolator(Interpolators.FAST_OUT_SLOW_IN)
                 .alpha(1f)
-                .withEndAction {
-                    aodUiAnimationPlaying = false
+                .setListener(object : AnimatorListenerAdapter() {
+                    override fun onAnimationEnd(animation: Animator?) {
+                        aodUiAnimationPlaying = false
 
-                    // Lock the keyguard if it was waiting for the screen off animation to end.
-                    keyguardViewMediatorLazy.get().maybeHandlePendingLock()
+                        // Lock the keyguard if it was waiting for the screen off animation to end.
+                        keyguardViewMediatorLazy.get().maybeHandlePendingLock()
 
-                    // Tell the StatusBar to become keyguard for real - we waited on that since it
-                    // is slow and would have caused the animation to jank.
-                    statusBar.updateIsKeyguard()
+                        // Tell the StatusBar to become keyguard for real - we waited on that since
+                        // it is slow and would have caused the animation to jank.
+                        statusBar.updateIsKeyguard()
 
-                    // Run the callback given to us by the KeyguardVisibilityHelper.
-                    after.run()
+                        // Run the callback given to us by the KeyguardVisibilityHelper.
+                        after.run()
 
-                    // Done going to sleep, reset this flag.
-                    decidedToAnimateGoingToSleep = null
-                }
+                        // Done going to sleep, reset this flag.
+                        decidedToAnimateGoingToSleep = null
+                        // We need to unset the listener. These are persistent for future animators
+                        keyguardView.animate().setListener(null)
+                    }
+                })
                 .start()
     }
 
@@ -226,6 +230,12 @@
             return false
         }
 
+        // If animations are disabled system-wide, don't play this one either.
+        if (Settings.Global.getString(
+                context.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE) == "0") {
+            return false
+        }
+
         // We only play the unlocked screen off animation if we are... unlocked.
         if (statusBarStateControllerImpl.state != StatusBarState.SHADE) {
             return false
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
index 5689707..959c673 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.java
@@ -48,7 +48,7 @@
 import com.android.systemui.plugins.FalsingManager;
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -68,6 +68,7 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.NotificationWakeUpCoordinator;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
@@ -88,6 +89,7 @@
 import com.android.systemui.statusbar.phone.LockscreenWallpaper;
 import com.android.systemui.statusbar.phone.NotificationIconAreaController;
 import com.android.systemui.statusbar.phone.PhoneStatusBarPolicy;
+import com.android.systemui.statusbar.phone.PhoneStatusBarViewController;
 import com.android.systemui.statusbar.phone.ScrimController;
 import com.android.systemui.statusbar.phone.ShadeController;
 import com.android.systemui.statusbar.phone.StatusBar;
@@ -111,6 +113,7 @@
 import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
 import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
 import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 import com.android.systemui.util.concurrency.MessageRouter;
@@ -155,6 +158,7 @@
             FalsingManager falsingManager,
             FalsingCollector falsingCollector,
             BroadcastDispatcher broadcastDispatcher,
+            NotifShadeEventSource notifShadeEventSource,
             NotificationEntryManager notificationEntryManager,
             NotificationGutsManager notificationGutsManager,
             NotificationLogger notificationLogger,
@@ -211,15 +215,17 @@
             ExtensionController extensionController,
             UserInfoControllerImpl userInfoControllerImpl,
             OperatorNameViewController.Factory operatorNameViewControllerFactory,
+            PhoneStatusBarViewController.Factory phoneStatusBarViewControllerFactory,
             PhoneStatusBarPolicy phoneStatusBarPolicy,
             KeyguardIndicationController keyguardIndicationController,
             DemoModeController demoModeController,
             Lazy<NotificationShadeDepthController> notificationShadeDepthController,
             StatusBarTouchableRegionManager statusBarTouchableRegionManager,
             NotificationIconAreaController notificationIconAreaController,
-            BrightnessSlider.Factory brightnessSliderFactory,
+            BrightnessSliderController.Factory brightnessSliderFactory,
             UnfoldTransitionConfig unfoldTransitionConfig,
             Lazy<UnfoldLightRevealOverlayAnimation> unfoldLightRevealOverlayAnimation,
+            Lazy<NaturalRotationUnfoldProgressProvider> naturalRotationUnfoldProgressProvider,
             Lazy<UnfoldTransitionWallpaperController> unfoldTransitionWallpaperController,
             Lazy<StatusBarMoveFromCenterAnimationController> statusBarMoveFromCenterAnimation,
             WallpaperController wallpaperController,
@@ -256,6 +262,7 @@
                 falsingManager,
                 falsingCollector,
                 broadcastDispatcher,
+                notifShadeEventSource,
                 notificationEntryManager,
                 notificationGutsManager,
                 notificationLogger,
@@ -311,6 +318,7 @@
                 extensionController,
                 userInfoControllerImpl,
                 operatorNameViewControllerFactory,
+                phoneStatusBarViewControllerFactory,
                 phoneStatusBarPolicy,
                 keyguardIndicationController,
                 demoModeController,
@@ -321,7 +329,7 @@
                 unfoldTransitionConfig,
                 unfoldLightRevealOverlayAnimation,
                 unfoldTransitionWallpaperController,
-                statusBarMoveFromCenterAnimation,
+                naturalRotationUnfoldProgressProvider,
                 wallpaperController,
                 ongoingCallController,
                 animationScheduler,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
index 2791678..9de0c46 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarViewModule.java
@@ -17,7 +17,6 @@
 package com.android.systemui.statusbar.phone.dagger;
 
 import android.annotation.Nullable;
-import android.content.Context;
 import android.view.LayoutInflater;
 import android.view.View;
 
@@ -33,7 +32,6 @@
 import com.android.systemui.statusbar.phone.NotificationShadeWindowView;
 import com.android.systemui.statusbar.phone.NotificationsQuickSettingsContainer;
 import com.android.systemui.statusbar.phone.TapAgainView;
-import com.android.systemui.util.InjectionInflationController;
 
 import javax.inject.Named;
 
@@ -49,12 +47,9 @@
     @Provides
     @StatusBarComponent.StatusBarScope
     public static NotificationShadeWindowView providesNotificationShadeWindowView(
-            InjectionInflationController injectionInflationController,
-            Context context) {
+            LayoutInflater layoutInflater) {
         NotificationShadeWindowView notificationShadeWindowView = (NotificationShadeWindowView)
-                injectionInflationController.injectable(
-                        LayoutInflater.from(context)).inflate(R.layout.super_notification_shade,
-                        /* root= */ null);
+                layoutInflater.inflate(R.layout.super_notification_shade, /* root= */ null);
         if (notificationShadeWindowView == null) {
             throw new IllegalStateException(
                     "R.layout.super_notification_shade could not be properly inflated");
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
index 1e52511..5bd20ff 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/BrightnessMirrorController.java
@@ -26,7 +26,7 @@
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.settings.brightness.ToggleSlider;
 import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -46,8 +46,8 @@
     private final NotificationPanelViewController mNotificationPanel;
     private final NotificationShadeDepthController mDepthController;
     private final ArraySet<BrightnessMirrorListener> mBrightnessMirrorListeners = new ArraySet<>();
-    private final BrightnessSlider.Factory mToggleSliderFactory;
-    private BrightnessSlider mToggleSliderController;
+    private final BrightnessSliderController.Factory mToggleSliderFactory;
+    private BrightnessSliderController mToggleSliderController;
     private final int[] mInt2Cache = new int[2];
     private FrameLayout mBrightnessMirror;
     private int mBrightnessMirrorBackgroundPadding;
@@ -56,7 +56,7 @@
     public BrightnessMirrorController(NotificationShadeWindowView statusBarWindow,
             NotificationPanelViewController notificationPanelViewController,
             NotificationShadeDepthController notificationShadeDepthController,
-            BrightnessSlider.Factory factory,
+            BrightnessSliderController.Factory factory,
             @NonNull Consumer<Boolean> visibilityCallback) {
         mStatusBarWindow = statusBarWindow;
         mToggleSliderFactory = factory;
@@ -135,9 +135,10 @@
         reinflate();
     }
 
-    private BrightnessSlider setMirrorLayout() {
+    private BrightnessSliderController setMirrorLayout() {
         Context context = mBrightnessMirror.getContext();
-        BrightnessSlider controller = mToggleSliderFactory.create(context, mBrightnessMirror);
+        BrightnessSliderController controller = mToggleSliderFactory.create(context,
+                mBrightnessMirror);
         controller.init();
 
         mBrightnessMirror.addView(controller.getRootView(), ViewGroup.LayoutParams.MATCH_PARENT,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
index 7b4c35a..3944c8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedController.java
@@ -14,23 +14,60 @@
 
 package com.android.systemui.statusbar.policy;
 
+import android.provider.Settings;
+
 import com.android.systemui.statusbar.policy.DeviceProvisionedController.DeviceProvisionedListener;
 
+/**
+ * Controller to cache in process the state of the device provisioning.
+ * <p>
+ * This controller keeps track of the values of device provisioning and user setup complete
+ */
 public interface DeviceProvisionedController extends CallbackController<DeviceProvisionedListener> {
 
+    /**
+     * @return whether the device is provisioned
+     * @see Settings.Global#DEVICE_PROVISIONED
+     */
     boolean isDeviceProvisioned();
-    boolean isUserSetup(int currentUser);
+
+    /**
+     * @deprecated use {@link com.android.systemui.settings.UserTracker}
+     */
+    @Deprecated
     int getCurrentUser();
 
-    default boolean isCurrentUserSetup() {
-        return isUserSetup(getCurrentUser());
-    }
+    /**
+     * @param user the user to query
+     * @return whether that user has completed the user setup
+     * @see Settings.Secure#USER_SETUP_COMPLETE
+     */
+    boolean isUserSetup(int user);
 
+    /**
+     * @see DeviceProvisionedController#isUserSetup
+     */
+    boolean isCurrentUserSetup();
+
+    /**
+     * Interface to provide calls when the values tracked change
+     */
     interface DeviceProvisionedListener {
+        /**
+         * Call when the device changes from not provisioned to provisioned
+         */
         default void onDeviceProvisionedChanged() { }
+
+        /**
+         * Call on user switched
+         */
         default void onUserSwitched() {
             onUserSetupChanged();
         }
+
+        /**
+         * Call when some user changes from not provisioned to provisioned
+         */
         default void onUserSetupChanged() { }
     }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
deleted file mode 100644
index 485b1b1..0000000
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.java
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * 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.statusbar.policy;
-
-import android.app.ActivityManager;
-import android.database.ContentObserver;
-import android.net.Uri;
-import android.os.Handler;
-import android.provider.Settings.Global;
-import android.provider.Settings.Secure;
-import android.util.Log;
-
-import androidx.annotation.NonNull;
-
-import com.android.systemui.broadcast.BroadcastDispatcher;
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.dagger.qualifiers.Main;
-import com.android.systemui.settings.CurrentUserTracker;
-import com.android.systemui.util.settings.GlobalSettings;
-import com.android.systemui.util.settings.SecureSettings;
-
-import java.util.ArrayList;
-
-import javax.inject.Inject;
-
-/**
- */
-@SysUISingleton
-public class DeviceProvisionedControllerImpl extends CurrentUserTracker implements
-        DeviceProvisionedController {
-
-    protected static final String TAG = DeviceProvisionedControllerImpl.class.getSimpleName();
-    protected final ArrayList<DeviceProvisionedListener> mListeners = new ArrayList<>();
-    private final GlobalSettings mGlobalSettings;
-    private final SecureSettings mSecureSettings;
-    private final Uri mDeviceProvisionedUri;
-    private final Uri mUserSetupUri;
-    protected final ContentObserver mSettingsObserver;
-
-    /**
-     */
-    @Inject
-    public DeviceProvisionedControllerImpl(@Main Handler mainHandler,
-            BroadcastDispatcher broadcastDispatcher, GlobalSettings globalSettings,
-            SecureSettings secureSettings) {
-        super(broadcastDispatcher);
-        mGlobalSettings = globalSettings;
-        mSecureSettings = secureSettings;
-        mDeviceProvisionedUri = mGlobalSettings.getUriFor(Global.DEVICE_PROVISIONED);
-        mUserSetupUri = mSecureSettings.getUriFor(Secure.USER_SETUP_COMPLETE);
-        mSettingsObserver = new ContentObserver(mainHandler) {
-            @Override
-            public void onChange(boolean selfChange, Uri uri, int flags) {
-                Log.d(TAG, "Setting change: " + uri);
-                if (mUserSetupUri.equals(uri)) {
-                    notifySetupChanged();
-                } else {
-                    notifyProvisionedChanged();
-                }
-            }
-        };
-    }
-
-    @Override
-    public boolean isDeviceProvisioned() {
-        return mGlobalSettings.getInt(Global.DEVICE_PROVISIONED, 0) != 0;
-    }
-
-    @Override
-    public boolean isUserSetup(int currentUser) {
-        return mSecureSettings.getIntForUser(Secure.USER_SETUP_COMPLETE, 0, currentUser) != 0;
-    }
-
-    @Override
-    public int getCurrentUser() {
-        return ActivityManager.getCurrentUser();
-    }
-
-    @Override
-    public void addCallback(@NonNull DeviceProvisionedListener listener) {
-        mListeners.add(listener);
-        if (mListeners.size() == 1) {
-            startListening(getCurrentUser());
-        }
-        listener.onUserSetupChanged();
-        listener.onDeviceProvisionedChanged();
-    }
-
-    @Override
-    public void removeCallback(@NonNull DeviceProvisionedListener listener) {
-        mListeners.remove(listener);
-        if (mListeners.size() == 0) {
-            stopListening();
-        }
-    }
-
-    protected void startListening(int user) {
-        mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
-                mSettingsObserver, 0);
-        mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
-                mSettingsObserver, user);
-        startTracking();
-    }
-
-    protected void stopListening() {
-        stopTracking();
-        mGlobalSettings.unregisterContentObserver(mSettingsObserver);
-    }
-
-    @Override
-    public void onUserSwitched(int newUserId) {
-        mGlobalSettings.unregisterContentObserver(mSettingsObserver);
-        mGlobalSettings.registerContentObserverForUser(mDeviceProvisionedUri, true,
-                mSettingsObserver, 0);
-        mSecureSettings.registerContentObserverForUser(mUserSetupUri, true,
-                mSettingsObserver, newUserId);
-        notifyUserChanged();
-    }
-
-    private void notifyUserChanged() {
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onUserSwitched();
-        }
-    }
-
-    private void notifySetupChanged() {
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onUserSetupChanged();
-        }
-    }
-
-    private void notifyProvisionedChanged() {
-        for (int i = mListeners.size() - 1; i >= 0; --i) {
-            mListeners.get(i).onDeviceProvisionedChanged();
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
new file mode 100644
index 0000000..acc1214
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImpl.kt
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy
+
+import android.content.Context
+import android.content.pm.UserInfo
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Handler
+import android.os.HandlerExecutor
+import android.os.UserHandle
+import android.provider.Settings
+import android.util.ArraySet
+import android.util.SparseBooleanArray
+import androidx.annotation.GuardedBy
+import androidx.annotation.WorkerThread
+import com.android.systemui.Dumpable
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.dagger.qualifiers.Background
+import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.settings.GlobalSettings
+import com.android.systemui.util.settings.SecureSettings
+import java.io.FileDescriptor
+import java.io.PrintWriter
+import java.util.concurrent.Executor
+import java.util.concurrent.atomic.AtomicBoolean
+import javax.inject.Inject
+
+@SysUISingleton
+open class DeviceProvisionedControllerImpl @Inject constructor(
+    private val secureSettings: SecureSettings,
+    private val globalSettings: GlobalSettings,
+    private val userTracker: UserTracker,
+    private val dumpManager: DumpManager,
+    @Background private val backgroundHandler: Handler,
+    @Main private val mainExecutor: Executor
+) : DeviceProvisionedController,
+    DeviceProvisionedController.DeviceProvisionedListener,
+    Dumpable {
+
+    companion object {
+        private const val ALL_USERS = -1
+        private const val NO_USERS = -2
+        protected const val TAG = "DeviceProvisionedControllerImpl"
+    }
+
+    private val deviceProvisionedUri = globalSettings.getUriFor(Settings.Global.DEVICE_PROVISIONED)
+    private val userSetupUri = secureSettings.getUriFor(Settings.Secure.USER_SETUP_COMPLETE)
+
+    private val deviceProvisioned = AtomicBoolean(false)
+    @GuardedBy("lock")
+    private val userSetupComplete = SparseBooleanArray()
+    @GuardedBy("lock")
+    private val listeners = ArraySet<DeviceProvisionedController.DeviceProvisionedListener>()
+
+    private val lock = Any()
+
+    private val backgroundExecutor = HandlerExecutor(backgroundHandler)
+
+    private val initted = AtomicBoolean(false)
+
+    private val _currentUser: Int
+        get() = userTracker.userId
+
+    override fun getCurrentUser(): Int {
+        return _currentUser
+    }
+
+    private val observer = object : ContentObserver(backgroundHandler) {
+        override fun onChange(
+            selfChange: Boolean,
+            uris: MutableCollection<Uri>,
+            flags: Int,
+            userId: Int
+        ) {
+            val updateDeviceProvisioned = deviceProvisionedUri in uris
+            val updateUser = if (userSetupUri in uris) userId else NO_USERS
+            updateValues(updateDeviceProvisioned, updateUser)
+            if (updateDeviceProvisioned) {
+                onDeviceProvisionedChanged()
+            }
+            if (updateUser != NO_USERS) {
+                onUserSetupChanged()
+            }
+        }
+    }
+
+    private val userChangedCallback = object : UserTracker.Callback {
+        @WorkerThread
+        override fun onUserChanged(newUser: Int, userContext: Context) {
+            updateValues(updateDeviceProvisioned = false, updateUser = newUser)
+            onUserSwitched()
+        }
+
+        override fun onProfilesChanged(profiles: List<UserInfo>) {}
+    }
+
+    init {
+        userSetupComplete.put(currentUser, false)
+    }
+
+    /**
+     * Call to initialize values and register observers
+     */
+    open fun init() {
+        if (!initted.compareAndSet(false, true)) {
+            return
+        }
+        dumpManager.registerDumpable(this)
+        updateValues()
+        userTracker.addCallback(userChangedCallback, backgroundExecutor)
+        globalSettings.registerContentObserver(deviceProvisionedUri, observer)
+        secureSettings.registerContentObserverForUser(userSetupUri, observer, UserHandle.USER_ALL)
+    }
+
+    @WorkerThread
+    private fun updateValues(updateDeviceProvisioned: Boolean = true, updateUser: Int = ALL_USERS) {
+        if (updateDeviceProvisioned) {
+            deviceProvisioned
+                    .set(globalSettings.getInt(Settings.Global.DEVICE_PROVISIONED, 0) != 0)
+        }
+        synchronized(lock) {
+            if (updateUser == ALL_USERS) {
+                val N = userSetupComplete.size()
+                for (i in 0 until N) {
+                    val user = userSetupComplete.keyAt(i)
+                    val value = secureSettings
+                            .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
+                    userSetupComplete.put(user, value)
+                }
+            } else if (updateUser != NO_USERS) {
+                val value = secureSettings
+                        .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, updateUser) != 0
+                userSetupComplete.put(updateUser, value)
+            }
+        }
+    }
+
+    /**
+     * Adds a listener.
+     *
+     * The listener will not be called when this happens.
+     */
+    override fun addCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
+        synchronized(lock) {
+            listeners.add(listener)
+        }
+    }
+
+    override fun removeCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
+        synchronized(lock) {
+            listeners.remove(listener)
+        }
+    }
+
+    override fun isDeviceProvisioned(): Boolean {
+        return deviceProvisioned.get()
+    }
+
+    override fun isUserSetup(user: Int): Boolean {
+        val index = synchronized(lock) {
+            userSetupComplete.indexOfKey(user)
+        }
+        return if (index < 0) {
+            val value = secureSettings
+                    .getIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 0, user) != 0
+            synchronized(lock) {
+                userSetupComplete.put(user, value)
+            }
+            value
+        } else {
+            synchronized(lock) {
+                userSetupComplete.get(user, false)
+            }
+        }
+    }
+
+    override fun isCurrentUserSetup(): Boolean {
+        return isUserSetup(currentUser)
+    }
+
+    override fun onDeviceProvisionedChanged() {
+        dispatchChange(
+                DeviceProvisionedController.DeviceProvisionedListener::onDeviceProvisionedChanged
+        )
+    }
+
+    override fun onUserSetupChanged() {
+        dispatchChange(DeviceProvisionedController.DeviceProvisionedListener::onUserSetupChanged)
+    }
+
+    override fun onUserSwitched() {
+        dispatchChange(DeviceProvisionedController.DeviceProvisionedListener::onUserSwitched)
+    }
+
+    protected fun dispatchChange(
+        callback: DeviceProvisionedController.DeviceProvisionedListener.() -> Unit
+    ) {
+        val listenersCopy = synchronized(lock) {
+            ArrayList(listeners)
+        }
+        mainExecutor.execute {
+            listenersCopy.forEach(callback)
+        }
+    }
+
+    override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) {
+        pw.println("Device provisioned: ${deviceProvisioned.get()}")
+        synchronized(lock) {
+            pw.println("User setup complete: $userSetupComplete")
+            pw.println("Listeners: $listeners")
+        }
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
index a8097c4..e0b0dd36 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/HeadsUpManager.java
@@ -38,11 +38,10 @@
 import com.android.systemui.statusbar.AlertingNotificationManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.row.NotificationRowContentBinder.InflationFlag;
+import com.android.systemui.util.ListenerSet;
 
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.HashSet;
 
 /**
  * A manager which handles heads up notifications which is a special mode where
@@ -52,7 +51,7 @@
     private static final String TAG = "HeadsUpManager";
     private static final String SETTING_HEADS_UP_SNOOZE_LENGTH_MS = "heads_up_snooze_length_ms";
 
-    protected final HashSet<OnHeadsUpChangedListener> mListeners = new HashSet<>();
+    protected final ListenerSet<OnHeadsUpChangedListener> mListeners = new ListenerSet<>();
 
     protected final Context mContext;
 
@@ -118,7 +117,7 @@
      * Adds an OnHeadUpChangedListener to observe events.
      */
     public void addListener(@NonNull OnHeadsUpChangedListener listener) {
-        mListeners.add(listener);
+        mListeners.addIfAbsent(listener);
     }
 
     /**
@@ -158,7 +157,7 @@
                         NotificationPeekEvent.NOTIFICATION_PEEK, entry.getSbn().getUid(),
                         entry.getSbn().getPackageName(), entry.getSbn().getInstanceId());
             }
-            for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
+            for (OnHeadsUpChangedListener listener : mListeners) {
                 if (isPinned) {
                     listener.onHeadsUpPinned(entry);
                 } else {
@@ -178,7 +177,7 @@
         entry.setHeadsUp(true);
         setEntryPinned((HeadsUpEntry) alertEntry, shouldHeadsUpBecomePinned(entry));
         EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 1 /* visible */);
-        for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
+        for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpStateChanged(entry, true);
         }
     }
@@ -189,7 +188,7 @@
         entry.setHeadsUp(false);
         setEntryPinned((HeadsUpEntry) alertEntry, false /* isPinned */);
         EventLogTags.writeSysuiHeadsUpStatus(entry.getKey(), 0 /* visible */);
-        for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
+        for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpStateChanged(entry, false);
         }
     }
@@ -207,7 +206,7 @@
         if (mHasPinnedNotification) {
             MetricsLogger.count(mContext, "note_peek", 1);
         }
-        for (OnHeadsUpChangedListener listener : new ArrayList<>(mListeners)) {
+        for (OnHeadsUpChangedListener listener : mListeners) {
             listener.onHeadsUpPinnedModeChanged(hasPinnedNotification);
         }
     }
diff --git a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
index 8912448..923aff1 100644
--- a/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
+++ b/packages/SystemUI/src/com/android/systemui/tv/TvSystemUIModule.java
@@ -180,9 +180,13 @@
         return new Recents(context, recentsImplementation, commandQueue);
     }
 
-    @Binds
-    abstract DeviceProvisionedController bindDeviceProvisionedController(
-            DeviceProvisionedControllerImpl deviceProvisionedController);
+    @SysUISingleton
+    @Provides
+    static DeviceProvisionedController providesDeviceProvisionedController(
+            DeviceProvisionedControllerImpl deviceProvisionedController) {
+        deviceProvisionedController.init();
+        return deviceProvisionedController;
+    }
 
     @Binds
     abstract KeyguardViewController bindKeyguardViewController(
diff --git a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
index b23aa20..7e4ec67 100644
--- a/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/unfold/UnfoldTransitionModule.kt
@@ -20,15 +20,19 @@
 import android.hardware.SensorManager
 import android.hardware.devicestate.DeviceStateManager
 import android.os.Handler
+import android.view.IWindowManager
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.keyguard.LifecycleScreenStatusProvider
 import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider
+import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
 import com.android.wm.shell.unfold.ShellUnfoldProgressProvider
 import dagger.Lazy
 import dagger.Module
 import dagger.Provides
 import java.util.Optional
 import java.util.concurrent.Executor
+import javax.inject.Named
 import javax.inject.Singleton
 
 @Module
@@ -62,6 +66,27 @@
 
     @Provides
     @Singleton
+    fun provideNaturalRotationProgressProvider(
+        context: Context,
+        windowManager: IWindowManager,
+        unfoldTransitionProgressProvider: UnfoldTransitionProgressProvider
+    ): NaturalRotationUnfoldProgressProvider =
+        NaturalRotationUnfoldProgressProvider(
+            context,
+            windowManager,
+            unfoldTransitionProgressProvider
+        )
+
+    @Provides
+    @Named(UNFOLD_STATUS_BAR)
+    @Singleton
+    fun provideStatusBarScopedTransitionProvider(
+        source: NaturalRotationUnfoldProgressProvider
+    ): ScopedUnfoldTransitionProgressProvider =
+        ScopedUnfoldTransitionProgressProvider(source)
+
+    @Provides
+    @Singleton
     fun provideShellProgressProvider(
         config: UnfoldTransitionConfig,
         provider: Lazy<UnfoldTransitionProgressProvider>
@@ -72,3 +97,5 @@
             Optional.empty()
         }
 }
+
+const val UNFOLD_STATUS_BAR = "unfold_status_bar"
\ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java b/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
deleted file mode 100644
index cdc5d87..0000000
--- a/packages/SystemUI/src/com/android/systemui/util/InjectionInflationController.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2018 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.util;
-
-import android.content.Context;
-import android.util.ArrayMap;
-import android.util.AttributeSet;
-import android.view.InflateException;
-import android.view.LayoutInflater;
-import android.view.View;
-
-import com.android.systemui.dagger.SysUISingleton;
-import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout;
-
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
-
-import javax.inject.Inject;
-import javax.inject.Named;
-
-import dagger.BindsInstance;
-import dagger.Subcomponent;
-
-/**
- * Manages inflation that requires dagger injection.
- * See docs/dagger.md for details.
- */
-@SysUISingleton
-public class InjectionInflationController {
-
-    public static final String VIEW_CONTEXT = "view_context";
-    private final ArrayMap<String, Method> mInjectionMap = new ArrayMap<>();
-    private final LayoutInflater.Factory2 mFactory = new InjectionFactory();
-    private final ViewInstanceCreator.Factory mViewInstanceCreatorFactory;
-
-    @Inject
-    public InjectionInflationController(ViewInstanceCreator.Factory viewInstanceCreatorFactory) {
-        mViewInstanceCreatorFactory = viewInstanceCreatorFactory;
-        initInjectionMap();
-    }
-
-    /**
-     * Wraps a {@link LayoutInflater} to support creating dagger injected views.
-     * See docs/dagger.md for details.
-     */
-    public LayoutInflater injectable(LayoutInflater inflater) {
-        LayoutInflater ret = inflater.cloneInContext(inflater.getContext());
-        ret.setPrivateFactory(mFactory);
-        return ret;
-    }
-
-    private void initInjectionMap() {
-        for (Method method : ViewInstanceCreator.class.getDeclaredMethods()) {
-            if (View.class.isAssignableFrom(method.getReturnType())
-                    && (method.getModifiers() & Modifier.PUBLIC) != 0) {
-                mInjectionMap.put(method.getReturnType().getName(), method);
-            }
-        }
-    }
-
-    /**
-     * Subcomponent that actually creates injected views.
-     */
-    @Subcomponent
-    public interface ViewInstanceCreator {
-
-        /** Factory for creating a ViewInstanceCreator. */
-        @Subcomponent.Factory
-        interface Factory {
-            ViewInstanceCreator build(
-                    @BindsInstance @Named(VIEW_CONTEXT) Context context,
-                    @BindsInstance AttributeSet attributeSet);
-        }
-
-        /**
-         * Creates the NotificationStackScrollLayout.
-         */
-        NotificationStackScrollLayout createNotificationStackScrollLayout();
-    }
-
-
-    private class InjectionFactory implements LayoutInflater.Factory2 {
-
-        @Override
-        public View onCreateView(String name, Context context, AttributeSet attrs) {
-            Method creationMethod = mInjectionMap.get(name);
-            if (creationMethod != null) {
-                try {
-                    return (View) creationMethod.invoke(
-                            mViewInstanceCreatorFactory.build(context, attrs));
-                } catch (IllegalAccessException e) {
-                    throw new InflateException("Could not inflate " + name, e);
-                } catch (InvocationTargetException e) {
-                    throw new InflateException("Could not inflate " + name, e);
-                }
-            }
-            return null;
-        }
-
-        @Override
-        public View onCreateView(View parent, String name, Context context, AttributeSet attrs) {
-            return onCreateView(name, context, attrs);
-        }
-    }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt b/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
new file mode 100644
index 0000000..0f4193e9
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/util/ListenerSet.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2021 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.util
+
+import java.util.concurrent.CopyOnWriteArrayList
+
+/**
+ * A collection of listeners, observers, callbacks, etc.
+ *
+ * This container is optimized for infrequent mutation and frequent iteration, with thread safety
+ * and reentrant-safety guarantees as well.
+ */
+class ListenerSet<E> : Iterable<E> {
+    private val listeners: CopyOnWriteArrayList<E> = CopyOnWriteArrayList()
+
+    /**
+     * A thread-safe, reentrant-safe method to add a listener.
+     * Does nothing if the listener is already in the set.
+     */
+    fun addIfAbsent(element: E): Boolean = listeners.addIfAbsent(element)
+
+    /**
+     * A thread-safe, reentrant-safe method to remove a listener.
+     */
+    fun remove(element: E): Boolean = listeners.remove(element)
+
+    /**
+     * Returns an iterator over the listeners currently in the set.  Note that to ensure
+     * [ConcurrentModificationException] is never thrown, this iterator will not reflect changes
+     * made to the set after the iterator is constructed.
+     */
+    override fun iterator(): Iterator<E> = listeners.iterator()
+}
diff --git a/packages/SystemUI/src/com/android/systemui/util/Utils.java b/packages/SystemUI/src/com/android/systemui/util/Utils.java
index a1cdfd8..407dc5e 100644
--- a/packages/SystemUI/src/com/android/systemui/util/Utils.java
+++ b/packages/SystemUI/src/com/android/systemui/util/Utils.java
@@ -24,8 +24,10 @@
 import android.content.res.TypedArray;
 import android.provider.Settings;
 import android.view.ContextThemeWrapper;
+import android.view.DisplayCutout;
 import android.view.View;
 
+import com.android.internal.policy.SystemBarUtils;
 import com.android.systemui.R;
 import com.android.systemui.shared.system.QuickStepContract;
 import com.android.systemui.statusbar.CommandQueue;
@@ -186,4 +188,39 @@
         return color;
     }
 
+    /**
+     * Gets the {@link R.dimen#split_shade_header_height}.
+     *
+     * Currently, it's the same as {@link com.android.internal.R.dimen#quick_qs_offset_height}.
+     */
+    public static int getSplitShadeStatusBarHeight(Context context) {
+        return SystemBarUtils.getQuickQsOffsetHeight(context);
+    }
+
+    /**
+     * Gets the {@link R.dimen#qs_header_system_icons_area_height}.
+     *
+     * It's the same as {@link com.android.internal.R.dimen#quick_qs_offset_height} except for
+     * sw600dp-land.
+     */
+    public static int getQsHeaderSystemIconsAreaHeight(Context context) {
+        final Resources res = context.getResources();
+        if (Utils.shouldUseSplitNotificationShade(res)) {
+            return res.getDimensionPixelSize(R.dimen.qs_header_system_icons_area_height);
+        } else {
+            return SystemBarUtils.getQuickQsOffsetHeight(context);
+        }
+    }
+
+    /**
+     * Gets the {@link R.dimen#status_bar_header_height_keyguard}.
+     */
+    public static int getStatusBarHeaderHeightKeyguard(Context context) {
+        final int statusBarHeight = SystemBarUtils.getStatusBarHeight(context);
+        final DisplayCutout cutout = context.getDisplay().getCutout();
+        final int waterfallInsetTop = cutout == null ? 0 : cutout.getWaterfallInsets().top;
+        final int statusBarHeaderHeightKeyguard = context.getResources()
+                .getDimensionPixelSize(R.dimen.status_bar_header_height_keyguard);
+        return Math.max(statusBarHeight, statusBarHeaderHeightKeyguard + waterfallInsetTop);
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
index 5af2cc5..0a33930 100644
--- a/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
+++ b/packages/SystemUI/src/com/android/systemui/wmshell/WMShellBaseModule.java
@@ -26,6 +26,7 @@
 
 import com.android.internal.logging.UiEventLogger;
 import com.android.internal.statusbar.IStatusBarService;
+import com.android.launcher3.icons.IconProvider;
 import com.android.systemui.dagger.WMComponent;
 import com.android.systemui.dagger.WMSingleton;
 import com.android.wm.shell.RootDisplayAreaOrganizer;
@@ -169,6 +170,12 @@
         return new SystemWindows(displayController, wmService);
     }
 
+    @WMSingleton
+    @Provides
+    static IconProvider provideIconProvider(Context context) {
+        return new IconProvider(context);
+    }
+
     // We currently dedupe multiple messages, so we use the shell main handler directly
     @WMSingleton
     @Provides
@@ -456,13 +463,13 @@
             @ShellMainThread ShellExecutor mainExecutor,
             DisplayImeController displayImeController,
             DisplayInsetsController displayInsetsController, Transitions transitions,
-            TransactionPool transactionPool,
+            TransactionPool transactionPool, IconProvider iconProvider,
             Provider<Optional<StageTaskUnfoldController>> stageTaskUnfoldControllerProvider) {
         if (ActivityTaskManager.supportsSplitScreenMultiWindow(context)) {
             return Optional.of(new SplitScreenController(shellTaskOrganizer, syncQueue, context,
                     rootTaskDisplayAreaOrganizer, mainExecutor, displayImeController,
-                    displayInsetsController, transitions,
-                    transactionPool, stageTaskUnfoldControllerProvider));
+                    displayInsetsController, transitions, transactionPool, iconProvider,
+                    stageTaskUnfoldControllerProvider));
         } else {
             return Optional.empty();
         }
@@ -504,9 +511,10 @@
     @Provides
     static StartingWindowController provideStartingWindowController(Context context,
             @ShellSplashscreenThread ShellExecutor splashScreenExecutor,
-            StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, TransactionPool pool) {
+            StartingWindowTypeAlgorithm startingWindowTypeAlgorithm, IconProvider iconProvider,
+            TransactionPool pool) {
         return new StartingWindowController(context, splashScreenExecutor,
-                startingWindowTypeAlgorithm, pool);
+                startingWindowTypeAlgorithm, iconProvider, pool);
     }
 
     //
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index fe0a2a4..5e0f427 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -194,7 +194,7 @@
         verifyAttachment(times(1));
 
         listenerArgumentCaptor.getValue().onViewDetachedFromWindow(mView);
-
+        verify(mView).onViewDetached();
         verify(mColorExtractor).removeOnColorsChangedListener(
                 any(ColorExtractor.OnColorsChangedListener.class));
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
index 35fe1ba..ff4412e9 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/ClockManagerTest.java
@@ -17,7 +17,6 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
@@ -40,7 +39,6 @@
 import com.android.systemui.plugins.ClockPlugin;
 import com.android.systemui.settings.CurrentUserObservable;
 import com.android.systemui.shared.plugins.PluginManager;
-import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.After;
 import org.junit.Before;
@@ -69,7 +67,6 @@
     private ContentObserver mContentObserver;
     private DockManagerFake mFakeDockManager;
     private MutableLiveData<Integer> mCurrentUser;
-    @Mock InjectionInflationController mMockInjectionInflationController;
     @Mock PluginManager mMockPluginManager;
     @Mock SysuiColorExtractor mMockColorExtractor;
     @Mock ContentResolver mMockContentResolver;
@@ -83,7 +80,6 @@
         MockitoAnnotations.initMocks(this);
 
         LayoutInflater inflater = LayoutInflater.from(getContext());
-        when(mMockInjectionInflationController.injectable(any())).thenReturn(inflater);
 
         mFakeDockManager = new DockManagerFake();
 
@@ -91,7 +87,7 @@
         mCurrentUser.setValue(MAIN_USER_ID);
         when(mMockCurrentUserObserable.getCurrentUser()).thenReturn(mCurrentUser);
 
-        mClockManager = new ClockManager(getContext(), mMockInjectionInflationController,
+        mClockManager = new ClockManager(getContext(), inflater,
                 mMockPluginManager, mMockColorExtractor, mMockContentResolver,
                 mMockCurrentUserObserable, mMockSettingsWrapper, mFakeDockManager);
 
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt b/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
index 456f32b..3a27e35 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/keyguard/clock/SmallClockPositionTest.kt
@@ -43,7 +43,7 @@
     @Test
     fun loadResources() {
         // Cover constructor taking Resources object.
-        position = SmallClockPosition(context.resources)
+        position = SmallClockPosition(context)
         position.setDarkAmount(1f)
         assertThat(position.preferredY).isGreaterThan(0)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
index 172dcda..b3c098c 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/flags/FeatureFlagManagerTest.java
@@ -18,23 +18,35 @@
 
 import static com.google.common.truth.Truth.assertThat;
 
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.dump.DumpManager;
 
 import org.junit.Before;
 import org.junit.Test;
+import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
+import java.io.FileDescriptor;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
 @SmallTest
 public class FeatureFlagManagerTest extends SysuiTestCase {
     FeatureFlagManager mFeatureFlagManager;
 
+    @Mock private DumpManager mDumpManager;
+
     @Before
     public void setup() {
         MockitoAnnotations.initMocks(this);
 
-        mFeatureFlagManager = new FeatureFlagManager();
+        mFeatureFlagManager = new FeatureFlagManager(mDumpManager);
     }
 
     @Test
@@ -43,4 +55,31 @@
         // Again, nothing changes.
         assertThat(mFeatureFlagManager.isEnabled(1, false)).isFalse();
     }
+
+    @Test
+    public void testDump() {
+        // Even if a flag is set before
+        mFeatureFlagManager.setEnabled(1, true);
+
+        // WHEN the flags have been accessed
+        assertFalse(mFeatureFlagManager.isEnabled(1, false));
+        assertTrue(mFeatureFlagManager.isEnabled(2, true));
+
+        // Even if a flag is set after
+        mFeatureFlagManager.setEnabled(2, false);
+
+        // THEN the dump contains the flags and the default values
+        String dump = dumpToString();
+        assertThat(dump).contains(" sysui_flag_1: false\n");
+        assertThat(dump).contains(" sysui_flag_2: true\n");
+    }
+
+    private String dumpToString() {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw);
+        mFeatureFlagManager.dump(mock(FileDescriptor.class), pw, new String[0]);
+        pw.flush();
+        String dump = sw.toString();
+        return dump;
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
deleted file mode 100644
index cb05a6b..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/FaceAuthScreenBrightnessControllerTest.kt
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * Copyright (C) 2020 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.animation.ValueAnimator
-import android.content.res.Resources
-import android.hardware.biometrics.BiometricSourceType
-import android.os.Handler
-import android.provider.Settings.System.SCREEN_BRIGHTNESS_FLOAT
-import android.testing.AndroidTestingRunner
-import android.util.TypedValue
-import android.view.View
-import androidx.test.filters.SmallTest
-import com.android.keyguard.KeyguardUpdateMonitor
-import com.android.keyguard.KeyguardUpdateMonitorCallback
-import com.android.systemui.Dumpable
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.dump.DumpManager
-import com.android.systemui.statusbar.NotificationShadeWindowController
-import com.android.systemui.util.mockito.any
-import com.android.systemui.util.mockito.capture
-import com.android.systemui.util.mockito.eq
-import com.android.systemui.util.settings.GlobalSettings
-import com.android.systemui.util.settings.SystemSettings
-import org.junit.Before
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentCaptor
-import org.mockito.Captor
-import org.mockito.Mock
-import org.mockito.Mockito.`when`
-import org.mockito.Mockito.anyInt
-import org.mockito.Mockito.anyString
-import org.mockito.Mockito.clearInvocations
-import org.mockito.Mockito.never
-import org.mockito.Mockito.verify
-import org.mockito.MockitoAnnotations
-
-const val INITIAL_BRIGHTNESS = 0.5f
-
-@RunWith(AndroidTestingRunner::class)
-@SmallTest
-class FaceAuthScreenBrightnessControllerTest : SysuiTestCase() {
-
-    @Mock
-    lateinit var whiteOverlay: View
-    @Mock
-    lateinit var dumpManager: DumpManager
-    @Mock
-    lateinit var resources: Resources
-    @Mock
-    lateinit var mainHandler: Handler
-    @Mock
-    lateinit var globalSettings: GlobalSettings
-    @Mock
-    lateinit var systemSettings: SystemSettings
-    @Mock
-    lateinit var keyguardUpdateMonitor: KeyguardUpdateMonitor
-    @Mock
-    lateinit var notificationShadeWindowController: NotificationShadeWindowController
-    @Mock
-    lateinit var animator: ValueAnimator
-    @Captor
-    lateinit var keyguardUpdateCallback: ArgumentCaptor<KeyguardUpdateMonitorCallback>
-    lateinit var faceAuthScreenBrightnessController: FaceAuthScreenBrightnessController
-
-    @Before
-    fun setup() {
-        MockitoAnnotations.initMocks(this)
-        faceAuthScreenBrightnessController = object : FaceAuthScreenBrightnessController(
-                notificationShadeWindowController, keyguardUpdateMonitor, resources, globalSettings,
-                systemSettings, mainHandler, dumpManager, true) {
-            override fun createAnimator(start: Float, end: Float) = animator
-        }
-        `when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT))).thenReturn(INITIAL_BRIGHTNESS)
-        `when`(systemSettings.getFloat(eq(SCREEN_BRIGHTNESS_FLOAT), eq(1f)))
-                .thenReturn(INITIAL_BRIGHTNESS)
-        faceAuthScreenBrightnessController.attach(whiteOverlay)
-        verify(keyguardUpdateMonitor).registerCallback(capture(keyguardUpdateCallback))
-    }
-
-    @Test
-    fun init_registersDumpManager() {
-        verify(dumpManager).registerDumpable(anyString(), any(Dumpable::class.java))
-    }
-
-    @Test
-    fun init_registersKeyguardCallback() {
-        verify(keyguardUpdateMonitor)
-                .registerCallback(any(KeyguardUpdateMonitorCallback::class.java))
-    }
-
-    @Test
-    fun onBiometricRunningChanged_animatesBrightness() {
-        clearInvocations(whiteOverlay)
-        keyguardUpdateCallback.value
-                .onBiometricRunningStateChanged(true, BiometricSourceType.FACE)
-        verify(whiteOverlay).visibility = eq(View.VISIBLE)
-        verify(animator).start()
-    }
-
-    @Test
-    fun faceAuthWallpaper_whenFaceIsDisabledForUser() {
-        faceAuthScreenBrightnessController.useFaceAuthWallpaper = true
-        faceAuthScreenBrightnessController.faceAuthWallpaper
-        verify(resources, never()).openRawResource(anyInt(), any(TypedValue::class.java))
-    }
-
-    @Test
-    fun faceAuthWallpaper_whenFaceFlagIsDisabled() {
-        faceAuthScreenBrightnessController.useFaceAuthWallpaper = true
-        faceAuthScreenBrightnessController.faceAuthWallpaper
-        verify(resources, never()).openRawResource(anyInt(), any(TypedValue::class.java))
-    }
-
-    @Test
-    fun faceAuthWallpaper_whenFaceIsEnabledForUser() {
-        faceAuthScreenBrightnessController.useFaceAuthWallpaper = true
-        `when`(keyguardUpdateMonitor.isFaceAuthEnabledForUser(anyInt())).thenReturn(true)
-        faceAuthScreenBrightnessController.faceAuthWallpaper
-        verify(resources).openRawResource(anyInt(), any(TypedValue::class.java))
-    }
-}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
index c5436ef6..5e73dbc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
@@ -62,7 +62,8 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
-import com.android.systemui.util.concurrency.DelayableExecutor;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
 
 import com.airbnb.lottie.LottieAnimationView;
 
@@ -97,11 +98,11 @@
     private @Mock DumpManager mDumpManager;
     private @Mock AccessibilityManager mAccessibilityManager;
     private @Mock ConfigurationController mConfigurationController;
-    private @Mock DelayableExecutor mDelayableExecutor;
     private @Mock Vibrator mVibrator;
     private @Mock AuthRippleController mAuthRippleController;
     private @Mock LottieAnimationView mAodFp;
     private @Mock LayoutInflater mLayoutInflater;
+    private FakeExecutor mDelayableExecutor = new FakeExecutor(new FakeSystemClock());
 
     private LockIconViewController mLockIconViewController;
 
@@ -223,6 +224,7 @@
 
         // WHEN all authenticators are registered
         mAuthControllerCallback.onAllAuthenticatorsRegistered();
+        mDelayableExecutor.runAllReady();
 
         // THEN lock icon view location is updated with the same coordinates as fpProps
         verify(mLockIconView).setCenterLocation(mPointCaptor.capture(), eq(udfps.first));
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 750600ad..52173c1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -212,12 +212,14 @@
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 1);
 
         assertThat(mViewHolder.mAddIcon.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mBottomDivider.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
-        assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(
-                mContext.getString(R.string.media_output_dialog_disconnected, TEST_DEVICE_NAME_2));
+        assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
+                TEST_DEVICE_NAME_2);
+        assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(
+                mContext.getString(R.string.media_output_dialog_disconnected));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
index 12c0d53..c4bab73 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSFragmentTest.java
@@ -39,7 +39,6 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.keyguard.CarrierText;
 import com.android.systemui.Dependency;
-import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiBaseFragmentTest;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dump.DumpManager;
@@ -63,7 +62,6 @@
 import com.android.systemui.statusbar.policy.RemoteInputQuickSettingsDisabler;
 import com.android.systemui.statusbar.policy.UserSwitcherController;
 import com.android.systemui.tuner.TunerService;
-import com.android.systemui.util.InjectionInflationController;
 import com.android.systemui.util.settings.SecureSettings;
 
 import org.junit.Before;
@@ -177,10 +175,6 @@
         return new QSFragment(
                 new RemoteInputQuickSettingsDisabler(context, mock(ConfigurationController.class),
                         commandQueue),
-                new InjectionInflationController(
-                        SystemUIFactory.getInstance()
-                                .getSysUIComponent()
-                                .createViewInstanceCreatorFactory()),
                 mock(QSTileHost.class),
                 mock(StatusBarStateController.class),
                 commandQueue,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
index 06a4ae0..3242adb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSPanelControllerTest.java
@@ -42,7 +42,7 @@
 import com.android.systemui.qs.logging.QSLogger;
 import com.android.systemui.qs.tileimpl.QSTileImpl;
 import com.android.systemui.settings.brightness.BrightnessController;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.settings.brightness.ToggleSlider;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.tuner.TunerService;
@@ -88,9 +88,9 @@
     @Mock
     private BrightnessController mBrightnessController;
     @Mock
-    private BrightnessSlider.Factory mToggleSliderViewControllerFactory;
+    private BrightnessSliderController.Factory mToggleSliderViewControllerFactory;
     @Mock
-    private BrightnessSlider mBrightnessSlider;
+    private BrightnessSliderController mBrightnessSliderController;
     @Mock
     QSTileImpl mQSTile;
     @Mock
@@ -120,7 +120,7 @@
         when(mQSTileHost.getTiles()).thenReturn(Collections.singleton(mQSTile));
         when(mQSTileHost.createTileView(any(), eq(mQSTile), anyBoolean())).thenReturn(mQSTileView);
         when(mToggleSliderViewControllerFactory.create(any(), any()))
-                .thenReturn(mBrightnessSlider);
+                .thenReturn(mBrightnessSliderController);
         when(mBrightnessControllerFactory.create(any(ToggleSlider.class)))
                 .thenReturn(mBrightnessController);
         when(mQSTileRevealControllerFactory.create(any(), any()))
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
new file mode 100644
index 0000000..3059aa1
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/QSSquishinessControllerTest.kt
@@ -0,0 +1,62 @@
+package com.android.systemui.qs
+
+import android.testing.AndroidTestingRunner
+import android.view.ViewGroup
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.plugins.qs.QSTile
+import com.android.systemui.qs.tileimpl.QSTileViewImpl
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.any
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class QSSquishinessControllerTest : SysuiTestCase() {
+
+    @Mock private lateinit var qsTileHost: QSTileHost
+    @Mock private lateinit var qqsFooterActionsView: FooterActionsView
+    @Mock private lateinit var qqsFooterActionsViewLP: ViewGroup.MarginLayoutParams
+    @Mock private lateinit var qsAnimator: QSAnimator
+    @Mock private lateinit var quickQsPanelController: QuickQSPanelController
+    @Mock private lateinit var qstileView: QSTileViewImpl
+    @Mock private lateinit var qstile: QSTile
+    @Mock private lateinit var tileLayout: TileLayout
+
+    @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
+
+    private lateinit var qsSquishinessController: QSSquishinessController
+
+    @Before
+    fun setup() {
+        qsSquishinessController = QSSquishinessController(qsTileHost, qqsFooterActionsView,
+                qsAnimator, quickQsPanelController)
+        `when`(qsTileHost.tiles).thenReturn(mutableListOf(qstile))
+        `when`(quickQsPanelController.getTileView(any())).thenReturn(qstileView)
+        `when`(quickQsPanelController.tileLayout).thenReturn(tileLayout)
+        `when`(qqsFooterActionsView.layoutParams).thenReturn(qqsFooterActionsViewLP)
+    }
+
+    @Test
+    fun setSquishiness_requestsAnimatorUpdate() {
+        qsSquishinessController.squishiness = 0.5f
+        verify(qsAnimator, never()).requestAnimatorUpdate()
+
+        qsSquishinessController.squishiness = 0f
+        verify(qsAnimator).requestAnimatorUpdate()
+    }
+
+    @Test
+    fun setSquishiness_updatesTiles() {
+        qsSquishinessController.squishiness = 0.5f
+        verify(qstileView).squishinessFraction = 0.5f
+        verify(tileLayout).setSquishinessFraction(0.5f)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
index 94af10a..98c7274 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/DeviceControlsTileTest.kt
@@ -52,13 +52,11 @@
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.ArgumentCaptor
-import org.mockito.ArgumentMatchers.anyInt
 import org.mockito.ArgumentMatchers.anyBoolean
 import org.mockito.Captor
 import org.mockito.Mock
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.doNothing
-import org.mockito.Mockito.never
 import org.mockito.Mockito.nullable
 import org.mockito.Mockito.spy
 import org.mockito.Mockito.verify
@@ -272,28 +270,7 @@
     }
 
     @Test
-    fun handleClick_availableAndLocked_activityStarted() {
-        verify(controlsListingController).observe(
-                any(LifecycleOwner::class.java),
-                capture(listingCallbackCaptor)
-        )
-        `when`(controlsComponent.getVisibility()).thenReturn(ControlsComponent.Visibility.AVAILABLE)
-        `when`(keyguardStateController.isUnlocked).thenReturn(false)
-
-        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
-        testableLooper.processAllMessages()
-
-        tile.click(null /* view */)
-        testableLooper.processAllMessages()
-
-        // The activity should be started right away and not require a keyguard dismiss.
-        verifyZeroInteractions(activityStarter)
-        verify(spiedContext).startActivity(intentCaptor.capture())
-        assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
-    }
-
-    @Test
-    fun handleClick_availableAndUnlocked_activityStarted() {
+    fun handleClick_available_shownOverLockscreenWhenLocked() {
         verify(controlsListingController).observe(
                 any(LifecycleOwner::class.java),
                 capture(listingCallbackCaptor)
@@ -307,16 +284,16 @@
         tile.click(null /* view */)
         testableLooper.processAllMessages()
 
-        verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
         verify(activityStarter).startActivity(
                 intentCaptor.capture(),
                 eq(true) /* dismissShade */,
-                nullable(ActivityLaunchAnimator.Controller::class.java))
+                nullable(ActivityLaunchAnimator.Controller::class.java),
+                eq(true) /* showOverLockscreenWhenLocked */)
         assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
     }
 
     @Test
-    fun handleClick_availableAfterUnlockAndIsLocked_keyguardDismissRequired() {
+    fun handleClick_availableAfterUnlock_notShownOverLockscreenWhenLocked() {
         verify(controlsListingController).observe(
             any(LifecycleOwner::class.java),
             capture(listingCallbackCaptor)
@@ -331,38 +308,11 @@
         tile.click(null /* view */)
         testableLooper.processAllMessages()
 
-        verify(activityStarter, never()).startActivity(
-                any(),
-                anyBoolean() /* dismissShade */,
-                nullable(ActivityLaunchAnimator.Controller::class.java))
-        verify(activityStarter).postStartActivityDismissingKeyguard(
-                intentCaptor.capture(),
-                anyInt(),
-                nullable(ActivityLaunchAnimator.Controller::class.java))
-        assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
-    }
-
-    @Test
-    fun handleClick_availableAfterUnlockAndIsUnlocked_activityStarted() {
-        verify(controlsListingController).observe(
-                any(LifecycleOwner::class.java),
-                capture(listingCallbackCaptor)
-        )
-        `when`(controlsComponent.getVisibility())
-                .thenReturn(ControlsComponent.Visibility.AVAILABLE_AFTER_UNLOCK)
-        `when`(keyguardStateController.isUnlocked).thenReturn(true)
-
-        listingCallbackCaptor.value.onServicesUpdated(listOf(serviceInfo))
-        testableLooper.processAllMessages()
-
-        tile.click(null /* view */)
-        testableLooper.processAllMessages()
-
-        verify(activityStarter, never()).postStartActivityDismissingKeyguard(any(), anyInt())
         verify(activityStarter).startActivity(
                 intentCaptor.capture(),
-                eq(true) /* dismissShade */,
-                nullable(ActivityLaunchAnimator.Controller::class.java))
+                anyBoolean() /* dismissShade */,
+                nullable(ActivityLaunchAnimator.Controller::class.java),
+                eq(false) /* showOverLockscreenWhenLocked */)
         assertThat(intentCaptor.value.component?.className).isEqualTo(CONTROLS_ACTIVITY_CLASS_NAME)
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
index fe32839..eb03b5f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogControllerTest.java
@@ -45,12 +45,14 @@
 import com.android.settingslib.wifi.WifiUtils;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.animation.DialogLaunchAnimator;
 import com.android.systemui.broadcast.BroadcastDispatcher;
 import com.android.systemui.dagger.qualifiers.Main;
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.connectivity.NetworkController;
 import com.android.systemui.statusbar.connectivity.NetworkController.AccessPointController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
+import com.android.systemui.statusbar.policy.LocationController;
 import com.android.systemui.toast.SystemUIToast;
 import com.android.systemui.toast.ToastFactory;
 import com.android.systemui.util.CarrierConfigTracker;
@@ -135,6 +137,10 @@
     private Animator mAnimator;
     @Mock
     private CarrierConfigTracker mCarrierConfigTracker;
+    @Mock
+    private LocationController mLocationController;
+    @Mock
+    private DialogLaunchAnimator mDialogLaunchAnimator;
 
     private TestableResources mTestableResources;
     private MockInternetDialogController mInternetDialogController;
@@ -170,7 +176,8 @@
                 mSubscriptionManager, mTelephonyManager, mWifiManager,
                 mock(ConnectivityManager.class), mHandler, mExecutor, mBroadcastDispatcher,
                 mock(KeyguardUpdateMonitor.class), mGlobalSettings, mKeyguardStateController,
-                mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker);
+                mWindowManager, mToastFactory, mWorkerHandler, mCarrierConfigTracker,
+                mLocationController, mDialogLaunchAnimator);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mExecutor,
                 mInternetDialogController.mOnSubscriptionsChangedListener);
         mInternetDialogController.onStart(mInternetDialogCallback, true);
@@ -602,6 +609,30 @@
         verify(mMergedCarrierEntry).setEnabled(false);
     }
 
+    @Test
+    public void isWifiScanEnabled_locationOff_returnFalse() {
+        when(mLocationController.isLocationEnabled()).thenReturn(false);
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+        assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+        assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+    }
+
+    @Test
+    public void isWifiScanEnabled_locationOn_returnIsScanAlwaysAvailable() {
+        when(mLocationController.isLocationEnabled()).thenReturn(true);
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(false);
+
+        assertThat(mInternetDialogController.isWifiScanEnabled()).isFalse();
+
+        when(mWifiManager.isScanAlwaysAvailable()).thenReturn(true);
+
+        assertThat(mInternetDialogController.isWifiScanEnabled()).isTrue();
+    }
+
     private String getResourcesString(String name) {
         return mContext.getResources().getString(getResourcesId(name));
     }
@@ -625,12 +656,14 @@
                 KeyguardUpdateMonitor keyguardUpdateMonitor, GlobalSettings globalSettings,
                 KeyguardStateController keyguardStateController, WindowManager windowManager,
                 ToastFactory toastFactory, Handler workerHandler,
-                CarrierConfigTracker carrierConfigTracker) {
+                CarrierConfigTracker carrierConfigTracker,
+                LocationController locationController,
+                DialogLaunchAnimator dialogLaunchAnimator) {
             super(context, uiEventLogger, starter, accessPointController, subscriptionManager,
                     telephonyManager, wifiManager, connectivityManager, handler, mainExecutor,
                     broadcastDispatcher, keyguardUpdateMonitor, globalSettings,
                     keyguardStateController, windowManager, toastFactory, workerHandler,
-                    carrierConfigTracker);
+                    carrierConfigTracker, locationController, dialogLaunchAnimator);
             mGlobalSettings = globalSettings;
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
index c42b64a..5e1fea5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/tiles/dialog/InternetDialogTest.java
@@ -19,6 +19,7 @@
 import android.testing.TestableLooper;
 import android.view.View;
 import android.widget.LinearLayout;
+import android.widget.TextView;
 
 import androidx.recyclerview.widget.RecyclerView;
 import androidx.test.filters.SmallTest;
@@ -26,6 +27,8 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.util.concurrency.FakeExecutor;
+import com.android.systemui.util.time.FakeSystemClock;
 import com.android.wifitrackerlib.WifiEntry;
 
 import org.junit.After;
@@ -64,6 +67,7 @@
     @Mock
     private InternetDialogController mInternetDialogController;
 
+    private FakeExecutor mBgExecutor = new FakeExecutor(new FakeSystemClock());
     private InternetDialog mInternetDialog;
     private View mDialogView;
     private View mSubTitle;
@@ -73,6 +77,7 @@
     private LinearLayout mConnectedWifi;
     private RecyclerView mWifiList;
     private LinearLayout mSeeAll;
+    private LinearLayout mWifiScanNotify;
 
     @Before
     public void setUp() {
@@ -91,7 +96,8 @@
         when(mInternetDialogController.getWifiManager()).thenReturn(mWifiManager);
 
         mInternetDialog = new InternetDialog(mContext, mock(InternetDialogFactory.class),
-                mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler);
+                mInternetDialogController, true, true, true, mock(UiEventLogger.class), mHandler,
+                mBgExecutor);
         mInternetDialog.mAdapter = mInternetAdapter;
         mInternetDialog.onAccessPointsChanged(mWifiEntries, mInternetWifiEntry);
         mInternetDialog.show();
@@ -104,6 +110,7 @@
         mConnectedWifi = mDialogView.requireViewById(R.id.wifi_connected_layout);
         mWifiList = mDialogView.requireViewById(R.id.wifi_list_layout);
         mSeeAll = mDialogView.requireViewById(R.id.see_all_layout);
+        mWifiScanNotify = mDialogView.requireViewById(R.id.wifi_scan_notify_layout);
     }
 
     @After
@@ -126,7 +133,7 @@
     public void updateDialog_withApmOn_internetDialogSubTitleGone() {
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mSubTitle.getVisibility()).isEqualTo(View.GONE);
     }
@@ -135,7 +142,7 @@
     public void updateDialog_withApmOff_internetDialogSubTitleVisible() {
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mSubTitle.getVisibility()).isEqualTo(View.VISIBLE);
     }
@@ -145,7 +152,7 @@
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
         when(mInternetDialogController.hasEthernet()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
     }
@@ -155,7 +162,7 @@
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(false);
         when(mInternetDialogController.hasEthernet()).thenReturn(false);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
     }
@@ -165,7 +172,7 @@
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
         when(mInternetDialogController.hasEthernet()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mEthernet.getVisibility()).isEqualTo(View.VISIBLE);
     }
@@ -175,7 +182,7 @@
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
         when(mInternetDialogController.hasEthernet()).thenReturn(false);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mEthernet.getVisibility()).isEqualTo(View.GONE);
     }
@@ -184,7 +191,7 @@
     public void updateDialog_withApmOn_mobileDataLayoutGone() {
         when(mInternetDialogController.isAirplaneModeEnabled()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(true);
 
         assertThat(mMobileDataToggle.getVisibility()).isEqualTo(View.GONE);
     }
@@ -194,7 +201,7 @@
         // The preconditions WiFi ON and Internet WiFi are already in setUp()
         doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.VISIBLE);
     }
@@ -205,7 +212,7 @@
         mInternetDialog.onAccessPointsChanged(mWifiEntries, null /* connectedEntry*/);
         doReturn(false).when(mInternetDialogController).activeNetworkIsCellular();
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
     }
@@ -215,7 +222,7 @@
         // The precondition WiFi ON is already in setUp()
         mInternetDialog.onAccessPointsChanged(null /* wifiEntries */, mInternetWifiEntry);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
         assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
@@ -225,7 +232,7 @@
     public void updateDialog_wifiOnAndHasWifiList_showWifiListAndSeeAll() {
         // The preconditions WiFi ON and WiFi entries are already in setUp()
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mWifiList.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mSeeAll.getVisibility()).isEqualTo(View.VISIBLE);
@@ -236,7 +243,7 @@
         // The preconditions WiFi ON and Internet WiFi are already in setUp()
         when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mWifiToggle.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mWifiToggle.getBackground()).isNotNull();
@@ -247,7 +254,7 @@
         // The preconditions WiFi ON and Internet WiFi are already in setUp()
         when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mConnectedWifi.getVisibility()).isEqualTo(View.GONE);
     }
@@ -257,13 +264,57 @@
         // The preconditions WiFi entries are already in setUp()
         when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
 
-        mInternetDialog.updateDialog();
+        mInternetDialog.updateDialog(false);
 
         assertThat(mWifiList.getVisibility()).isEqualTo(View.GONE);
         assertThat(mSeeAll.getVisibility()).isEqualTo(View.GONE);
     }
 
     @Test
+    public void updateDialog_wifiOn_hideWifiScanNotify() {
+        // The preconditions WiFi ON and Internet WiFi are already in setUp()
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void updateDialog_wifiOffAndWifiScanOff_hideWifiScanNotify() {
+        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiScanEnabled()).thenReturn(false);
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void updateDialog_wifiOffAndWifiScanOnAndDeviceLocked_hideWifiScanNotify() {
+        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(true);
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.GONE);
+    }
+
+    @Test
+    public void updateDialog_wifiOffAndWifiScanOnAndDeviceUnlocked_showWifiScanNotify() {
+        when(mWifiManager.isWifiEnabled()).thenReturn(false);
+        when(mInternetDialogController.isWifiScanEnabled()).thenReturn(true);
+        when(mInternetDialogController.isDeviceLocked()).thenReturn(false);
+
+        mInternetDialog.updateDialog(false);
+
+        assertThat(mWifiScanNotify.getVisibility()).isEqualTo(View.VISIBLE);
+        TextView wifiScanNotifyText = mDialogView.requireViewById(R.id.wifi_scan_notify_text);
+        assertThat(wifiScanNotifyText.getText().length()).isNotEqualTo(0);
+        assertThat(wifiScanNotifyText.getMovementMethod()).isNotNull();
+    }
+
+    @Test
     public void onClickSeeMoreButton_clickSeeAll_verifyLaunchNetworkSetting() {
         mSeeAll.performClick();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
similarity index 96%
rename from packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
rename to packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
index bceb928..2b39354 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/settings/brightness/BrightnessSliderControllerTest.kt
@@ -45,7 +45,7 @@
 
 @SmallTest
 @RunWith(AndroidTestingRunner::class)
-class BrightnessSliderTest : SysuiTestCase() {
+class BrightnessSliderControllerTest : SysuiTestCase() {
 
     @Mock
     private lateinit var brightnessSliderView: BrightnessSliderView
@@ -66,7 +66,7 @@
     private lateinit var seekBar: SeekBar
     private var mFalsingManager: FalsingManagerFake = FalsingManagerFake()
 
-    private lateinit var mController: BrightnessSlider
+    private lateinit var mController: BrightnessSliderController
 
     @Before
     fun setUp() {
@@ -75,7 +75,7 @@
         whenever(mirrorController.toggleSlider).thenReturn(mirror)
         whenever(motionEvent.copy()).thenReturn(motionEvent)
 
-        mController = BrightnessSlider(brightnessSliderView, mFalsingManager)
+        mController = BrightnessSliderController(brightnessSliderView, mFalsingManager)
         mController.init()
         mController.setOnChangedListener(listener)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index ea21aa9..23cca72 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -20,10 +20,10 @@
 import static android.app.NotificationManager.IMPORTANCE_LOW;
 import static android.content.Intent.ACTION_USER_SWITCHED;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_MEDIA_CONTROLS;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_MEDIA_CONTROLS;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
 
 import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.assertTrue;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
index 67cab74..b23d07a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerBaseTest.java
@@ -216,7 +216,7 @@
         mCallbackHandler = mock(CallbackHandler.class);
 
         mMockProvisionController = mock(DeviceProvisionedController.class);
-        when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(true);
+        when(mMockProvisionController.isCurrentUserSetup()).thenReturn(true);
         doAnswer(invocation -> {
             mUserCallback = (DeviceProvisionedListener) invocation.getArguments()[0];
             mUserCallback.onUserSetupChanged();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
index 00dedd9..12f8282 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/connectivity/NetworkControllerDataTest.java
@@ -21,7 +21,6 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
-import static org.mockito.Matchers.anyInt;
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.when;
 
@@ -211,7 +210,7 @@
         updateDataConnectionState(TelephonyManager.DATA_DISCONNECTED, 0);
         setConnectivityViaCallbackInNetworkController(
                 NetworkCapabilities.TRANSPORT_CELLULAR, false, false, null);
-        when(mMockProvisionController.isUserSetup(anyInt())).thenReturn(false);
+        when(mMockProvisionController.isCurrentUserSetup()).thenReturn(false);
         mUserCallback.onUserSetupChanged();
         TestableLooper.get(this).processAllMessages();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
index 39d794d..ebeb591 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/NotifCollectionTest.java
@@ -60,6 +60,7 @@
 import android.util.ArraySet;
 import android.util.Pair;
 
+import androidx.annotation.NonNull;
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.statusbar.IStatusBarService;
@@ -1405,25 +1406,26 @@
             mName = name;
         }
 
+        @NonNull
         @Override
         public String getName() {
             return mName;
         }
 
         @Override
-        public void setCallback(OnEndLifetimeExtensionCallback callback) {
+        public void setCallback(@NonNull OnEndLifetimeExtensionCallback callback) {
             this.callback = callback;
         }
 
         @Override
         public boolean shouldExtendLifetime(
-                NotificationEntry entry,
+                @NonNull NotificationEntry entry,
                 @CancellationReason int reason) {
             return shouldExtendLifetime;
         }
 
         @Override
-        public void cancelLifetimeExtension(NotificationEntry entry) {
+        public void cancelLifetimeExtension(@NonNull NotificationEntry entry) {
             if (onCancelLifetimeExtension != null) {
                 onCancelLifetimeExtension.run();
             }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
index 3378003..e9e6718 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/ShadeListBuilderTest.java
@@ -33,6 +33,7 @@
 import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import static java.util.Collections.singletonList;
@@ -42,6 +43,7 @@
 import android.testing.TestableLooper;
 import android.util.ArrayMap;
 
+import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
@@ -78,6 +80,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.stream.Collectors;
 
 @SmallTest
@@ -608,6 +611,30 @@
     }
 
     @Test
+    public void testNotifSectionsChildrenUpdated() {
+        AtomicBoolean validChildren = new AtomicBoolean(false);
+        final NotifSectioner pkg1Sectioner = spy(new PackageSectioner(PACKAGE_1) {
+            @Nullable
+            @Override
+            public void onEntriesUpdated(List<ListEntry> entries) {
+                super.onEntriesUpdated(entries);
+                validChildren.set(entries.size() == 2);
+            }
+        });
+        mListBuilder.setSectioners(Arrays.asList(pkg1Sectioner));
+
+        addNotif(0, PACKAGE_4);
+        addNotif(1, PACKAGE_1);
+        addNotif(2, PACKAGE_1);
+        addNotif(3, PACKAGE_3);
+
+        dispatchBuild();
+
+        verify(pkg1Sectioner, times(1)).onEntriesUpdated(any());
+        assertTrue(validChildren.get());
+    }
+
+    @Test
     public void testNotifSections() {
         // GIVEN a filter that removes all PACKAGE_4 notifs and sections that divide
         // notifs based on package name
@@ -1633,7 +1660,7 @@
         private final String mPackage;
 
         PackageSectioner(String pkg) {
-            super("PackageSection_" + pkg);
+            super("PackageSection_" + pkg, 0);
             mPackage = pkg;
         }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt
new file mode 100644
index 0000000..0cba0703
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/GutsCoordinatorTest.kt
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifLifetimeExtender.OnEndLifetimeExtensionCallback
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewListener
+import com.android.systemui.statusbar.notification.collection.render.NotifGutsViewManager
+import com.android.systemui.statusbar.notification.row.NotificationGuts
+import com.android.systemui.util.mockito.argumentCaptor
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.mock
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class GutsCoordinatorTest : SysuiTestCase() {
+    private lateinit var coordinator: GutsCoordinator
+    private lateinit var notifLifetimeExtender: NotifLifetimeExtender
+    private lateinit var notifGutsViewListener: NotifGutsViewListener
+
+    private lateinit var entry1: NotificationEntry
+    private lateinit var entry2: NotificationEntry
+
+    @Mock private lateinit var notifGutsViewManager: NotifGutsViewManager
+    @Mock private lateinit var pipeline: NotifPipeline
+    @Mock private lateinit var dumpManager: DumpManager
+    @Mock private lateinit var logger: GutsCoordinatorLogger
+    @Mock private lateinit var lifetimeExtenderCallback: OnEndLifetimeExtensionCallback
+
+    @Before
+    fun setUp() {
+        initMocks(this)
+        coordinator = GutsCoordinator(notifGutsViewManager, logger, dumpManager)
+        coordinator.attach(pipeline)
+        notifLifetimeExtender = argumentCaptor<NotifLifetimeExtender>().let {
+            verify(pipeline).addNotificationLifetimeExtender(it.capture())
+            it.value!!
+        }
+        notifGutsViewListener = argumentCaptor<NotifGutsViewListener>().let {
+            verify(notifGutsViewManager).setGutsListener(it.capture())
+            it.value!!
+        }
+        notifLifetimeExtender.setCallback(lifetimeExtenderCallback)
+        entry1 = NotificationEntryBuilder().setId(1).build()
+        entry2 = NotificationEntryBuilder().setId(2).build()
+    }
+
+    @Test
+    fun testSimpleLifetimeExtension() {
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+        notifGutsViewListener.onGutsOpen(entry1, mock(NotificationGuts::class.java))
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+        notifGutsViewListener.onGutsClose(entry1)
+        verify(lifetimeExtenderCallback).onEndLifetimeExtension(notifLifetimeExtender, entry1)
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+    }
+
+    @Test
+    fun testDoubleOpenLifetimeExtension() {
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+        notifGutsViewListener.onGutsOpen(entry1, mock(NotificationGuts::class.java))
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+        notifGutsViewListener.onGutsOpen(entry1, mock(NotificationGuts::class.java))
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+        notifGutsViewListener.onGutsClose(entry1)
+        verify(lifetimeExtenderCallback).onEndLifetimeExtension(notifLifetimeExtender, entry1)
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+    }
+
+    @Test
+    fun testTwoEntryLifetimeExtension() {
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry2, 0)).isFalse()
+        notifGutsViewListener.onGutsOpen(entry1, mock(NotificationGuts::class.java))
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry2, 0)).isFalse()
+        notifGutsViewListener.onGutsOpen(entry2, mock(NotificationGuts::class.java))
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isTrue()
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry2, 0)).isTrue()
+        notifGutsViewListener.onGutsClose(entry1)
+        verify(lifetimeExtenderCallback).onEndLifetimeExtension(notifLifetimeExtender, entry1)
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry2, 0)).isTrue()
+        notifGutsViewListener.onGutsClose(entry2)
+        verify(lifetimeExtenderCallback).onEndLifetimeExtension(notifLifetimeExtender, entry2)
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry1, 0)).isFalse()
+        assertThat(notifLifetimeExtender.shouldExtendLifetime(entry2, 0)).isFalse()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
index 1031d6b..8f241a3 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/RankingCoordinatorTest.java
@@ -21,17 +21,22 @@
 
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
+import android.app.Notification;
+import android.service.notification.StatusBarNotification;
 import android.testing.AndroidTestingRunner;
 
+import androidx.annotation.Nullable;
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.RankingBuilder;
+import com.android.systemui.statusbar.notification.collection.ListEntry;
 import com.android.systemui.statusbar.notification.collection.NotifPipeline;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
@@ -39,6 +44,7 @@
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner;
 import com.android.systemui.statusbar.notification.collection.provider.HighPriorityProvider;
 import com.android.systemui.statusbar.notification.collection.render.NodeController;
+import com.android.systemui.statusbar.notification.collection.render.SectionHeaderController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -46,8 +52,11 @@
 import org.mockito.ArgumentCaptor;
 import org.mockito.Captor;
 import org.mockito.Mock;
+import org.mockito.Mockito;
 import org.mockito.MockitoAnnotations;
 
+import java.util.Arrays;
+
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
 public class RankingCoordinatorTest extends SysuiTestCase {
@@ -56,7 +65,8 @@
     @Mock private HighPriorityProvider mHighPriorityProvider;
     @Mock private NotifPipeline mNotifPipeline;
     @Mock private NodeController mAlertingHeaderController;
-    @Mock private NodeController mSilentHeaderController;
+    @Mock private NodeController mSilentNodeController;
+    @Mock private SectionHeaderController mSilentHeaderController;
 
     @Captor private ArgumentCaptor<NotifFilter> mNotifFilterCaptor;
 
@@ -72,7 +82,7 @@
         MockitoAnnotations.initMocks(this);
         RankingCoordinator rankingCoordinator = new RankingCoordinator(
                 mStatusBarStateController, mHighPriorityProvider, mAlertingHeaderController,
-                mSilentHeaderController);
+                mSilentHeaderController, mSilentNodeController);
         mEntry = new NotificationEntryBuilder().build();
 
         rankingCoordinator.attach(mNotifPipeline);
@@ -85,6 +95,28 @@
     }
 
     @Test
+    public void testSilentHeaderClearableChildrenUpdate() {
+        StatusBarNotification sbn = Mockito.mock(StatusBarNotification.class);
+        Mockito.doReturn("key").when(sbn).getKey();
+        Mockito.doReturn(Mockito.mock(Notification.class)).when(sbn).getNotification();
+        NotificationEntry entry = new NotificationEntryBuilder().setSbn(sbn).build();
+        ListEntry listEntry = new ListEntry("key", 0L) {
+            @Nullable
+            @Override
+            public NotificationEntry getRepresentativeEntry() {
+                return entry;
+            }
+        };
+        Mockito.doReturn(true).when(sbn).isClearable();
+        mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry));
+        verify(mSilentHeaderController).setClearSectionEnabled(eq(true));
+
+        Mockito.doReturn(false).when(sbn).isClearable();
+        mSilentSectioner.onEntriesUpdated(Arrays.asList(listEntry));
+        verify(mSilentHeaderController).setClearSectionEnabled(eq(false));
+    }
+
+    @Test
     public void testUnfilteredState() {
         // GIVEN no suppressed visual effects + app not suspended
         mEntry.setRanking(getRankingForUnfilteredNotif().build());
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
new file mode 100644
index 0000000..5915cd7
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/coordinator/ShadeEventCoordinatorTest.kt
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.systemui.statusbar.notification.collection.coordinator
+
+import android.service.notification.NotificationListenerService.REASON_APP_CANCEL
+import android.service.notification.NotificationListenerService.REASON_CANCEL
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.statusbar.notification.collection.NotifPipeline
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
+import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
+import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
+import com.android.systemui.util.mockito.argumentCaptor
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.Mock
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations.initMocks
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper
+class ShadeEventCoordinatorTest : SysuiTestCase() {
+    private lateinit var coordinator: ShadeEventCoordinator
+    private lateinit var notifCollectionListener: NotifCollectionListener
+    private lateinit var onBeforeRenderListListener: OnBeforeRenderListListener
+
+    private lateinit var entry1: NotificationEntry
+    private lateinit var entry2: NotificationEntry
+
+    @Mock private lateinit var pipeline: NotifPipeline
+    @Mock private lateinit var logger: ShadeEventCoordinatorLogger
+    @Mock private lateinit var notifRemovedByUserCallback: Runnable
+    @Mock private lateinit var shadeEmptiedCallback: Runnable
+
+    @Before
+    fun setUp() {
+        initMocks(this)
+        coordinator = ShadeEventCoordinator(logger)
+        coordinator.attach(pipeline)
+        notifCollectionListener = argumentCaptor<NotifCollectionListener>().let {
+            verify(pipeline).addCollectionListener(it.capture())
+            it.value!!
+        }
+        onBeforeRenderListListener = argumentCaptor<OnBeforeRenderListListener>().let {
+            verify(pipeline).addOnBeforeRenderListListener(it.capture())
+            it.value!!
+        }
+        coordinator.setNotifRemovedByUserCallback(notifRemovedByUserCallback)
+        coordinator.setShadeEmptiedCallback(shadeEmptiedCallback)
+        entry1 = NotificationEntryBuilder().setId(1).build()
+        entry2 = NotificationEntryBuilder().setId(2).build()
+    }
+
+    @Test
+    fun testUserCancelLastNotification() {
+        notifCollectionListener.onEntryRemoved(entry1, REASON_CANCEL)
+        verify(shadeEmptiedCallback, never()).run()
+        verify(notifRemovedByUserCallback, never()).run()
+        onBeforeRenderListListener.onBeforeRenderList(listOf())
+        verify(shadeEmptiedCallback).run()
+        verify(notifRemovedByUserCallback).run()
+    }
+
+    @Test
+    fun testAppCancelLastNotification() {
+        notifCollectionListener.onEntryRemoved(entry1, REASON_APP_CANCEL)
+        onBeforeRenderListListener.onBeforeRenderList(listOf())
+        verify(shadeEmptiedCallback).run()
+        verify(notifRemovedByUserCallback, never()).run()
+    }
+
+    @Test
+    fun testUserCancelOneOfTwoNotifications() {
+        notifCollectionListener.onEntryRemoved(entry1, REASON_CANCEL)
+        onBeforeRenderListListener.onBeforeRenderList(listOf(entry2))
+        verify(shadeEmptiedCallback, never()).run()
+        verify(notifRemovedByUserCallback).run()
+    }
+
+    @Test
+    fun testAppCancelOneOfTwoNotifications() {
+        notifCollectionListener.onEntryRemoved(entry1, REASON_APP_CANCEL)
+        onBeforeRenderListListener.onBeforeRenderList(listOf(entry2))
+        verify(shadeEmptiedCallback, never()).run()
+        verify(notifRemovedByUserCallback, never()).run()
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
index 2e676bb..ed48452 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/collection/render/NodeSpecBuilderTest.kt
@@ -26,6 +26,10 @@
 import com.android.systemui.statusbar.notification.collection.getAttachState
 import com.android.systemui.statusbar.notification.collection.listbuilder.NotifSection
 import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.NotifSectioner
+import com.android.systemui.statusbar.notification.stack.BUCKET_ALERTING
+import com.android.systemui.statusbar.notification.stack.BUCKET_PEOPLE
+import com.android.systemui.statusbar.notification.stack.BUCKET_SILENT
+import com.android.systemui.statusbar.notification.stack.PriorityBucket
 import com.android.systemui.util.mockito.any
 import org.junit.Before
 import org.junit.Test
@@ -45,11 +49,15 @@
     private var headerController1: NodeController = buildFakeController("header1")
     private var headerController2: NodeController = buildFakeController("header2")
 
-    private val section0 = buildSection(0, headerController0)
-    private val section0NoHeader = buildSection(0, null)
-    private val section1 = buildSection(1, headerController1)
-    private val section1NoHeader = buildSection(1, null)
-    private val section2 = buildSection(2, headerController2)
+    private val section0Bucket = BUCKET_PEOPLE
+    private val section1Bucket = BUCKET_ALERTING
+    private val section2Bucket = BUCKET_SILENT
+
+    private val section0 = buildSection(0, section0Bucket, headerController0)
+    private val section0NoHeader = buildSection(0, section0Bucket, null)
+    private val section1 = buildSection(1, section1Bucket, headerController1)
+    private val section1NoHeader = buildSection(1, section1Bucket, null)
+    private val section2 = buildSection(2, section2Bucket, headerController2)
 
     private val fakeViewBarn = FakeViewBarn()
 
@@ -297,8 +305,12 @@
     return controller
 }
 
-private fun buildSection(index: Int, nodeController: NodeController?): NotifSection {
-    return NotifSection(object : NotifSectioner("Section $index") {
+private fun buildSection(
+    index: Int,
+    @PriorityBucket bucket: Int,
+    nodeController: NodeController?
+): NotifSection {
+    return NotifSection(object : NotifSectioner("Section $index (bucket=$bucket)", bucket) {
 
         override fun isInSection(entry: ListEntry?): Boolean {
             throw NotImplementedError("This should never be called")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
index c1d2ea8..f11f8c4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationSectionsManagerTest.java
@@ -18,11 +18,11 @@
 
 import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
 
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_ALERTING;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_FOREGROUND_SERVICE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_HEADS_UP;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_PEOPLE;
-import static com.android.systemui.statusbar.notification.stack.NotificationSectionsManagerKt.BUCKET_SILENT;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_ALERTING;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_FOREGROUND_SERVICE;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_HEADS_UP;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_PEOPLE;
+import static com.android.systemui.statusbar.notification.stack.NotificationPriorityBucketKt.BUCKET_SILENT;
 
 import static com.google.common.truth.Truth.assertThat;
 
@@ -64,7 +64,6 @@
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
-import org.mockito.Answers;
 import org.mockito.Mock;
 import org.mockito.junit.MockitoJUnit;
 import org.mockito.junit.MockitoRule;
@@ -608,7 +607,7 @@
         }
     }
 
-    private View mockNotification(int bucket, boolean isGone) {
+    private View mockNotification(@PriorityBucket int bucket, boolean isGone) {
         ExpandableNotificationRow notifRow =
                 mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
         when(notifRow.getVisibility()).thenReturn(View.VISIBLE);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
index 9f42fa4d..185d9cd 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutTest.java
@@ -58,6 +58,8 @@
 import com.android.systemui.statusbar.SysuiStatusBarStateController;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.legacy.NotificationGroupManagerLegacy;
+import com.android.systemui.statusbar.notification.collection.render.GroupExpansionManager;
+import com.android.systemui.statusbar.notification.collection.render.GroupMembershipManager;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.FooterView;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
@@ -110,9 +112,20 @@
         Settings.Secure.putIntForUser(mContext.getContentResolver(), NOTIFICATION_HISTORY_ENABLED,
                 1, UserHandle.USER_CURRENT);
 
+
+        // Interact with real instance of AmbientState.
+        mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController);
+
         // Inject dependencies before initializing the layout
         mDependency.injectTestDependency(SysuiStatusBarStateController.class, mBarState);
         mDependency.injectMockDependency(ShadeController.class);
+        mDependency.injectTestDependency(
+                NotificationSectionsManager.class, mNotificationSectionsManager);
+        mDependency.injectTestDependency(GroupMembershipManager.class, mGroupMembershipManger);
+        mDependency.injectTestDependency(GroupExpansionManager.class, mGroupExpansionManager);
+        mDependency.injectTestDependency(AmbientState.class, mAmbientState);
+        mDependency.injectTestDependency(
+                UnlockedScreenOffAnimationController.class, mUnlockedScreenOffAnimationController);
 
         NotificationShelfController notificationShelfController =
                 mock(NotificationShelfController.class);
@@ -123,22 +136,12 @@
                         mNotificationSection
                 });
 
-        // Interact with real instance of AmbientState.
-        mAmbientState = new AmbientState(mContext, mNotificationSectionsManager, mBypassController);
-
         // The actual class under test.  You may need to work with this class directly when
         // testing anonymous class members of mStackScroller, like mMenuEventListener,
         // which refer to members of NotificationStackScrollLayout. The spy
         // holds a copy of the CUT's instances of these KeyguardBypassController, so they still
         // refer to the CUT's member variables, not the spy's member variables.
-        mStackScrollerInternal = new NotificationStackScrollLayout(
-                getContext(),
-                null,
-                mNotificationSectionsManager,
-                mGroupMembershipManger,
-                mGroupExpansionManager,
-                mAmbientState,
-                mUnlockedScreenOffAnimationController);
+        mStackScrollerInternal = new NotificationStackScrollLayout(getContext(), null);
         mStackScrollerInternal.initView(getContext(), mNotificationSwipeHelper);
         mStackScroller = spy(mStackScrollerInternal);
         mStackScroller.setShelfController(notificationShelfController);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
index d098e1a..624bedc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithmTest.java
@@ -58,7 +58,6 @@
     private KeyguardClockPositionAlgorithm.Result mClockPosition;
 
     private MockitoSession mStaticMockSession;
-    private int mNotificationStackHeight;
 
     private float mPanelExpansion;
     private int mKeyguardStatusBarHeaderHeight;
@@ -264,6 +263,30 @@
     }
 
     @Test
+    public void notifPaddingExpandedAlignedWithClockInSplitShadeMode() {
+        givenLockScreen();
+        mIsSplitShade = true;
+        mKeyguardStatusHeight = 200;
+        // WHEN the position algorithm is run
+        positionClock();
+        // THEN the padding DOESN'T adjust for keyguard status height.
+        assertThat(mClockPosition.stackScrollerPaddingExpanded)
+                .isEqualTo(mClockPosition.clockYFullyDozing);
+    }
+
+    @Test
+    public void notifMinPaddingAlignedWithClockInSplitShadeMode() {
+        givenLockScreen();
+        mIsSplitShade = true;
+        mKeyguardStatusHeight = 200;
+        // WHEN the position algorithm is run
+        positionClock();
+        // THEN the padding DOESN'T adjust for keyguard status height.
+        assertThat(mClockPositionAlgorithm.getMinStackScrollerPadding())
+                .isEqualTo(mKeyguardStatusBarHeaderHeight);
+    }
+
+    @Test
     public void notifPositionWithLargeClockOnLockScreen() {
         // GIVEN on lock screen and clock has a nonzero height
         givenLockScreen();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
index 2369d8e..ead3291 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationPanelViewControllerTest.java
@@ -338,8 +338,6 @@
         when(mView.findViewById(R.id.keyguard_clock_container)).thenReturn(mKeyguardClockSwitch);
         when(mView.findViewById(R.id.notification_stack_scroller))
                 .thenReturn(mNotificationStackScrollLayout);
-        when(mNotificationStackScrollLayout.getController())
-                .thenReturn(mNotificationStackScrollLayoutController);
         when(mNotificationStackScrollLayoutController.getHeight()).thenReturn(1000);
         when(mNotificationStackScrollLayoutController.getHeadsUpCallback())
                 .thenReturn(mHeadsUpCallback);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
index c62d73c..6e9bb2d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/NotificationShadeWindowViewTest.java
@@ -34,7 +34,6 @@
 
 import com.android.keyguard.LockIconViewController;
 import com.android.systemui.R;
-import com.android.systemui.SystemUIFactory;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.classifier.FalsingCollectorFake;
 import com.android.systemui.dock.DockManager;
@@ -55,7 +54,6 @@
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.tuner.TunerService;
-import com.android.systemui.util.InjectionInflationController;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -117,10 +115,6 @@
         when(mDockManager.isDocked()).thenReturn(false);
 
         mController = new NotificationShadeWindowViewController(
-                new InjectionInflationController(
-                        SystemUIFactory.getInstance()
-                                .getSysUIComponent()
-                                .createViewInstanceCreatorFactory()),
                 mCoordinator,
                 mPulseExpansionHandler,
                 mDynamicPrivacyController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
index 033f689..310a8ba 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/PhoneStatusBarViewControllerTest.kt
@@ -19,19 +19,25 @@
 import android.view.LayoutInflater
 import android.view.MotionEvent
 import android.view.ViewGroup
+import android.view.ViewTreeObserver
+import android.view.ViewTreeObserver.OnPreDrawListener
 import android.widget.FrameLayout
 import androidx.test.filters.SmallTest
 import androidx.test.platform.app.InstrumentationRegistry
 import com.android.systemui.R
 import com.android.systemui.SysuiTestCase
+import com.android.systemui.unfold.config.UnfoldTransitionConfig
+import com.android.systemui.unfold.util.ScopedUnfoldTransitionProgressProvider
 import com.android.systemui.util.mockito.any
 import com.google.common.truth.Truth.assertThat
 import org.junit.Before
 import org.junit.Test
+import org.mockito.ArgumentCaptor
 import org.mockito.Mock
+import org.mockito.Mockito.spy
+import org.mockito.Mockito.mock
 import org.mockito.Mockito.`when`
 import org.mockito.Mockito.verify
-import org.mockito.Mockito.mock
 import org.mockito.MockitoAnnotations
 
 @SmallTest
@@ -48,10 +54,14 @@
 
     @Mock
     private lateinit var moveFromCenterAnimation: StatusBarMoveFromCenterAnimationController
+    @Mock
+    private lateinit var progressProvider: ScopedUnfoldTransitionProgressProvider
 
     private lateinit var view: PhoneStatusBarView
     private lateinit var controller: PhoneStatusBarViewController
 
+    private val unfoldConfig = UnfoldConfig()
+
     @Before
     fun setUp() {
         MockitoAnnotations.initMocks(this)
@@ -66,11 +76,7 @@
             view.setBar(mock(StatusBar::class.java))
         }
 
-        controller = PhoneStatusBarViewController(
-                view,
-                null,
-                touchEventHandler,
-        )
+        controller = createController(view)
     }
 
     @Test
@@ -83,12 +89,38 @@
     }
 
     @Test
-    fun constructor_moveFromCenterAnimationIsNotNull_moveFromCenterAnimationInitialized() {
-        controller = PhoneStatusBarViewController(
-                view, moveFromCenterAnimation, touchEventHandler
-        )
+    fun onViewAttachedAndDrawn_moveFromCenterAnimationEnabled_moveFromCenterAnimationInitialized() {
+        val view = createViewMock()
+        val argumentCaptor = ArgumentCaptor.forClass(OnPreDrawListener::class.java)
+        unfoldConfig.isEnabled = true
+        controller = createController(view)
+        controller.init()
 
-        verify(moveFromCenterAnimation).init(any(), any())
+        verify(view.viewTreeObserver).addOnPreDrawListener(argumentCaptor.capture())
+        argumentCaptor.value.onPreDraw()
+
+        verify(moveFromCenterAnimation).onViewsReady(any(), any())
+    }
+
+    private fun createViewMock(): PhoneStatusBarView {
+        val view = spy(view)
+        val viewTreeObserver = mock(ViewTreeObserver::class.java)
+        `when`(view.viewTreeObserver).thenReturn(viewTreeObserver)
+        `when`(view.isAttachedToWindow).thenReturn(true)
+        return view
+    }
+
+    private fun createController(view: PhoneStatusBarView): PhoneStatusBarViewController {
+        return PhoneStatusBarViewController.Factory(
+            { progressProvider },
+            { moveFromCenterAnimation },
+            unfoldConfig
+        ).create(view, touchEventHandler)
+    }
+
+    private class UnfoldConfig : UnfoldTransitionConfig {
+        override var isEnabled: Boolean = false
+        override var isHingeAngleEnabled: Boolean = false
     }
 
     private class TestTouchEventHandler : PhoneStatusBarView.TouchEventHandler {
@@ -97,6 +129,5 @@
             lastEvent = event
             return false
         }
-
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
new file mode 100644
index 0000000..a9e8164
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/SplitShadeHeaderControllerTest.kt
@@ -0,0 +1,87 @@
+package com.android.systemui.statusbar.phone
+
+import android.content.Context
+import android.content.res.Resources
+import android.test.suitebuilder.annotation.SmallTest
+import android.view.View
+import com.android.systemui.R
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.animation.ShadeInterpolation
+import com.android.systemui.battery.BatteryMeterView
+import com.android.systemui.battery.BatteryMeterViewController
+import com.android.systemui.flags.FeatureFlags
+import com.android.systemui.qs.carrier.QSCarrierGroupController
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Rule
+import org.junit.Test
+import org.mockito.ArgumentMatchers.any
+import org.mockito.ArgumentMatchers.anyInt
+import org.mockito.Mock
+import org.mockito.Mockito.`when` as whenever
+import org.mockito.Mockito.verify
+import org.mockito.junit.MockitoJUnit
+
+@SmallTest
+class SplitShadeHeaderControllerTest : SysuiTestCase() {
+
+    @Mock private lateinit var view: View
+    @Mock private lateinit var statusIcons: StatusIconContainer
+    @Mock private lateinit var statusBarIconController: StatusBarIconController
+    @Mock private lateinit var qsCarrierGroupController: QSCarrierGroupController
+    @Mock private lateinit var qsCarrierGroupControllerBuilder: QSCarrierGroupController.Builder
+    @Mock private lateinit var featureFlags: FeatureFlags
+    @Mock private lateinit var batteryMeterView: BatteryMeterView
+    @Mock private lateinit var batteryMeterViewController: BatteryMeterViewController
+    @Mock private lateinit var resources: Resources
+    @Mock private lateinit var context: Context
+    @JvmField @Rule val mockitoRule = MockitoJUnit.rule()
+    var viewVisibility = View.GONE
+
+    private lateinit var splitShadeHeaderController: SplitShadeHeaderController
+
+    @Before
+    fun setup() {
+        whenever<BatteryMeterView>(view.findViewById(R.id.batteryRemainingIcon))
+                .thenReturn(batteryMeterView)
+        whenever<StatusIconContainer>(view.findViewById(R.id.statusIcons)).thenReturn(statusIcons)
+        whenever(statusIcons.context).thenReturn(context)
+        whenever(context.resources).thenReturn(resources)
+        whenever(qsCarrierGroupControllerBuilder.setQSCarrierGroup(any()))
+                .thenReturn(qsCarrierGroupControllerBuilder)
+        whenever(qsCarrierGroupControllerBuilder.build()).thenReturn(qsCarrierGroupController)
+        whenever(view.setVisibility(anyInt())).then {
+            viewVisibility = it.arguments[0] as Int
+            null
+        }
+        whenever(view.visibility).thenAnswer { _ -> viewVisibility }
+        splitShadeHeaderController = SplitShadeHeaderController(view, statusBarIconController,
+        qsCarrierGroupControllerBuilder, featureFlags, batteryMeterViewController)
+    }
+
+    @Test
+    fun setVisible_onlyInSplitShade() {
+        splitShadeHeaderController.splitShadeMode = true
+        splitShadeHeaderController.shadeExpanded = true
+        assertThat(viewVisibility).isEqualTo(View.VISIBLE)
+
+        splitShadeHeaderController.splitShadeMode = false
+        assertThat(viewVisibility).isEqualTo(View.GONE)
+    }
+
+    @Test
+    fun updateListeners_registersWhenVisible() {
+        splitShadeHeaderController.splitShadeMode = true
+        splitShadeHeaderController.shadeExpanded = true
+        verify(qsCarrierGroupController).setListening(true)
+        verify(statusBarIconController).addIconGroup(any())
+    }
+
+    @Test
+    fun shadeExpandedFraction_updatesAlpha() {
+        splitShadeHeaderController.splitShadeMode = true
+        splitShadeHeaderController.shadeExpanded = true
+        splitShadeHeaderController.shadeExpandedFraction = 0.5f
+        verify(view).setAlpha(ShadeInterpolation.getContentAlpha(0.5f))
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
index 1503af8..e5158e7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarContentInsetsProviderTest.kt
@@ -86,7 +86,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         var chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
         /* 1080 - 20 (rounded corner) - 30 (chip),
@@ -115,7 +117,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         chipBounds = getPrivacyChipBoundingRectForInsets(bounds, dotWidth, chipWidth, isRtl)
         /* 2160 - 20 (rounded corner) - 30 (chip),
@@ -146,6 +150,8 @@
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
         val currentRotation = ROTATION_NONE
+        val isRtl = false
+        val dotWidth = 10
 
         `when`(dc.boundingRects).thenReturn(listOf(dcBounds))
 
@@ -164,7 +170,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
@@ -181,7 +189,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
@@ -200,7 +210,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
@@ -208,7 +220,7 @@
         targetRotation = ROTATION_SEASCAPE
         expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.height() - dcBounds.height(),
+                screenBounds.height() - dcBounds.height() - dotWidth,
                 sbHeightLandscape)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -218,7 +230,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
@@ -237,6 +251,8 @@
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
         val currentRotation = ROTATION_NONE
+        val isRtl = false
+        val dotWidth = 10
 
         `when`(dc.boundingRects).thenReturn(listOf(dcBounds))
 
@@ -255,7 +271,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
@@ -272,7 +290,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
@@ -289,14 +309,16 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_SEASCAPE
         expectedBounds = Rect(minLeftPadding,
                 0,
-                screenBounds.height() - dcBounds.height(),
+                screenBounds.height() - dcBounds.height() - dotWidth,
                 sbHeightLandscape)
 
         bounds = calculateInsetsForRotationWithRotatedResources(
@@ -306,7 +328,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
@@ -320,6 +344,8 @@
         val minRightPadding = 20
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
+        val isRtl = false
+        val dotWidth = 10
 
         // THEN content insets should only use rounded corner padding
         var targetRotation = ROTATION_NONE
@@ -335,7 +361,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_LANDSCAPE
@@ -351,7 +379,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_UPSIDE_DOWN
@@ -367,7 +397,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
 
         targetRotation = ROTATION_LANDSCAPE
@@ -383,7 +415,9 @@
                 screenBounds,
                 sbHeightLandscape,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
 
@@ -397,6 +431,8 @@
         val sbHeightPortrait = 100
         val sbHeightLandscape = 60
         val currentRotation = ROTATION_NONE
+        val isRtl = false
+        val dotWidth = 10
 
         `when`(dc.boundingRects).thenReturn(listOf(dcBounds))
 
@@ -414,7 +450,9 @@
                 screenBounds,
                 sbHeightPortrait,
                 minLeftPadding,
-                minRightPadding)
+                minRightPadding,
+                isRtl,
+                dotWidth)
 
         assertRects(expectedBounds, bounds, currentRotation, targetRotation)
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
index 3fcd071..2d944aa 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManagerTest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.statusbar.phone;
 
+import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyBoolean;
 import static org.mockito.ArgumentMatchers.anyFloat;
@@ -44,7 +45,6 @@
 import com.android.systemui.dock.DockManager;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.keyguard.DismissCallbackRegistry;
-import com.android.systemui.keyguard.FaceAuthScreenBrightnessController;
 import com.android.systemui.keyguard.WakefulnessLifecycle;
 import com.android.systemui.navigationbar.NavigationModeController;
 import com.android.systemui.plugins.ActivityStarter.OnDismissAction;
@@ -60,8 +60,6 @@
 import org.mockito.Mock;
 import org.mockito.MockitoAnnotations;
 
-import java.util.Optional;
-
 import dagger.Lazy;
 
 @SmallTest
@@ -92,8 +90,6 @@
     @Mock
     private KeyguardBypassController mBypassController;
     @Mock
-    private FaceAuthScreenBrightnessController mFaceAuthScreenBrightnessController;
-    @Mock
     private KeyguardBouncer.Factory mKeyguardBouncerFactory;
     @Mock
     private KeyguardMessageAreaController.Factory mKeyguardMessageAreaFactory;
@@ -102,6 +98,8 @@
     @Mock
     private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
     @Mock
+    private StatusBarKeyguardViewManager.AlternateAuthInterceptor mAlternateAuthInterceptor;
+    @Mock
     private KeyguardMessageArea mKeyguardMessageArea;
     @Mock
     private Lazy<ShadeController> mShadeController;
@@ -133,7 +131,6 @@
                 mock(DockManager.class),
                 mock(NotificationShadeWindowController.class),
                 mKeyguardStateController,
-                Optional.of(mFaceAuthScreenBrightnessController),
                 mock(NotificationMediaManager.class),
                 mKeyguardBouncerFactory,
                 mWakefulnessLifecycle,
@@ -293,6 +290,24 @@
     }
 
     @Test
+    public void testShowing_whenAlternateAuthShowing() {
+        mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+        when(mBouncer.isShowing()).thenReturn(false);
+        when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+        assertTrue("Is showing not accurate when alternative auth showing",
+                mStatusBarKeyguardViewManager.isShowing());
+    }
+
+    @Test
+    public void testWillBeShowing_whenAlternateAuthShowing() {
+        mStatusBarKeyguardViewManager.setAlternateAuthInterceptor(mAlternateAuthInterceptor);
+        when(mBouncer.isShowing()).thenReturn(false);
+        when(mAlternateAuthInterceptor.isShowingAlternateAuthBouncer()).thenReturn(true);
+        assertTrue("Is or will be showing not accurate when alternative auth showing",
+                mStatusBarKeyguardViewManager.bouncerIsOrWillBeShowing());
+    }
+
+    @Test
     public void testUpdateResources_delegatesToBouncer() {
         mStatusBarKeyguardViewManager.updateResources();
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
index c80c072..4e6b0a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/StatusBarNotificationPresenterTest.java
@@ -37,6 +37,7 @@
 import com.android.systemui.ForegroundServiceNotificationListener;
 import com.android.systemui.InitController;
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -51,6 +52,7 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProvider;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptSuppressor;
 import com.android.systemui.statusbar.notification.row.ActivatableNotificationView;
@@ -109,12 +111,15 @@
                 mock(DozeScrimController.class), mock(ScrimController.class),
                 mock(NotificationShadeWindowController.class), mock(DynamicPrivacyController.class),
                 mock(KeyguardStateController.class),
-                mock(KeyguardIndicationController.class), mStatusBar,
+                mock(KeyguardIndicationController.class),
+                mock(FeatureFlags.class),
+                mStatusBar,
                 mock(ShadeControllerImpl.class), mock(LockscreenShadeTransitionController.class),
                 mCommandQueue,
                 mock(NotificationViewHierarchyManager.class),
                 mock(NotificationLockscreenUserManager.class),
                 mock(SysuiStatusBarStateController.class),
+                mock(NotifShadeEventSource.class),
                 mock(NotificationEntryManager.class),
                 mock(NotificationMediaManager.class),
                 mock(NotificationGutsManager.class),
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 741d95f..f14b126 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
@@ -96,7 +96,7 @@
 import com.android.systemui.plugins.PluginDependencyProvider;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
 import com.android.systemui.recents.ScreenPinningRequest;
-import com.android.systemui.settings.brightness.BrightnessSlider;
+import com.android.systemui.settings.brightness.BrightnessSliderController;
 import com.android.systemui.shared.plugins.PluginManager;
 import com.android.systemui.statusbar.CommandQueue;
 import com.android.systemui.statusbar.KeyguardIndicationController;
@@ -121,6 +121,7 @@
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder;
 import com.android.systemui.statusbar.notification.collection.legacy.VisualStabilityManager;
+import com.android.systemui.statusbar.notification.collection.render.NotifShadeEventSource;
 import com.android.systemui.statusbar.notification.init.NotificationsController;
 import com.android.systemui.statusbar.notification.interruption.BypassHeadsUpNotifier;
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl;
@@ -144,6 +145,7 @@
 import com.android.systemui.unfold.UnfoldLightRevealOverlayAnimation;
 import com.android.systemui.unfold.UnfoldTransitionWallpaperController;
 import com.android.systemui.unfold.config.UnfoldTransitionConfig;
+import com.android.systemui.unfold.util.NaturalRotationUnfoldProgressProvider;
 import com.android.systemui.util.WallpaperController;
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.concurrency.MessageRouterImpl;
@@ -209,6 +211,7 @@
     @Mock private NotificationShadeWindowView mNotificationShadeWindowView;
     @Mock private BroadcastDispatcher mBroadcastDispatcher;
     @Mock private AssistManager mAssistManager;
+    @Mock private NotifShadeEventSource mNotifShadeEventSource;
     @Mock private NotificationEntryManager mNotificationEntryManager;
     @Mock private NotificationGutsManager mNotificationGutsManager;
     @Mock private NotificationMediaManager mNotificationMediaManager;
@@ -256,10 +259,10 @@
     @Mock private PhoneStatusBarPolicy mPhoneStatusBarPolicy;
     @Mock private DemoModeController mDemoModeController;
     @Mock private Lazy<NotificationShadeDepthController> mNotificationShadeDepthControllerLazy;
-    @Mock private BrightnessSlider.Factory mBrightnessSliderFactory;
+    @Mock private BrightnessSliderController.Factory mBrightnessSliderFactory;
     @Mock private UnfoldTransitionConfig mUnfoldTransitionConfig;
     @Mock private Lazy<UnfoldLightRevealOverlayAnimation> mUnfoldLightRevealOverlayAnimationLazy;
-    @Mock private Lazy<StatusBarMoveFromCenterAnimationController> mMoveFromCenterAnimationLazy;
+    @Mock private Lazy<NaturalRotationUnfoldProgressProvider> mNaturalRotationProgressProvider;
     @Mock private Lazy<UnfoldTransitionWallpaperController> mUnfoldWallpaperController;
     @Mock private WallpaperController mWallpaperController;
     @Mock private OngoingCallController mOngoingCallController;
@@ -276,6 +279,7 @@
     @Mock private StartingSurface mStartingSurface;
     @Mock private OperatorNameViewController mOperatorNameViewController;
     @Mock private OperatorNameViewController.Factory mOperatorNameViewControllerFactory;
+    @Mock private PhoneStatusBarViewController.Factory mPhoneStatusBarViewControllerFactory;
     @Mock private ActivityLaunchAnimator mActivityLaunchAnimator;
     @Mock private DialogLaunchAnimator mDialogLaunchAnimator;
     private ShadeController mShadeController;
@@ -314,7 +318,6 @@
 
         mContext.setTheme(R.style.Theme_SystemUI_LightWallpaper);
 
-        when(mStackScroller.getController()).thenReturn(mStackScrollerController);
         when(mStackScrollerController.getView()).thenReturn(mStackScroller);
         when(mStackScrollerController.getNotificationListContainer()).thenReturn(
                 mNotificationListContainer);
@@ -376,6 +379,7 @@
                 new FalsingManagerFake(),
                 new FalsingCollectorFake(),
                 mBroadcastDispatcher,
+                mNotifShadeEventSource,
                 mNotificationEntryManager,
                 mNotificationGutsManager,
                 notificationLogger,
@@ -430,6 +434,7 @@
                 mExtensionController,
                 mUserInfoControllerImpl,
                 mOperatorNameViewControllerFactory,
+                mPhoneStatusBarViewControllerFactory,
                 mPhoneStatusBarPolicy,
                 mKeyguardIndicationController,
                 mDemoModeController,
@@ -440,7 +445,7 @@
                 mUnfoldTransitionConfig,
                 mUnfoldLightRevealOverlayAnimationLazy,
                 mUnfoldWallpaperController,
-                mMoveFromCenterAnimationLazy,
+                mNaturalRotationProgressProvider,
                 mWallpaperController,
                 mOngoingCallController,
                 mAnimationScheduler,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
new file mode 100644
index 0000000..a8a33da
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/UnlockedScreenOffAnimationControllerTest.kt
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.phone
+
+import android.animation.Animator
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper.RunWithLooper
+import android.view.View
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.keyguard.KeyguardViewMediator
+import com.android.systemui.keyguard.WakefulnessLifecycle
+import com.android.systemui.statusbar.LightRevealScrim
+import com.android.systemui.statusbar.StatusBarStateControllerImpl
+import com.android.systemui.statusbar.policy.KeyguardStateController
+import com.android.systemui.util.settings.GlobalSettings
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito
+import org.mockito.Mockito.spy
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@RunWithLooper(setAsMainLooper = true)
+class UnlockedScreenOffAnimationControllerTest : SysuiTestCase() {
+
+    private lateinit var controller: UnlockedScreenOffAnimationController
+    @Mock
+    private lateinit var keyguardViewMediator: KeyguardViewMediator
+    @Mock
+    private lateinit var dozeParameters: DozeParameters
+    @Mock
+    private lateinit var keyguardStateController: KeyguardStateController
+    @Mock
+    private lateinit var globalSettings: GlobalSettings
+    @Mock
+    private lateinit var statusbar: StatusBar
+    @Mock
+    private lateinit var lightRevealScrim: LightRevealScrim
+    @Mock
+    private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
+    @Mock
+    private lateinit var statusBarStateController: StatusBarStateControllerImpl
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        controller = UnlockedScreenOffAnimationController(
+                context,
+                wakefulnessLifecycle,
+                statusBarStateController,
+                dagger.Lazy<KeyguardViewMediator> { keyguardViewMediator },
+                keyguardStateController,
+                dagger.Lazy<DozeParameters> { dozeParameters },
+                globalSettings
+        )
+        controller.initialize(statusbar, lightRevealScrim)
+    }
+
+    @Test
+    fun testAnimClearsEndListener() {
+        val keyguardView = View(context)
+        val animator = spy(keyguardView.animate())
+        val keyguardSpy = spy(keyguardView)
+        Mockito.`when`(keyguardSpy.animate()).thenReturn(animator)
+        val listener = ArgumentCaptor.forClass(Animator.AnimatorListener::class.java)
+        controller.animateInKeyguard(keyguardSpy, Runnable {})
+        Mockito.verify(animator).setListener(listener.capture())
+        // Verify that the listener is cleared when it ends
+        listener.value.onAnimationEnd(null)
+        Mockito.verify(animator).setListener(null)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
new file mode 100644
index 0000000..5129f85
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/policy/DeviceProvisionedControllerImplTest.kt
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.policy
+
+import android.os.Handler
+import android.provider.Settings
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.dump.DumpManager
+import com.android.systemui.settings.UserTracker
+import com.android.systemui.util.concurrency.FakeExecutor
+import com.android.systemui.util.mockito.any
+import com.android.systemui.util.mockito.capture
+import com.android.systemui.util.settings.FakeSettings
+import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Captor
+import org.mockito.Mock
+import org.mockito.Mockito.`when`
+import org.mockito.Mockito.never
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class DeviceProvisionedControllerImplTest : SysuiTestCase() {
+
+    companion object {
+        private const val START_USER = 0
+    }
+
+    private lateinit var controller: DeviceProvisionedControllerImpl
+
+    @Mock
+    private lateinit var userTracker: UserTracker
+    @Mock
+    private lateinit var dumpManager: DumpManager
+    @Mock
+    private lateinit var listener: DeviceProvisionedController.DeviceProvisionedListener
+    @Captor
+    private lateinit var userTrackerCallbackCaptor: ArgumentCaptor<UserTracker.Callback>
+
+    private lateinit var mainExecutor: FakeExecutor
+    private lateinit var testableLooper: TestableLooper
+    private lateinit var settings: FakeSettings
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+        testableLooper = TestableLooper.get(this)
+        mainExecutor = FakeExecutor(FakeSystemClock())
+        settings = FakeSettings()
+        `when`(userTracker.userId).thenReturn(START_USER)
+
+        controller = DeviceProvisionedControllerImpl(
+                settings,
+                settings,
+                userTracker,
+                dumpManager,
+                Handler(testableLooper.looper),
+                mainExecutor
+        )
+    }
+
+    @Test
+    fun testNotProvisionedByDefault() {
+        init()
+        assertThat(controller.isDeviceProvisioned).isFalse()
+    }
+
+    @Test
+    fun testNotUserSetupByDefault() {
+        init()
+        assertThat(controller.isUserSetup(START_USER)).isFalse()
+    }
+
+    @Test
+    fun testProvisionedWhenCreated() {
+        settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
+        init()
+
+        assertThat(controller.isDeviceProvisioned).isTrue()
+    }
+
+    @Test
+    fun testUserSetupWhenCreated() {
+        settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
+        init()
+
+        assertThat(controller.isUserSetup(START_USER))
+    }
+
+    @Test
+    fun testDeviceProvisionedChange() {
+        init()
+
+        settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
+        testableLooper.processAllMessages() // background observer
+
+        assertThat(controller.isDeviceProvisioned).isTrue()
+    }
+
+    @Test
+    fun testUserSetupChange() {
+        init()
+
+        settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
+        testableLooper.processAllMessages() // background observer
+
+        assertThat(controller.isUserSetup(START_USER)).isTrue()
+    }
+
+    @Test
+    fun testUserSetupChange_otherUser() {
+        init()
+        val otherUser = 10
+
+        settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, otherUser)
+        testableLooper.processAllMessages() // background observer
+
+        assertThat(controller.isUserSetup(START_USER)).isFalse()
+        assertThat(controller.isUserSetup(otherUser)).isTrue()
+    }
+
+    @Test
+    fun testCurrentUserSetup() {
+        val otherUser = 10
+        settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, otherUser)
+        init()
+
+        assertThat(controller.isCurrentUserSetup).isFalse()
+        switchUser(otherUser)
+        testableLooper.processAllMessages()
+
+        assertThat(controller.isCurrentUserSetup).isTrue()
+    }
+
+    @Test
+    fun testListenerNotCalledOnAdd() {
+        init()
+        controller.addCallback(listener)
+
+        mainExecutor.runAllReady()
+
+        verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener, never()).onUserSetupChanged()
+        verify(listener, never()).onUserSwitched()
+    }
+
+    @Test
+    fun testListenerCalledOnUserSwitched() {
+        init()
+        controller.addCallback(listener)
+
+        switchUser(10)
+
+        testableLooper.processAllMessages()
+        mainExecutor.runAllReady()
+
+        verify(listener).onUserSwitched()
+        verify(listener, never()).onUserSetupChanged()
+        verify(listener, never()).onDeviceProvisionedChanged()
+    }
+
+    @Test
+    fun testListenerCalledOnUserSetupChanged() {
+        init()
+        controller.addCallback(listener)
+
+        settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
+        testableLooper.processAllMessages()
+        mainExecutor.runAllReady()
+
+        verify(listener, never()).onUserSwitched()
+        verify(listener).onUserSetupChanged()
+        verify(listener, never()).onDeviceProvisionedChanged()
+    }
+
+    @Test
+    fun testListenerCalledOnDeviceProvisionedChanged() {
+        init()
+        controller.addCallback(listener)
+
+        settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
+        testableLooper.processAllMessages()
+        mainExecutor.runAllReady()
+
+        verify(listener, never()).onUserSwitched()
+        verify(listener, never()).onUserSetupChanged()
+        verify(listener).onDeviceProvisionedChanged()
+    }
+
+    @Test
+    fun testRemoveListener() {
+        init()
+        controller.addCallback(listener)
+        controller.removeCallback(listener)
+
+        switchUser(10)
+        settings.putIntForUser(Settings.Secure.USER_SETUP_COMPLETE, 1, START_USER)
+        settings.putInt(Settings.Global.DEVICE_PROVISIONED, 1)
+
+        testableLooper.processAllMessages()
+        mainExecutor.runAllReady()
+
+        verify(listener, never()).onDeviceProvisionedChanged()
+        verify(listener, never()).onUserSetupChanged()
+        verify(listener, never()).onUserSwitched()
+    }
+
+    private fun init() {
+        controller.init()
+        verify(userTracker).addCallback(capture(userTrackerCallbackCaptor), any())
+    }
+
+    private fun switchUser(toUser: Int) {
+        `when`(userTracker.userId).thenReturn(toUser)
+        userTrackerCallbackCaptor.value.onUserChanged(toUser, mContext)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
new file mode 100644
index 0000000..a3f17aa
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/unfold/util/NaturalRotationUnfoldProgressProviderTest.kt
@@ -0,0 +1,139 @@
+/*
+ * Copyright (C) 2021 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.unfold.util
+
+import android.testing.AndroidTestingRunner
+import android.view.IRotationWatcher
+import android.view.IWindowManager
+import android.view.Surface
+import androidx.test.filters.SmallTest
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider
+import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener
+import com.android.systemui.util.mockito.any
+import com.android.systemui.SysuiTestCase
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentCaptor
+import org.mockito.Mock
+import org.mockito.Mockito.verify
+import org.mockito.Mockito.clearInvocations
+import org.mockito.Mockito.never
+import org.mockito.MockitoAnnotations
+
+@RunWith(AndroidTestingRunner::class)
+@SmallTest
+class NaturalRotationUnfoldProgressProviderTest : SysuiTestCase() {
+
+    @Mock
+    lateinit var windowManager: IWindowManager
+
+    @Mock
+    lateinit var sourceProvider: UnfoldTransitionProgressProvider
+
+    @Mock
+    lateinit var transitionListener: TransitionProgressListener
+
+    lateinit var progressProvider: NaturalRotationUnfoldProgressProvider
+
+    private val sourceProviderListenerCaptor =
+        ArgumentCaptor.forClass(TransitionProgressListener::class.java)
+    private val rotationWatcherCaptor =
+        ArgumentCaptor.forClass(IRotationWatcher.Stub::class.java)
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+
+        progressProvider = NaturalRotationUnfoldProgressProvider(
+            context,
+            windowManager,
+            sourceProvider
+        )
+
+        progressProvider.init()
+
+        verify(sourceProvider).addCallback(sourceProviderListenerCaptor.capture())
+        verify(windowManager).watchRotation(rotationWatcherCaptor.capture(), any())
+
+        progressProvider.addCallback(transitionListener)
+    }
+
+    @Test
+    fun testNaturalRotation0_sendTransitionStartedEvent_eventReceived() {
+        onRotationChanged(Surface.ROTATION_0)
+
+        source.onTransitionStarted()
+
+        verify(transitionListener).onTransitionStarted()
+    }
+
+    @Test
+    fun testNaturalRotation0_sendTransitionProgressEvent_eventReceived() {
+        onRotationChanged(Surface.ROTATION_0)
+
+        source.onTransitionProgress(0.5f)
+
+        verify(transitionListener).onTransitionProgress(0.5f)
+    }
+
+    @Test
+    fun testNotNaturalRotation90_sendTransitionStartedEvent_eventNotReceived() {
+        onRotationChanged(Surface.ROTATION_90)
+
+        source.onTransitionStarted()
+
+        verify(transitionListener, never()).onTransitionStarted()
+    }
+
+    @Test
+    fun testNaturalRotation90_sendTransitionProgressEvent_eventNotReceived() {
+        onRotationChanged(Surface.ROTATION_90)
+
+        source.onTransitionProgress(0.5f)
+
+        verify(transitionListener, never()).onTransitionProgress(0.5f)
+    }
+
+    @Test
+    fun testRotationBecameUnnaturalDuringTransition_sendsTransitionFinishedEvent() {
+        onRotationChanged(Surface.ROTATION_0)
+        source.onTransitionStarted()
+        clearInvocations(transitionListener)
+
+        onRotationChanged(Surface.ROTATION_90)
+
+        verify(transitionListener).onTransitionFinished()
+    }
+
+    @Test
+    fun testRotationBecameNaturalDuringTransition_sendsTransitionStartedEvent() {
+        onRotationChanged(Surface.ROTATION_90)
+        source.onTransitionStarted()
+        clearInvocations(transitionListener)
+
+        onRotationChanged(Surface.ROTATION_0)
+
+        verify(transitionListener).onTransitionStarted()
+    }
+
+    private fun onRotationChanged(rotation: Int) {
+        rotationWatcherCaptor.value.onRotationChanged(rotation)
+    }
+
+    private val source: TransitionProgressListener
+        get() = sourceProviderListenerCaptor.value
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt b/packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
new file mode 100644
index 0000000..2662da2
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/ListenerSetTest.kt
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2021 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.util
+
+import android.test.suitebuilder.annotation.SmallTest
+import androidx.test.runner.AndroidJUnit4
+import com.android.systemui.SysuiTestCase
+import com.google.common.truth.Truth.assertThat
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+class ListenerSetTest : SysuiTestCase() {
+
+    var runnableSet: ListenerSet<Runnable> = ListenerSet()
+
+    @Before
+    fun setup() {
+        runnableSet = ListenerSet()
+    }
+
+    @Test
+    fun addIfAbsent_doesNotDoubleAdd() {
+        // setup & preconditions
+        val runnable1 = Runnable { }
+        val runnable2 = Runnable { }
+        assertThat(runnableSet.toList()).isEmpty()
+
+        // Test that an element can be added
+        assertThat(runnableSet.addIfAbsent(runnable1)).isTrue()
+        assertThat(runnableSet.toList()).containsExactly(runnable1)
+
+        // Test that a second element can be added
+        assertThat(runnableSet.addIfAbsent(runnable2)).isTrue()
+        assertThat(runnableSet.toList()).containsExactly(runnable1, runnable2)
+
+        // Test that re-adding the first element does nothing and returns false
+        assertThat(runnableSet.addIfAbsent(runnable1)).isFalse()
+        assertThat(runnableSet.toList()).containsExactly(runnable1, runnable2)
+    }
+
+    @Test
+    fun remove_removesListener() {
+        // setup and preconditions
+        val runnable1 = Runnable { }
+        val runnable2 = Runnable { }
+        assertThat(runnableSet.toList()).isEmpty()
+        runnableSet.addIfAbsent(runnable1)
+        runnableSet.addIfAbsent(runnable2)
+        assertThat(runnableSet.toList()).containsExactly(runnable1, runnable2)
+
+        // Test that removing the first runnable only removes that one runnable
+        assertThat(runnableSet.remove(runnable1)).isTrue()
+        assertThat(runnableSet.toList()).containsExactly(runnable2)
+
+        // Test that removing a non-present runnable does not error
+        assertThat(runnableSet.remove(runnable1)).isFalse()
+        assertThat(runnableSet.toList()).containsExactly(runnable2)
+
+        // Test that removing the other runnable succeeds
+        assertThat(runnableSet.remove(runnable2)).isTrue()
+        assertThat(runnableSet.toList()).isEmpty()
+    }
+
+    @Test
+    fun remove_isReentrantSafe() {
+        // Setup and preconditions
+        val runnablesCalled = mutableListOf<Int>()
+        // runnable1 is configured to remove itself
+        val runnable1 = object : Runnable {
+            override fun run() {
+                runnableSet.remove(this)
+                runnablesCalled.add(1)
+            }
+        }
+        val runnable2 = Runnable {
+            runnablesCalled.add(2)
+        }
+        assertThat(runnableSet.toList()).isEmpty()
+        runnableSet.addIfAbsent(runnable1)
+        runnableSet.addIfAbsent(runnable2)
+        assertThat(runnableSet.toList()).containsExactly(runnable1, runnable2)
+
+        // Test that both runnables are called and 1 was removed
+        for (runnable in runnableSet) {
+            runnable.run()
+        }
+        assertThat(runnablesCalled).containsExactly(1, 2)
+        assertThat(runnableSet.toList()).containsExactly(runnable2)
+    }
+
+    @Test
+    fun addIfAbsent_isReentrantSafe() {
+        // Setup and preconditions
+        val runnablesCalled = mutableListOf<Int>()
+        val runnable99 = Runnable {
+            runnablesCalled.add(99)
+        }
+        // runnable1 is configured to add runnable99
+        val runnable1 = Runnable {
+            runnableSet.addIfAbsent(runnable99)
+            runnablesCalled.add(1)
+        }
+        val runnable2 = Runnable {
+            runnablesCalled.add(2)
+        }
+        assertThat(runnableSet.toList()).isEmpty()
+        runnableSet.addIfAbsent(runnable1)
+        runnableSet.addIfAbsent(runnable2)
+        assertThat(runnableSet.toList()).containsExactly(runnable1, runnable2)
+
+        // Test that both original runnables are called and 99 was added but not called
+        for (runnable in runnableSet) {
+            runnable.run()
+        }
+        assertThat(runnablesCalled).containsExactly(1, 2)
+        assertThat(runnableSet.toList()).containsExactly(runnable1, runnable2, runnable99)
+    }
+}
\ No newline at end of file
diff --git a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
index bff99bf..483dc9f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/util/mockito/KotlinMockitoHelpers.kt
@@ -58,3 +58,24 @@
  */
 inline fun <reified T : Any> argumentCaptor(): ArgumentCaptor<T> =
         ArgumentCaptor.forClass(T::class.java)
+
+/**
+ * Helper function for creating new mocks, without the need to pass in a [Class] instance.
+ *
+ * Generic T is nullable because implicitly bounded by Any?.
+ */
+inline fun <reified T : Any> mock(): T = Mockito.mock(T::class.java)
+
+/**
+ * Helper function for creating and using a single-use ArgumentCaptor in kotlin.
+ *
+ *    val captor = argumentCaptor<Foo>()
+ *    verify(...).someMethod(captor.capture())
+ *    val captured = captor.value
+ *
+ * becomes:
+ *
+ *    val captured = withArgCaptor<Foo> { verify(...).someMethod(capture()) }
+ */
+inline fun <reified T : Any> withArgCaptor(block: ArgumentCaptor<T>.() -> Unit): T =
+        argumentCaptor<T>().apply { block() }.value
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">28dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
index 9254b4d..c340432 100644
--- a/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationCornerOverlay/res/values/config.xml
@@ -44,14 +44,6 @@
      -->
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">48dp</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-
 </resources>
 
 
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">28dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
index 80c997a..928d9df 100644
--- a/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationDoubleOverlay/res/values/config.xml
@@ -56,14 +56,6 @@
      -->
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">48dp</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-
 </resources>
 
 
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-land/config.xml
deleted file mode 100644
index 2e971de..0000000
--- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">28dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
diff --git a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml
index 9f558d0..62f0535 100644
--- a/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationHoleOverlay/res/values/config.xml
@@ -48,14 +48,6 @@
      -->
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">136px</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar) -->
-    <dimen name="quick_qs_offset_height">136px</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">488px</dimen>
-
 </resources>
 
 
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">28dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
index 6fb3c7f..a9f8b4b 100644
--- a/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationNarrowOverlay/res/values/config.xml
@@ -47,14 +47,6 @@
      -->
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">48dp</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-
 </resources>
 
 
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">28dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
index 7c29ffb..be7d0e4 100644
--- a/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationTallOverlay/res/values/config.xml
@@ -47,14 +47,6 @@
      -->
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">48dp</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-
 </resources>
 
 
diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values-land/config.xml
deleted file mode 100644
index df2f3d1..0000000
--- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2020 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.
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml
index 8d0227e..cc51ebe 100644
--- a/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWaterfallOverlay/res/values/config.xml
@@ -19,16 +19,6 @@
     <string translatable="false" name="config_mainBuiltInDisplayCutout"></string>
     <string translatable="false" name="config_mainBuiltInDisplayCutoutRectApproximation"></string>
 
-    <!-- Height of the status bar in portrait. The height should be
-         Max((status bar content height + waterfall top size), top cutout size) -->
-    <dimen name="status_bar_height_portrait">28dp</dimen>
-    <!-- Max((28 + 20), 0) = 48 -->
-    <dimen name="status_bar_height_landscape">48dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-
     <dimen name="waterfall_display_left_edge_size">20dp</dimen>
     <dimen name="waterfall_display_top_edge_size">0dp</dimen>
     <dimen name="waterfall_display_right_edge_size">20dp</dimen>
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
deleted file mode 100644
index bd52901..0000000
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values-land/config.xml
+++ /dev/null
@@ -1,22 +0,0 @@
-<!--
-  ~ Copyright (C) 2018 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
-  -->
-
-<resources>
-    <!-- Can't link to other dimensions here, but this should be status_bar_height_landscape -->
-    <dimen name="quick_qs_offset_height">28dp</dimen>
-    <!-- Total height of QQS in landscape; quick_qs_offset_height + 128 -->
-    <dimen name="quick_qs_total_height">156dp</dimen>
-</resources>
\ No newline at end of file
diff --git a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
index 5fb8b9e..78cc7e0 100644
--- a/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
+++ b/packages/overlays/DisplayCutoutEmulationWideOverlay/res/values/config.xml
@@ -47,14 +47,6 @@
      -->
     <bool name="config_fillMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">48dp</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
-
 </resources>
 
 
diff --git a/packages/overlays/NoCutoutOverlay/res/values/config.xml b/packages/overlays/NoCutoutOverlay/res/values/config.xml
index 9157699..84b91b8 100644
--- a/packages/overlays/NoCutoutOverlay/res/values/config.xml
+++ b/packages/overlays/NoCutoutOverlay/res/values/config.xml
@@ -25,12 +25,4 @@
          by shrinking the display such that it does not overlap the cutout area. -->
     <bool name="config_maskMainBuiltInDisplayCutout">true</bool>
 
-    <!-- Height of the status bar -->
-    <dimen name="status_bar_height_portrait">28dp</dimen>
-    <dimen name="status_bar_height_landscape">28dp</dimen>
-
-    <!-- Height of area above QQS where battery/time go (equal to status bar height if > 48dp) -->
-    <dimen name="quick_qs_offset_height">48dp</dimen>
-    <!-- Total height of QQS (quick_qs_offset_height + 128) -->
-    <dimen name="quick_qs_total_height">176dp</dimen>
 </resources>
diff --git a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
index 6374d34..cf4c8a3 100644
--- a/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
+++ b/services/core/java/com/android/server/am/BatteryExternalStatsWorker.java
@@ -669,12 +669,10 @@
             if (measuredEnergyDeltas != null) {
                 final long[] displayChargeUC = measuredEnergyDeltas.displayChargeUC;
                 if (displayChargeUC != null && displayChargeUC.length > 0) {
-                    // TODO (b/194107383): pass all display ordinals to mStats with
-                    //  displayScreenStates
-                    final long primaryDisplayChargeUC = displayChargeUC[0];
-                    // If updating, pass in what BatteryExternalStatsWorker thinks screenState is.
-                    mStats.updateDisplayMeasuredEnergyStatsLocked(primaryDisplayChargeUC,
-                            screenState, elapsedRealtime);
+                    // If updating, pass in what BatteryExternalStatsWorker thinks
+                    // displayScreenStates is.
+                    mStats.updateDisplayMeasuredEnergyStatsLocked(displayChargeUC,
+                            displayScreenStates, elapsedRealtime);
                 }
 
                 final long gnssChargeUC = measuredEnergyDeltas.gnssChargeUC;
diff --git a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
index 85d6d7f..031f6ee 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -360,6 +360,43 @@
         }
     }
 
+    /**
+     * Only call this method on interfaces where lockout does not come from onError, I.E. the
+     * old HIDL implementation.
+     */
+    protected void onLockoutTimed(long durationMillis) {
+        final ClientMonitorCallbackConverter listener = getListener();
+        final CoexCoordinator coordinator = CoexCoordinator.getInstance();
+        coordinator.onAuthenticationError(this, BiometricConstants.BIOMETRIC_ERROR_LOCKOUT,
+                new CoexCoordinator.ErrorCallback() {
+            @Override
+            public void sendHapticFeedback() {
+                if (listener != null && mShouldVibrate) {
+                    vibrateError();
+                }
+            }
+        });
+    }
+
+    /**
+     * Only call this method on interfaces where lockout does not come from onError, I.E. the
+     * old HIDL implementation.
+     */
+    protected void onLockoutPermanent() {
+        final ClientMonitorCallbackConverter listener = getListener();
+        final CoexCoordinator coordinator = CoexCoordinator.getInstance();
+        coordinator.onAuthenticationError(this,
+                BiometricConstants.BIOMETRIC_ERROR_LOCKOUT_PERMANENT,
+                new CoexCoordinator.ErrorCallback() {
+            @Override
+            public void sendHapticFeedback() {
+                if (listener != null && mShouldVibrate) {
+                    vibrateError();
+                }
+            }
+        });
+    }
+
     private void sendCancelOnly(@Nullable ClientMonitorCallbackConverter listener) {
         if (listener == null) {
             Slog.e(TAG, "Unable to sendAuthenticationCanceled, listener null");
diff --git a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
index cbceba6..97d791b 100644
--- a/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/face/aidl/FaceAuthenticationClient.java
@@ -225,6 +225,7 @@
 
     @Override
     public void onLockoutTimed(long durationMillis) {
+        super.onLockoutTimed(durationMillis);
         mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_TIMED);
         // Lockout metrics are logged as an error code.
         final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT;
@@ -239,6 +240,7 @@
 
     @Override
     public void onLockoutPermanent() {
+        super.onLockoutPermanent();
         mLockoutCache.setLockoutModeForUser(getTargetUserId(), LockoutTracker.LOCKOUT_PERMANENT);
         // Lockout metrics are logged as an error code.
         final int error = BiometricFaceConstants.FACE_ERROR_LOCKOUT_PERMANENT;
diff --git a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
index 0050a89..be0e6ed 100644
--- a/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
+++ b/services/core/java/com/android/server/biometrics/sensors/fingerprint/FingerprintStateCallback.java
@@ -23,7 +23,6 @@
 import static android.hardware.fingerprint.FingerprintStateListener.STATE_KEYGUARD_AUTH;
 
 import android.annotation.NonNull;
-import android.content.Context;
 import android.hardware.fingerprint.FingerprintStateListener;
 import android.hardware.fingerprint.IFingerprintStateListener;
 import android.os.RemoteException;
@@ -34,8 +33,6 @@
 import com.android.server.biometrics.sensors.BaseClientMonitor;
 import com.android.server.biometrics.sensors.EnrollClient;
 import com.android.server.biometrics.sensors.EnrollmentModifier;
-import com.android.server.biometrics.sensors.RemovalConsumer;
-import com.android.server.biometrics.sensors.fingerprint.hidl.FingerprintEnrollClient;
 
 import java.util.concurrent.CopyOnWriteArrayList;
 
@@ -70,7 +67,7 @@
             } else {
                 mFingerprintState = STATE_AUTH_OTHER;
             }
-        } else if (client instanceof FingerprintEnrollClient) {
+        } else if (client instanceof EnrollClient) {
             mFingerprintState = STATE_ENROLLING;
         } else {
             Slog.w(FingerprintService.TAG,
@@ -143,6 +140,7 @@
     /**
      * Enables clients to register a FingerprintStateListener. Used by FingerprintService to forward
      * updates in fingerprint sensor state to the SideFpNsEventHandler
+     *
      * @param listener
      */
     public void registerFingerprintStateListener(@NonNull IFingerprintStateListener listener) {
diff --git a/services/core/java/com/android/server/camera/CameraServiceProxy.java b/services/core/java/com/android/server/camera/CameraServiceProxy.java
index 42b676f..9d2cff9 100644
--- a/services/core/java/com/android/server/camera/CameraServiceProxy.java
+++ b/services/core/java/com/android/server/camera/CameraServiceProxy.java
@@ -15,6 +15,7 @@
  */
 package com.android.server.camera;
 
+import static android.content.pm.ActivityInfo.RESIZE_MODE_UNRESIZEABLE;
 import static android.os.Build.VERSION_CODES.M;
 
 import android.annotation.IntDef;
@@ -39,7 +40,9 @@
 import android.hardware.CameraStreamStats;
 import android.hardware.ICameraService;
 import android.hardware.ICameraServiceProxy;
+import android.hardware.camera2.CameraCharacteristics;
 import android.hardware.camera2.CameraMetadata;
+import android.hardware.camera2.CaptureRequest;
 import android.hardware.devicestate.DeviceStateManager;
 import android.hardware.devicestate.DeviceStateManager.FoldStateListener;
 import android.hardware.display.DisplayManager;
@@ -346,13 +349,13 @@
 
     private final TaskStateHandler mTaskStackListener = new TaskStateHandler();
 
-    private final class TaskInfo {
-        private int frontTaskId;
-        private boolean isResizeable;
-        private boolean isFixedOrientationLandscape;
-        private boolean isFixedOrientationPortrait;
-        private int displayId;
-        private int userId;
+    public static final class TaskInfo {
+        public int frontTaskId;
+        public boolean isResizeable;
+        public boolean isFixedOrientationLandscape;
+        public boolean isFixedOrientationPortrait;
+        public int displayId;
+        public int userId;
     }
 
     private final class TaskStateHandler extends TaskStackListener {
@@ -367,7 +370,8 @@
             synchronized (mMapLock) {
                 TaskInfo info = new TaskInfo();
                 info.frontTaskId = taskInfo.taskId;
-                info.isResizeable = taskInfo.isResizeable;
+                info.isResizeable =
+                        (taskInfo.topActivityInfo.resizeMode != RESIZE_MODE_UNRESIZEABLE);
                 info.displayId = taskInfo.displayId;
                 info.userId = taskInfo.userId;
                 info.isFixedOrientationLandscape = ActivityInfo.isFixedOrientationLandscape(
@@ -427,97 +431,108 @@
         }
     };
 
-    private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
-        private boolean isMOrBelow(Context ctx, String packageName) {
-            try {
-                return ctx.getPackageManager().getPackageInfo(
-                        packageName, 0).applicationInfo.targetSdkVersion <= M;
-            } catch (PackageManager.NameNotFoundException e) {
-                Slog.e(TAG,"Package name not found!");
-            }
-            return false;
+    private static boolean isMOrBelow(Context ctx, String packageName) {
+        try {
+            return ctx.getPackageManager().getPackageInfo(
+                    packageName, 0).applicationInfo.targetSdkVersion <= M;
+        } catch (PackageManager.NameNotFoundException e) {
+            Slog.e(TAG,"Package name not found!");
+        }
+        return false;
+    }
+
+    /**
+     * Estimate the app crop-rotate-scale compensation value.
+     */
+    public static int getCropRotateScale(@NonNull Context ctx, @NonNull String packageName,
+            @Nullable TaskInfo taskInfo, int displayRotation, int lensFacing,
+            boolean ignoreResizableAndSdkCheck) {
+        if (taskInfo == null) {
+            return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
         }
 
-        /**
-         * Gets whether crop-rotate-scale is needed.
-         */
-        private boolean getNeedCropRotateScale(@NonNull Context ctx, @NonNull String packageName,
-                @Nullable TaskInfo taskInfo, int sensorOrientation, int lensFacing,
-                boolean ignoreResizableAndSdkCheck) {
-            if (taskInfo == null) {
-                return false;
-            }
+        // External cameras do not need crop-rotate-scale.
+        if (lensFacing != CameraMetadata.LENS_FACING_FRONT
+                && lensFacing != CameraMetadata.LENS_FACING_BACK) {
+            Log.v(TAG, "lensFacing=" + lensFacing + ". Crop-rotate-scale is disabled.");
+            return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+        }
 
-            // External cameras do not need crop-rotate-scale.
-            if (lensFacing != CameraMetadata.LENS_FACING_FRONT
-                    && lensFacing != CameraMetadata.LENS_FACING_BACK) {
-                Log.v(TAG, "lensFacing=" + lensFacing + ". Crop-rotate-scale is disabled.");
-                return false;
-            }
-
-            // In case the activity behavior is not explicitly overridden, enable the
-            // crop-rotate-scale workaround if the app targets M (or below) or is not
-            // resizeable.
-            if (!ignoreResizableAndSdkCheck && !isMOrBelow(ctx, packageName) &&
-                    taskInfo.isResizeable) {
-                Slog.v(TAG,
-                        "The activity is N or above and claims to support resizeable-activity. "
-                                + "Crop-rotate-scale is disabled.");
-                return false;
-            }
-
-            DisplayManager displayManager = ctx.getSystemService(DisplayManager.class);
-            int rotationDegree = 0;
-            if (displayManager != null) {
-                Display display = displayManager.getDisplay(taskInfo.displayId);
-                if (display == null) {
-                    Slog.e(TAG, "Invalid display id: " + taskInfo.displayId);
-                    return false;
-                }
-
-                int rotation = display.getRotation();
-                switch (rotation) {
-                    case Surface.ROTATION_0:
-                        rotationDegree = 0;
-                        break;
-                    case Surface.ROTATION_90:
-                        rotationDegree = 90;
-                        break;
-                    case Surface.ROTATION_180:
-                        rotationDegree = 180;
-                        break;
-                    case Surface.ROTATION_270:
-                        rotationDegree = 270;
-                        break;
-                }
-            } else {
-                Slog.e(TAG, "Failed to query display manager!");
-                return false;
-            }
-
-            // Here we only need to know whether the camera is landscape or portrait. Therefore we
-            // don't need to consider whether it is a front or back camera. The formula works for
-            // both.
-            boolean landscapeCamera = ((rotationDegree + sensorOrientation) % 180 == 0);
+        // In case the activity behavior is not explicitly overridden, enable the
+        // crop-rotate-scale workaround if the app targets M (or below) or is not
+        // resizeable.
+        if (!ignoreResizableAndSdkCheck && !isMOrBelow(ctx, packageName) &&
+                taskInfo.isResizeable) {
             Slog.v(TAG,
-                    "Display.getRotation()=" + rotationDegree
-                            + " CameraCharacteristics.SENSOR_ORIENTATION=" + sensorOrientation
-                            + " isFixedOrientationPortrait=" + taskInfo.isFixedOrientationPortrait
-                            + " isFixedOrientationLandscape=" +
-                            taskInfo.isFixedOrientationLandscape);
-            // We need to do crop-rotate-scale when camera is landscape and activity is portrait or
-            // vice versa.
-            return (taskInfo.isFixedOrientationPortrait && landscapeCamera)
-                    || (taskInfo.isFixedOrientationLandscape && !landscapeCamera);
+                    "The activity is N or above and claims to support resizeable-activity. "
+                            + "Crop-rotate-scale is disabled.");
+            return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
         }
 
+        if (!taskInfo.isFixedOrientationPortrait && !taskInfo.isFixedOrientationLandscape) {
+            Log.v(TAG, "Non-fixed orientation activity. Crop-rotate-scale is disabled.");
+            return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+        }
+
+        int rotationDegree;
+        switch (displayRotation) {
+            case Surface.ROTATION_0:
+                rotationDegree = 0;
+                break;
+            case Surface.ROTATION_90:
+                rotationDegree = 90;
+                break;
+            case Surface.ROTATION_180:
+                rotationDegree = 180;
+                break;
+            case Surface.ROTATION_270:
+                rotationDegree = 270;
+                break;
+            default:
+                Log.e(TAG, "Unsupported display rotation: " + displayRotation);
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+        }
+
+        Slog.v(TAG,
+                "Display.getRotation()=" + rotationDegree
+                        + " isFixedOrientationPortrait=" + taskInfo.isFixedOrientationPortrait
+                        + " isFixedOrientationLandscape=" +
+                        taskInfo.isFixedOrientationLandscape);
+        // We are trying to estimate the necessary rotation compensation for clients that
+        // don't handle various display orientations.
+        // The logic that is missing on client side is similar to the reference code
+        // in {@link android.hardware.Camera#setDisplayOrientation} where "info.orientation"
+        // is already applied in "CameraUtils::getRotationTransform".
+        // Care should be taken to reverse the rotation direction depending on the camera
+        // lens facing.
+        if (rotationDegree == 0) {
+            return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+        }
+        if (lensFacing == CameraCharacteristics.LENS_FACING_FRONT) {
+            // Switch direction for front facing cameras
+            rotationDegree = 360 - rotationDegree;
+        }
+
+        switch (rotationDegree) {
+            case 90:
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_90;
+            case 270:
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_270;
+            case 180:
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_180;
+            case 0:
+            default:
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+        }
+    }
+
+    private final ICameraServiceProxy.Stub mCameraServiceProxy = new ICameraServiceProxy.Stub() {
         @Override
-        public boolean isRotateAndCropOverrideNeeded(String packageName, int sensorOrientation,
-                int lensFacing) {
+        public int getRotateAndCropOverride(String packageName, int lensFacing) {
             if (Binder.getCallingUid() != Process.CAMERASERVER_UID) {
                 Slog.e(TAG, "Calling UID: " + Binder.getCallingUid() + " doesn't match expected " +
                         " camera service UID!");
-                return false;
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
             }
 
             // TODO: Modify the sensor orientation in camera characteristics along with any 3A
@@ -531,10 +546,10 @@
                 if (CompatChanges.isChangeEnabled(OVERRIDE_CAMERA_ROTATE_AND_CROP, packageName,
                         UserHandle.getUserHandleForUid(taskInfo.userId))) {
                     Slog.v(TAG, "OVERRIDE_CAMERA_ROTATE_AND_CROP enabled!");
-                    return true;
+                    return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
                 } else {
                     Slog.v(TAG, "OVERRIDE_CAMERA_ROTATE_AND_CROP disabled!");
-                    return false;
+                    return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
                 }
             }
             boolean ignoreResizableAndSdkCheck = false;
@@ -544,7 +559,23 @@
                 Slog.v(TAG, "OVERRIDE_CAMERA_RESIZABLE_AND_SDK_CHECK enabled!");
                 ignoreResizableAndSdkCheck = true;
             }
-            return getNeedCropRotateScale(mContext, packageName, taskInfo, sensorOrientation,
+
+            DisplayManager displayManager = mContext.getSystemService(DisplayManager.class);
+            int displayRotation;
+            if (displayManager != null) {
+                Display display = displayManager.getDisplay(taskInfo.displayId);
+                if (display == null) {
+                    Slog.e(TAG, "Invalid display id: " + taskInfo.displayId);
+                    return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+                }
+
+                displayRotation = display.getRotation();
+            } else {
+                Slog.e(TAG, "Failed to query display manager!");
+                return CaptureRequest.SCALER_ROTATE_AND_CROP_NONE;
+            }
+
+            return getCropRotateScale(mContext, packageName, taskInfo, displayRotation,
                     lensFacing, ignoreResizableAndSdkCheck);
         }
 
diff --git a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
index 091e6c4..a56a8ea 100644
--- a/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
+++ b/services/core/java/com/android/server/connectivity/MultipathPolicyTracker.java
@@ -227,7 +227,7 @@
             subscriberId = tele.getSubscriberId();
             mNetworkTemplate = new NetworkTemplate(
                     NetworkTemplate.MATCH_MOBILE, subscriberId, new String[] { subscriberId },
-                    null, NetworkStats.METERED_ALL, NetworkStats.ROAMING_ALL,
+                    null, NetworkStats.METERED_YES, NetworkStats.ROAMING_ALL,
                     NetworkStats.DEFAULT_NETWORK_NO, NETWORK_TYPE_ALL, OEM_MANAGED_ALL,
                     SUBSCRIBER_ID_MATCH_RULE_EXACT);
             mUsageCallback = new UsageCallback() {
diff --git a/services/core/java/com/android/server/display/DisplayManagerService.java b/services/core/java/com/android/server/display/DisplayManagerService.java
index f16ed41..a3b5e79 100644
--- a/services/core/java/com/android/server/display/DisplayManagerService.java
+++ b/services/core/java/com/android/server/display/DisplayManagerService.java
@@ -2062,9 +2062,6 @@
             pw.println();
             mLogicalDisplayMapper.dumpLocked(pw);
 
-            pw.println();
-            mDisplayModeDirector.dump(pw);
-
             final int callbackCount = mCallbacks.size();
             pw.println();
             pw.println("Callbacks: size=" + callbackCount);
@@ -2087,6 +2084,8 @@
             pw.println();
             mPersistentDataStore.dump(pw);
         }
+        pw.println();
+        mDisplayModeDirector.dump(pw);
     }
 
     private static float[] getFloatArray(TypedArray array) {
diff --git a/services/core/java/com/android/server/display/DisplayPowerController.java b/services/core/java/com/android/server/display/DisplayPowerController.java
index 63d32c8..768587a 100644
--- a/services/core/java/com/android/server/display/DisplayPowerController.java
+++ b/services/core/java/com/android/server/display/DisplayPowerController.java
@@ -1052,11 +1052,6 @@
         }
         assert(state != Display.STATE_UNKNOWN);
 
-        // Initialize things the first time the power state is changed.
-        if (mustInitialize) {
-            initialize(state);
-        }
-
         // Apply the proximity sensor.
         if (mProximitySensor != null) {
             if (mPowerRequest.useProximitySensor && state != Display.STATE_OFF) {
@@ -1107,6 +1102,11 @@
             state = Display.STATE_OFF;
         }
 
+        // Initialize things the first time the power state is changed.
+        if (mustInitialize) {
+            initialize(state);
+        }
+
         // Animate the screen state change unless already animating.
         // The transition may be deferred, so after this point we will use the
         // actual state instead of the desired one.
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 0e82c2a..9d6678053 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -2356,6 +2356,8 @@
 
         if (displayIdToShowIme == INVALID_DISPLAY) {
             mImeHiddenByDisplayPolicy = true;
+            hideCurrentInputLocked(mCurFocusedWindow, 0, null,
+                    SoftInputShowHideReason.HIDE_DISPLAY_IME_POLICY_HIDE);
             return InputBindResult.NO_IME;
         }
         mImeHiddenByDisplayPolicy = false;
diff --git a/services/core/java/com/android/server/location/provider/LocationProviderManager.java b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
index 345dc21..72ab8c1 100644
--- a/services/core/java/com/android/server/location/provider/LocationProviderManager.java
+++ b/services/core/java/com/android/server/location/provider/LocationProviderManager.java
@@ -1996,6 +1996,11 @@
                         + TimeUtils.formatDuration(delayMs));
             }
 
+            if (mDelayedRegister != null) {
+                mAlarmHelper.cancel(mDelayedRegister);
+                mDelayedRegister = null;
+            }
+
             mDelayedRegister = new OnAlarmListener() {
                 @Override
                 public void onAlarm() {
diff --git a/services/core/java/com/android/server/media/MediaRouterService.java b/services/core/java/com/android/server/media/MediaRouterService.java
index 9f02c3c..9be618c 100644
--- a/services/core/java/com/android/server/media/MediaRouterService.java
+++ b/services/core/java/com/android/server/media/MediaRouterService.java
@@ -338,6 +338,25 @@
 
     // Binder call
     @Override
+    public void setBluetoothA2dpOn(IMediaRouterClient client, boolean on) {
+        if (client == null) {
+            throw new IllegalArgumentException("client must not be null");
+        }
+
+        final long token = Binder.clearCallingIdentity();
+        try {
+            synchronized (mLock) {
+                mAudioService.setBluetoothA2dpOn(on);
+            }
+        } catch (RemoteException ex) {
+            Slog.w(TAG, "RemoteException while calling setBluetoothA2dpOn. on=" + on);
+        } finally {
+            Binder.restoreCallingIdentity(token);
+        }
+    }
+
+    // Binder call
+    @Override
     public void setDiscoveryRequest(IMediaRouterClient client,
             int routeTypes, boolean activeScan) {
         if (client == null) {
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 83b7489..b7d4d22 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -404,7 +404,6 @@
     private AccessibilityShortcutController mAccessibilityShortcutController;
 
     boolean mSafeMode;
-    private WindowState mKeyguardCandidate = null;
 
     // Whether to allow dock apps with METADATA_DOCK_HOME to temporarily take over the Home key.
     // This is for car dock and this is updated from resource.
@@ -3061,7 +3060,6 @@
         if (mKeyguardOccludedChanged) {
             if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded changed occluded="
                     + mPendingKeyguardOccluded);
-            mKeyguardOccludedChanged = false;
             if (setKeyguardOccludedLw(mPendingKeyguardOccluded, false /* force */,
                     transitionStarted)) {
                 return FINISH_LAYOUT_REDO_LAYOUT | FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3271,14 +3269,6 @@
         mNavBarVirtualKeyHapticFeedbackEnabled = enabled;
     }
 
-    /** {@inheritDoc} */
-    @Override
-    public void setKeyguardCandidateLw(WindowState win) {
-        mKeyguardCandidate = win;
-        setKeyguardOccludedLw(isKeyguardOccluded(), true /* force */,
-                false /* keyguardOccludingStarted */);
-    }
-
     /**
      * Updates the occluded state of the Keyguard.
      *
@@ -3291,6 +3281,7 @@
     private boolean setKeyguardOccludedLw(boolean isOccluded, boolean force,
             boolean transitionStarted) {
         if (DEBUG_KEYGUARD) Slog.d(TAG, "setKeyguardOccluded occluded=" + isOccluded);
+        mKeyguardOccludedChanged = false;
         if (isKeyguardOccluded() == isOccluded && !force) {
             return false;
         }
@@ -4634,6 +4625,12 @@
         return mKeyguardDelegate.isInputRestricted();
     }
 
+    /** {@inheritDoc} */
+    @Override
+    public boolean isKeyguardUnoccluding() {
+        return keyguardOn() && !mWindowManagerFuncs.isAppTransitionStateIdle();
+    }
+
     @Override
     public void dismissKeyguardLw(IKeyguardDismissCallback callback, CharSequence message) {
         if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index c3ec6a4..2f2f94d 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -370,6 +370,12 @@
          * as the top display.
          */
         void moveDisplayToTop(int displayId);
+
+        /**
+         * Return whether the app transition state is idle.
+         * @return {@code true} if app transition state is idle on the default display.
+         */
+        boolean isAppTransitionStateIdle();
     }
 
     /**
@@ -722,13 +728,6 @@
             int icon, int logo, int windowFlags, Configuration overrideConfig, int displayId);
 
     /**
-     * Set or clear a window which can behave as the keyguard.
-     *
-     * @param win The window which can behave as the keyguard.
-     */
-    void setKeyguardCandidateLw(@Nullable WindowState win);
-
-    /**
      * Create and return an animation to re-display a window that was force hidden by Keyguard.
      */
     public Animation createHiddenByKeyguardExit(boolean onWallpaper,
@@ -977,6 +976,14 @@
     public boolean isKeyguardOccluded();
 
     /**
+     * Return whether the keyguard is unoccluding.
+     * @return {@code true} if the keyguard is unoccluding.
+     */
+    default boolean isKeyguardUnoccluding() {
+        return false;
+    }
+
+    /**
      * @return true if in keyguard is on.
      */
     boolean isKeyguardShowing();
diff --git a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
index 106cff1..2be29d4 100644
--- a/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
+++ b/services/core/java/com/android/server/stats/pull/StatsPullAtomService.java
@@ -29,6 +29,7 @@
 import static android.net.NetworkIdentity.OEM_PRIVATE;
 import static android.net.NetworkStats.DEFAULT_NETWORK_ALL;
 import static android.net.NetworkStats.METERED_ALL;
+import static android.net.NetworkStats.METERED_YES;
 import static android.net.NetworkStats.ROAMING_ALL;
 import static android.net.NetworkTemplate.MATCH_ETHERNET;
 import static android.net.NetworkTemplate.MATCH_MOBILE_WILDCARD;
@@ -1348,7 +1349,7 @@
     @Nullable private NetworkStats getUidNetworkStatsSnapshotForTransport(int transport) {
         final NetworkTemplate template = (transport == TRANSPORT_CELLULAR)
                 ? NetworkTemplate.buildTemplateMobileWithRatType(
-                /*subscriptionId=*/null, NETWORK_TYPE_ALL)
+                /*subscriptionId=*/null, NETWORK_TYPE_ALL, METERED_YES)
                 : NetworkTemplate.buildTemplateWifiWildcard();
         return getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
     }
@@ -1388,7 +1389,8 @@
         final List<NetworkStatsExt> ret = new ArrayList<>();
         for (final int ratType : getAllCollapsedRatTypes()) {
             final NetworkTemplate template =
-                    buildTemplateMobileWithRatType(subInfo.subscriberId, ratType);
+                    buildTemplateMobileWithRatType(subInfo.subscriberId, ratType,
+                    METERED_YES);
             final NetworkStats stats =
                     getUidNetworkStatsSnapshotForTemplate(template, /*includeTags=*/false);
             if (stats != null) {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index 7365f88..8ace5e4 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -154,6 +154,7 @@
 import static com.android.server.wm.ActivityRecordProto.IS_WAITING_FOR_TRANSITION_START;
 import static com.android.server.wm.ActivityRecordProto.LAST_ALL_DRAWN;
 import static com.android.server.wm.ActivityRecordProto.LAST_SURFACE_SHOWING;
+import static com.android.server.wm.ActivityRecordProto.MIN_ASPECT_RATIO;
 import static com.android.server.wm.ActivityRecordProto.NAME;
 import static com.android.server.wm.ActivityRecordProto.NUM_DRAWN_WINDOWS;
 import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
@@ -1145,10 +1146,11 @@
             if (info.getMaxAspectRatio() != 0) {
                 pw.println(prefix + "maxAspectRatio=" + info.getMaxAspectRatio());
             }
-            if (info.getMinAspectRatio() != 0) {
-                pw.println(prefix + "minAspectRatio=" + info.getMinAspectRatio());
+            final float minAspectRatio = getMinAspectRatio();
+            if (minAspectRatio != 0) {
+                pw.println(prefix + "minAspectRatio=" + minAspectRatio);
             }
-            if (info.getMinAspectRatio() != info.getManifestMinAspectRatio()) {
+            if (minAspectRatio != info.getManifestMinAspectRatio()) {
                 // Log the fact that we've overridden the min aspect ratio from the manifest
                 pw.println(prefix + "manifestMinAspectRatio="
                         + info.getManifestMinAspectRatio());
@@ -3079,9 +3081,6 @@
 
         mAtmService.deferWindowLayout();
         try {
-            final Transition newTransition = (!mTransitionController.isCollecting()
-                    && mTransitionController.getTransitionPlayer() != null)
-                    ? mTransitionController.createTransition(TRANSIT_CLOSE) : null;
             mTaskSupervisor.mNoHistoryActivities.remove(this);
             makeFinishingLocked();
             // Make a local reference to its task since this.task could be set to null once this
@@ -3113,10 +3112,7 @@
 
             final boolean endTask = task.getTopNonFinishingActivity() == null
                     && !task.isClearingToReuseTask();
-            if (newTransition != null) {
-                mTransitionController.requestStartTransition(newTransition,
-                        endTask ? task : null, null /* remote */);
-            }
+            mTransitionController.requestCloseTransitionIfNeeded(endTask ? task : this);
             if (isState(RESUMED)) {
                 if (endTask) {
                     mAtmService.getTaskChangeNotificationController().notifyTaskRemovalStarted(
@@ -3542,13 +3538,6 @@
         if (stopped) {
             abortAndClearOptionsAnimation();
         }
-        if (mTransitionController.isCollecting()) {
-            // We don't want the finishing to change the transition ready state since there will not
-            // be corresponding setReady for finishing.
-            mTransitionController.collectExistenceChange(this);
-        } else {
-            mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, this);
-        }
     }
 
     /**
@@ -3642,6 +3631,10 @@
 
         if (mPendingRelaunchCount > 0) {
             mPendingRelaunchCount--;
+            if (mPendingRelaunchCount == 0 && !isClientVisible()) {
+                // Don't count if the client won't report drawn.
+                mRelaunchStartTime = 0;
+            }
         } else {
             // Update keyguard flags upon finishing relaunch.
             checkKeyguardFlagsChanged();
@@ -3726,6 +3719,7 @@
             // to the restarted activity.
             nowVisible = mVisibleRequested;
         }
+        mTransitionController.requestCloseTransitionIfNeeded(this);
         cleanUp(true /* cleanServices */, true /* setState */);
         if (remove) {
             if (mStartingData != null && mVisible && task != null) {
@@ -4151,19 +4145,40 @@
      *         conditions a) above.
      *         Multi-windowing mode will be exited if {@code true} is returned.
      */
-    boolean canShowWhenLocked() {
-        if (!inPinnedWindowingMode() && (mShowWhenLocked || containsShowWhenLockedWindow())) {
+    private static boolean canShowWhenLocked(ActivityRecord r) {
+        if (r == null || r.getTaskFragment() == null) {
+            return false;
+        }
+        if (!r.inPinnedWindowingMode() && (r.mShowWhenLocked || r.containsShowWhenLockedWindow())) {
             return true;
-        } else if (mInheritShownWhenLocked) {
-            final ActivityRecord r = task.getActivityBelow(this);
-            return r != null && !r.inPinnedWindowingMode() && (r.mShowWhenLocked
-                    || r.containsShowWhenLockedWindow());
+        } else if (r.mInheritShownWhenLocked) {
+            final ActivityRecord activity = r.getTaskFragment().getActivityBelow(r);
+            return activity != null && !activity.inPinnedWindowingMode()
+                    && (activity.mShowWhenLocked || activity.containsShowWhenLockedWindow());
         } else {
             return false;
         }
     }
 
     /**
+     *  Determines if the activity can show while lock-screen is displayed. System displays
+     *  activities while lock-screen is displayed only if all activities
+     *  {@link #canShowWhenLocked(ActivityRecord)}.
+     *  @see #canShowWhenLocked(ActivityRecord)
+     */
+    boolean canShowWhenLocked() {
+        final TaskFragment taskFragment = getTaskFragment();
+        if (taskFragment != null && taskFragment.getAdjacentTaskFragment() != null
+                && taskFragment.isEmbedded()) {
+            final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment();
+            final ActivityRecord r = adjacentTaskFragment.getTopNonFinishingActivity();
+            return canShowWhenLocked(this) && canShowWhenLocked(r);
+        } else {
+            return canShowWhenLocked(this);
+        }
+    }
+
+    /**
      * @return Whether we are allowed to show non-starting windows at the moment. We disallow
      *         showing windows during transitions in case we have windows that have wide-color-gamut
      *         color mode set to avoid jank in the middle of the transition.
@@ -7272,7 +7287,7 @@
                 return false;
             }
         }
-        return !isResizeable() && (info.isFixedOrientation() || info.hasFixedAspectRatio())
+        return !isResizeable() && (info.isFixedOrientation() || hasFixedAspectRatio())
                 // The configuration of non-standard type should be enforced by system.
                 // {@link WindowConfiguration#ACTIVITY_TYPE_STANDARD} is set when this activity is
                 // added to a task, but this function is called when resolving the launch params, at
@@ -7943,13 +7958,14 @@
                 return false;
             }
         }
-        if (info.getMinAspectRatio() > 0) {
+        final float minAspectRatio = getMinAspectRatio();
+        if (minAspectRatio > 0) {
             // The activity should have at least the min aspect ratio, so this checks if the
             // container still has available space to provide larger aspect ratio.
             final float containerAspectRatio =
                     (0.5f + Math.max(containerAppWidth, containerAppHeight))
                             / Math.min(containerAppWidth, containerAppHeight);
-            if (containerAspectRatio <= info.getMinAspectRatio()) {
+            if (containerAspectRatio <= minAspectRatio) {
                 // The long side has reached the parent.
                 return false;
             }
@@ -8160,8 +8176,7 @@
             Rect containingBounds, float desiredAspectRatio, boolean fixedOrientationLetterboxed) {
         final float maxAspectRatio = info.getMaxAspectRatio();
         final Task rootTask = getRootTask();
-        final float minAspectRatio = info.getMinAspectRatio();
-
+        final float minAspectRatio = getMinAspectRatio();
         if (task == null || rootTask == null
                 || (inMultiWindowMode() && !shouldCreateCompatDisplayInsets()
                 && !fixedOrientationLetterboxed)
@@ -8265,6 +8280,20 @@
     }
 
     /**
+     * Returns the min aspect ratio of this activity.
+     */
+    private float getMinAspectRatio() {
+        return info.getMinAspectRatio(getRequestedOrientation());
+    }
+
+    /**
+     * Returns true if the activity has maximum or minimum aspect ratio.
+     */
+    private boolean hasFixedAspectRatio() {
+        return info.hasFixedAspectRatio(getRequestedOrientation());
+    }
+
+    /**
      * Returns the aspect ratio of the given {@code rect}.
      */
     static float computeAspectRatio(Rect rect) {
@@ -8993,6 +9022,7 @@
         }
         proto.write(PIP_AUTO_ENTER_ENABLED, pictureInPictureArgs.isAutoEnterEnabled());
         proto.write(IN_SIZE_COMPAT_MODE, inSizeCompatMode());
+        proto.write(MIN_ASPECT_RATIO, getMinAspectRatio());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 01e3e19..dc5126d 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -1565,7 +1565,7 @@
         // transition based on a sub-action.
         // Only do the create here (and defer requestStart) since startActivityInner might abort.
         final TransitionController transitionController = r.mTransitionController;
-        final Transition newTransition = (!transitionController.isCollecting()
+        Transition newTransition = (!transitionController.isCollecting()
                 && transitionController.getTransitionPlayer() != null)
                 ? transitionController.createTransition(TRANSIT_OPEN) : null;
         RemoteTransition remoteTransition = r.takeRemoteTransition();
@@ -1620,6 +1620,10 @@
                     // The activity is started new rather than just brought forward, so record
                     // it as an existence change.
                     transitionController.collectExistenceChange(r);
+                } else if (result == START_DELIVERED_TO_TOP && newTransition != null) {
+                    // We just delivered to top, so there isn't an actual transition here
+                    newTransition.abort();
+                    newTransition = null;
                 }
                 if (isTransient) {
                     // `r` isn't guaranteed to be the actual relevant activity, so we must wait
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index ba30592..7c5f059 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -44,7 +44,6 @@
 import static android.os.Process.INVALID_UID;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.Display.DEFAULT_DISPLAY;
-import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_TO_FRONT;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_STATES;
@@ -1562,19 +1561,7 @@
             // Prevent recursion.
             return;
         }
-        if (task.isVisible()) {
-            if (task.mTransitionController.isCollecting()) {
-                // We don't want the finishing to change the transition ready state since there will
-                // not be corresponding setReady for finishing.
-                task.mTransitionController.collectExistenceChange(task);
-            } else {
-                task.mTransitionController.requestTransitionIfNeeded(TRANSIT_CLOSE, task);
-            }
-        } else {
-            // Removing a non-visible task doesn't require a transition, but if there is one
-            // collecting, this should be a member just in case.
-            task.mTransitionController.collect(task);
-        }
+        task.mTransitionController.requestCloseTransitionIfNeeded(task);
         task.mInRemoveTask = true;
         try {
             task.performClearTask(reason);
diff --git a/services/core/java/com/android/server/wm/AppTransition.java b/services/core/java/com/android/server/wm/AppTransition.java
index bd08d01..b9353e1 100644
--- a/services/core/java/com/android/server/wm/AppTransition.java
+++ b/services/core/java/com/android/server/wm/AppTransition.java
@@ -367,6 +367,10 @@
         setAppTransitionState(APP_STATE_IDLE);
     }
 
+    boolean isIdle() {
+        return mAppTransitionState == APP_STATE_IDLE;
+    }
+
     boolean isTimeout() {
         return mAppTransitionState == APP_STATE_TIMEOUT;
     }
diff --git a/services/core/java/com/android/server/wm/BLASTSyncEngine.java b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
index 4355b38..2a8ac39e 100644
--- a/services/core/java/com/android/server/wm/BLASTSyncEngine.java
+++ b/services/core/java/com/android/server/wm/BLASTSyncEngine.java
@@ -20,9 +20,11 @@
 
 import android.annotation.NonNull;
 import android.util.ArraySet;
+import android.util.Slog;
 import android.util.SparseArray;
 import android.view.SurfaceControl;
 
+import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.protolog.common.ProtoLog;
 
 /**
@@ -65,6 +67,7 @@
     class SyncGroup {
         final int mSyncId;
         final TransactionReadyListener mListener;
+        final Runnable mOnTimeout;
         boolean mReady = false;
         final ArraySet<WindowContainer> mRootMembers = new ArraySet<>();
         private SurfaceControl.Transaction mOrphanTransaction = null;
@@ -72,6 +75,12 @@
         private SyncGroup(TransactionReadyListener listener, int id) {
             mSyncId = id;
             mListener = listener;
+            mOnTimeout = () -> {
+                Slog.w(TAG, "Sync group " + mSyncId + " timeout");
+                synchronized (mWm.mGlobalLock) {
+                    onTimeout();
+                }
+            };
         }
 
         /**
@@ -114,6 +123,7 @@
             }
             mListener.onTransactionReady(mSyncId, merged);
             mActiveSyncs.remove(mSyncId);
+            mWm.mH.removeCallbacks(mOnTimeout);
         }
 
         private void setReady(boolean ready) {
@@ -136,6 +146,17 @@
         void onCancelSync(WindowContainer wc) {
             mRootMembers.remove(wc);
         }
+
+        private void onTimeout() {
+            if (!mActiveSyncs.contains(mSyncId)) return;
+            for (int i = mRootMembers.size() - 1; i >= 0; --i) {
+                final WindowContainer<?> wc = mRootMembers.valueAt(i);
+                if (!wc.isSyncFinished()) {
+                    Slog.i(TAG, "Unfinished container: " + wc);
+                }
+            }
+            finishNow();
+        }
     }
 
     private final WindowManagerService mWm;
@@ -147,13 +168,23 @@
     }
 
     int startSyncSet(TransactionReadyListener listener) {
+        return startSyncSet(listener, WindowState.BLAST_TIMEOUT_DURATION);
+    }
+
+    int startSyncSet(TransactionReadyListener listener, long timeoutMs) {
         final int id = mNextSyncId++;
         final SyncGroup s = new SyncGroup(listener, id);
         mActiveSyncs.put(id, s);
         ProtoLog.v(WM_DEBUG_SYNC_ENGINE, "SyncGroup %d: Started for listener: %s", id, listener);
+        scheduleTimeout(s, timeoutMs);
         return id;
     }
 
+    @VisibleForTesting
+    void scheduleTimeout(SyncGroup s, long timeoutMs) {
+        mWm.mH.postDelayed(s.mOnTimeout, timeoutMs);
+    }
+
     void addToSyncSet(int id, WindowContainer wc) {
         mActiveSyncs.get(id).addToSync(wc);
     }
diff --git a/services/core/java/com/android/server/wm/DisplayContent.java b/services/core/java/com/android/server/wm/DisplayContent.java
index 2f88a98..cb37652 100644
--- a/services/core/java/com/android/server/wm/DisplayContent.java
+++ b/services/core/java/com/android/server/wm/DisplayContent.java
@@ -93,6 +93,7 @@
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SCREEN_ON;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WALLPAPER;
 import static com.android.internal.protolog.ProtoLogGroup.WM_SHOW_TRANSACTIONS;
+import static com.android.internal.util.LatencyTracker.ACTION_ROTATE_SCREEN;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_ANIM;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_CONFIG;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_LAYOUT;
@@ -114,10 +115,12 @@
 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_CONTROL_TARGET;
 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_INPUT_TARGET;
 import static com.android.server.wm.DisplayContentProto.INPUT_METHOD_TARGET;
+import static com.android.server.wm.DisplayContentProto.IS_SLEEPING;
 import static com.android.server.wm.DisplayContentProto.OPENING_APPS;
 import static com.android.server.wm.DisplayContentProto.RESUMED_ACTIVITY;
 import static com.android.server.wm.DisplayContentProto.ROOT_DISPLAY_AREA;
 import static com.android.server.wm.DisplayContentProto.SCREEN_ROTATION_ANIMATION;
+import static com.android.server.wm.DisplayContentProto.SLEEP_TOKENS;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_RECENTS;
 import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
@@ -3230,6 +3233,11 @@
         }
         final Transition t = controller.requestTransitionIfNeeded(TRANSIT_CHANGE, this);
         if (t != null) {
+            if (getRotation() != getWindowConfiguration().getRotation()) {
+                mWmService.mLatencyTracker.onActionStart(ACTION_ROTATE_SCREEN);
+                controller.mTransitionMetricsReporter.associate(t,
+                        startTime -> mWmService.mLatencyTracker.onActionEnd(ACTION_ROTATE_SCREEN));
+            }
             t.setKnownConfigChanges(this, changes);
         }
     }
@@ -3287,6 +3295,11 @@
             proto.write(FOCUSED_ROOT_TASK_ID, INVALID_TASK_ID);
         }
         proto.write(DISPLAY_READY, isReady());
+        proto.write(IS_SLEEPING, isSleeping());
+        for (int i = 0; i < mAllSleepTokens.size(); ++i) {
+            mAllSleepTokens.get(i).writeTagToProto(proto, SLEEP_TOKENS);
+        }
+
         if (mImeLayeringTarget != null) {
             mImeLayeringTarget.dumpDebug(proto, INPUT_METHOD_TARGET, logLevel);
         }
@@ -3443,7 +3456,9 @@
 
     @Override
     public String toString() {
-        return "Display " + mDisplayId + " info=" + mDisplayInfo + " rootTasks=" + mChildren;
+        return "Display{#" + mDisplayId + " state=" + Display.stateToString(mDisplayInfo.state)
+                + " size=" + mDisplayInfo.logicalWidth + "x" + mDisplayInfo.logicalHeight
+                + " " + Surface.rotationToString(mDisplayInfo.rotation) + "}";
     }
 
     String getName() {
@@ -4132,6 +4147,8 @@
                 target.mActivityRecord.mImeInsetsFrozenUntilStartInput = false;
             }
             setImeInputTarget(target);
+            mInsetsStateController.updateAboveInsetsState(mInputMethodWindow, mInsetsStateController
+                    .getRawInsetsState().getSourceOrDefaultVisibility(ITYPE_IME));
             updateImeControlTarget();
         }
     }
diff --git a/services/core/java/com/android/server/wm/DisplayPolicy.java b/services/core/java/com/android/server/wm/DisplayPolicy.java
index 0c0d01c..eab1aaf 100644
--- a/services/core/java/com/android/server/wm/DisplayPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayPolicy.java
@@ -122,6 +122,7 @@
 import android.graphics.PixelFormat;
 import android.graphics.Rect;
 import android.graphics.Region;
+import android.gui.DropInputMode;
 import android.hardware.power.Boost;
 import android.os.Handler;
 import android.os.IBinder;
@@ -156,6 +157,7 @@
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.internal.policy.GestureNavigationSettingsObserver;
 import com.android.internal.policy.ScreenDecorationsUtils;
+import com.android.internal.policy.SystemBarUtils;
 import com.android.internal.protolog.common.ProtoLog;
 import com.android.internal.util.ScreenshotHelper;
 import com.android.internal.util.function.TriConsumer;
@@ -951,6 +953,20 @@
     }
 
     /**
+     * Add additional policy if needed to ensure the window or its children should not receive any
+     * input.
+     */
+    public void setDropInputModePolicy(WindowState win, LayoutParams attrs) {
+        if (attrs.type == TYPE_TOAST
+                && (attrs.privateFlags & PRIVATE_FLAG_TRUSTED_OVERLAY) == 0) {
+            // Toasts should not receive input. These windows should not have any children, so
+            // force this hierarchy of windows to drop all input.
+            mService.mTransactionFactory.get()
+                    .setDropInputMode(win.getSurfaceControl(), DropInputMode.ALL).apply();
+        }
+    }
+
+    /**
      * Check if a window can be added to the system.
      *
      * Currently enforces that two window types are singletons per display:
@@ -1094,9 +1110,6 @@
         switch (attrs.type) {
             case TYPE_NOTIFICATION_SHADE:
                 mNotificationShade = win;
-                if (mDisplayContent.isDefaultDisplay) {
-                    mService.mPolicy.setKeyguardCandidateLw(win);
-                }
                 break;
             case TYPE_STATUS_BAR:
                 mStatusBar = win;
@@ -1292,9 +1305,6 @@
             mDisplayContent.setInsetProvider(ITYPE_NAVIGATION_BAR, null, null);
         } else if (mNotificationShade == win) {
             mNotificationShade = null;
-            if (mDisplayContent.isDefaultDisplay) {
-                mService.mPolicy.setKeyguardCandidateLw(null);
-            }
         } else if (mClimateBarAlt == win) {
             mClimateBarAlt = null;
             mDisplayContent.setInsetProvider(ITYPE_CLIMATE_BAR, null, null);
@@ -1321,6 +1331,11 @@
         return Math.max(statusBarHeight, displayFrames.mDisplayCutoutSafe.top);
     }
 
+    @VisibleForTesting
+    int getStatusBarHeightForRotation(@Surface.Rotation int rotation) {
+        return SystemBarUtils.getStatusBarHeightForRotation(mUiContext, rotation);
+    }
+
     WindowState getStatusBar() {
         return mStatusBar != null ? mStatusBar : mStatusBarAlt;
     }
@@ -1590,8 +1605,6 @@
         // For layout, the status bar is always at the top with our fixed height.
         int statusBarBottom = displayFrames.mUnrestricted.top
                 + mStatusBarHeightForRotation[displayFrames.mRotation];
-        // Make sure the status bar covers the entire cutout height
-        statusBarBottom = Math.max(statusBarBottom, displayFrames.mDisplayCutoutSafe.top);
 
         if (displayFrames.mDisplayCutoutSafe.top > displayFrames.mUnrestricted.top) {
             // Make sure that the zone we're avoiding for the cutout is at least as tall as the
@@ -2124,10 +2137,11 @@
         if (hasStatusBar()) {
             mStatusBarHeightForRotation[portraitRotation] =
                     mStatusBarHeightForRotation[upsideDownRotation] =
-                            res.getDimensionPixelSize(R.dimen.status_bar_height_portrait);
+                            getStatusBarHeightForRotation(portraitRotation);
             mStatusBarHeightForRotation[landscapeRotation] =
-                    mStatusBarHeightForRotation[seascapeRotation] =
-                            res.getDimensionPixelSize(R.dimen.status_bar_height_landscape);
+                    getStatusBarHeightForRotation(landscapeRotation);
+            mStatusBarHeightForRotation[seascapeRotation] =
+                    getStatusBarHeightForRotation(seascapeRotation);
             mDisplayCutoutTouchableRegionSize = res.getDimensionPixelSize(
                     R.dimen.display_cutout_touchable_region_size);
         } else {
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index e3600e6..b1eca9d 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -2700,6 +2700,7 @@
             token = new SleepToken(tag, displayId);
             mSleepTokens.put(tokenKey, token);
             display.mAllSleepTokens.add(token);
+            ProtoLog.d(WM_DEBUG_STATES, "Create sleep token: tag=%s, displayId=%d", tag, displayId);
         } else {
             throw new RuntimeException("Create the same sleep token twice: " + token);
         }
@@ -2718,6 +2719,8 @@
             return;
         }
 
+        ProtoLog.d(WM_DEBUG_STATES, "Remove sleep token: tag=%s, displayId=%d", token.mTag,
+                token.mDisplayId);
         display.mAllSleepTokens.remove(token);
         if (display.mAllSleepTokens.isEmpty()) {
             mService.updateSleepIfNeededLocked();
@@ -3729,6 +3732,10 @@
             return "{\"" + mTag + "\", display " + mDisplayId
                     + ", acquire at " + TimeUtils.formatUptime(mAcquireTime) + "}";
         }
+
+        void writeTagToProto(ProtoOutputStream proto, long fieldId) {
+            proto.write(fieldId, mTag);
+        }
     }
 
     private class RankTaskLayersRunnable implements Runnable {
diff --git a/services/core/java/com/android/server/wm/TaskDisplayArea.java b/services/core/java/com/android/server/wm/TaskDisplayArea.java
index 275ed0e..f5e7967 100644
--- a/services/core/java/com/android/server/wm/TaskDisplayArea.java
+++ b/services/core/java/com/android/server/wm/TaskDisplayArea.java
@@ -864,12 +864,9 @@
         int layer = 0;
         // Place root home tasks to the bottom.
         layer = adjustRootTaskLayer(t, mTmpHomeChildren, layer);
-        adjustRootTaskLayer(t, mTmpNormalChildren, layer);
-
-        // Always on top tasks layer should higher than split divider layer so set it as start.
-        t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
-        layer = SPLIT_DIVIDER_LAYER + 1;
+        layer = adjustRootTaskLayer(t, mTmpNormalChildren, layer);
         adjustRootTaskLayer(t, mTmpAlwaysOnTopChildren, layer);
+        t.setLayer(mSplitScreenDividerAnchor, SPLIT_DIVIDER_LAYER);
     }
 
     /**
@@ -884,19 +881,33 @@
             ArrayList<WindowContainer> children, int startLayer) {
         mTmpNeedsZBoostIndexes.clear();
         final int childCount = children.size();
+        boolean hasAdjacentTask = false;
         for (int i = 0; i < childCount; i++) {
             final WindowContainer child = children.get(i);
             final TaskDisplayArea childTda = child.asTaskDisplayArea();
-
-            boolean childNeedsZBoost = childTda != null
+            final boolean childNeedsZBoost = childTda != null
                     ? childTda.childrenNeedZBoost()
                     : child.needsZBoost();
 
-            if (!childNeedsZBoost) {
-                child.assignLayer(t, startLayer++);
-            } else {
+            if (childNeedsZBoost) {
                 mTmpNeedsZBoostIndexes.add(i);
+                continue;
             }
+
+            final Task childTask = child.asTask();
+            final boolean inAdjacentTask = childTask != null
+                    && child.inMultiWindowMode()
+                    && childTask.getRootTask().getAdjacentTaskFragment() != null;
+
+            if (inAdjacentTask || child.inSplitScreenWindowingMode()) {
+                hasAdjacentTask = true;
+            } else if (hasAdjacentTask && startLayer < SPLIT_DIVIDER_LAYER) {
+                // Task on top of adjacent tasks should be higher than split divider layer so
+                // set it as start.
+                startLayer = SPLIT_DIVIDER_LAYER + 1;
+            }
+
+            child.assignLayer(t, startLayer++);
         }
 
         final int zBoostSize = mTmpNeedsZBoostIndexes.size();
diff --git a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
index d543c1f..b8ceb4a 100644
--- a/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
+++ b/services/core/java/com/android/server/wm/TaskLaunchParamsModifier.java
@@ -818,7 +818,7 @@
         final int layoutMinHeight = (layout == null) ? -1 : layout.minHeight;
 
         // Aspect ratio requirements.
-        final float minAspectRatio = info.getMinAspectRatio();
+        final float minAspectRatio = info.getMinAspectRatio(orientation);
         final float maxAspectRatio = info.getMaxAspectRatio();
 
         final int width = Math.min(defaultWidth, Math.max(phoneWidth, layoutMinWidth));
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index 8bd6257..4db8ef4 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -165,13 +165,13 @@
     private boolean mNavBarAttachedToApp = false;
     private int mRecentsDisplayId = INVALID_DISPLAY;
 
-    Transition(@TransitionType int type, @TransitionFlags int flags,
+    Transition(@TransitionType int type, @TransitionFlags int flags, long timeoutMs,
             TransitionController controller, BLASTSyncEngine syncEngine) {
         mType = type;
         mFlags = flags;
         mController = controller;
         mSyncEngine = syncEngine;
-        mSyncId = mSyncEngine.startSyncSet(this);
+        mSyncId = mSyncEngine.startSyncSet(this, timeoutMs);
     }
 
     void addFlag(int flag) {
@@ -338,6 +338,11 @@
         applyReady();
     }
 
+    @VisibleForTesting
+    boolean allReady() {
+        return mReadyTracker.allReady();
+    }
+
     /**
      * Build a transaction that "resets" all the re-parenting and layer changes. This is
      * intended to be applied at the end of the transition but before the finish callback. This
@@ -469,6 +474,7 @@
         if (mState != STATE_COLLECTING) {
             throw new IllegalStateException("Too late to abort.");
         }
+        ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Aborting Transition: %d", mSyncId);
         mController.dispatchLegacyAppTransitionCancelled();
         mState = STATE_ABORT;
         // Syncengine abort will call through to onTransactionReady()
diff --git a/services/core/java/com/android/server/wm/TransitionController.java b/services/core/java/com/android/server/wm/TransitionController.java
index b849170..a21e4f2 100644
--- a/services/core/java/com/android/server/wm/TransitionController.java
+++ b/services/core/java/com/android/server/wm/TransitionController.java
@@ -17,6 +17,7 @@
 package com.android.server.wm;
 
 import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
+import static android.view.WindowManager.TRANSIT_CHANGE;
 import static android.view.WindowManager.TRANSIT_CLOSE;
 import static android.view.WindowManager.TRANSIT_FLAG_IS_RECENTS;
 import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_GOING_AWAY;
@@ -30,10 +31,11 @@
 import android.os.IRemoteCallback;
 import android.os.RemoteException;
 import android.os.SystemClock;
+import android.util.ArrayMap;
 import android.util.Slog;
 import android.util.proto.ProtoOutputStream;
 import android.view.WindowManager;
-import android.window.IRemoteTransition;
+import android.window.ITransitionMetricsReporter;
 import android.window.ITransitionPlayer;
 import android.window.RemoteTransition;
 import android.window.TransitionInfo;
@@ -45,6 +47,7 @@
 import com.android.server.statusbar.StatusBarManagerInternal;
 
 import java.util.ArrayList;
+import java.util.function.LongConsumer;
 
 /**
  * Handles all the aspects of recording and synchronizing transitions.
@@ -52,12 +55,19 @@
 class TransitionController {
     private static final String TAG = "TransitionController";
 
+    /** The same as legacy APP_TRANSITION_TIMEOUT_MS. */
+    private static final int DEFAULT_TIMEOUT_MS = 5000;
+    /** Less duration for CHANGE type because it does not involve app startup. */
+    private static final int CHANGE_TIMEOUT_MS = 2000;
+
     // State constants to line-up with legacy app-transition proto expectations.
     private static final int LEGACY_STATE_IDLE = 0;
     private static final int LEGACY_STATE_READY = 1;
     private static final int LEGACY_STATE_RUNNING = 2;
 
     private ITransitionPlayer mTransitionPlayer;
+    final TransitionMetricsReporter mTransitionMetricsReporter = new TransitionMetricsReporter();
+
     final ActivityTaskManagerService mAtm;
     final TaskSnapshotController mTaskSnapshotController;
 
@@ -116,7 +126,10 @@
         if (mCollectingTransition != null) {
             throw new IllegalStateException("Simultaneous transitions not supported yet.");
         }
-        mCollectingTransition = new Transition(type, flags, this, mAtm.mWindowManager.mSyncEngine);
+        // Distinguish change type because the response time is usually expected to be not too long.
+        final long timeoutMs = type == TRANSIT_CHANGE ? CHANGE_TIMEOUT_MS : DEFAULT_TIMEOUT_MS;
+        mCollectingTransition = new Transition(type, flags, timeoutMs, this,
+                mAtm.mWindowManager.mSyncEngine);
         ProtoLog.v(ProtoLogGroup.WM_DEBUG_WINDOW_TRANSITIONS, "Creating Transition: %s",
                 mCollectingTransition);
         dispatchLegacyAppTransitionPending();
@@ -212,7 +225,7 @@
     }
 
     /**
-     * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+     * @see #requestTransitionIfNeeded(int, int, WindowContainer, WindowContainer, RemoteTransition)
      */
     @Nullable
     Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -221,7 +234,7 @@
     }
 
     /**
-     * @see #requestTransitionIfNeeded(int, int, WindowContainer, IRemoteTransition)
+     * @see #requestTransitionIfNeeded(int, int, WindowContainer, WindowContainer, RemoteTransition)
      */
     @Nullable
     Transition requestTransitionIfNeeded(@WindowManager.TransitionType int type,
@@ -292,6 +305,22 @@
         return transition;
     }
 
+    /** Requests transition for a window container which will be removed or invisible. */
+    void requestCloseTransitionIfNeeded(@NonNull WindowContainer<?> wc) {
+        if (mTransitionPlayer == null) return;
+        if (wc.isVisibleRequested()) {
+            if (!isCollecting()) {
+                requestStartTransition(createTransition(TRANSIT_CLOSE, 0 /* flags */),
+                        wc.asTask(), null /* remoteTransition */);
+            }
+            collectExistenceChange(wc);
+        } else {
+            // Removing a non-visible window doesn't require a transition, but if there is one
+            // collecting, this should be a member just in case.
+            collect(wc);
+        }
+    }
+
     /** @see Transition#collect */
     void collect(@NonNull WindowContainer wc) {
         if (mCollectingTransition == null) return;
@@ -324,6 +353,8 @@
 
     /** @see Transition#finishTransition */
     void finishTransition(@NonNull IBinder token) {
+        // It is usually a no-op but make sure that the metric consumer is removed.
+        mTransitionMetricsReporter.reportAnimationStart(token, 0 /* startTime */);
         final Transition record = Transition.fromBinder(token);
         if (record == null || !mPlayingTransitions.contains(record)) {
             Slog.e(TAG, "Trying to finish a non-playing transition " + token);
@@ -420,6 +451,28 @@
         proto.end(token);
     }
 
+    static class TransitionMetricsReporter extends ITransitionMetricsReporter.Stub {
+        private final ArrayMap<IBinder, LongConsumer> mMetricConsumers = new ArrayMap<>();
+
+        void associate(IBinder transitionToken, LongConsumer consumer) {
+            synchronized (mMetricConsumers) {
+                mMetricConsumers.put(transitionToken, consumer);
+            }
+        }
+
+        @Override
+        public void reportAnimationStart(IBinder transitionToken, long startTime) {
+            final LongConsumer c;
+            synchronized (mMetricConsumers) {
+                if (mMetricConsumers.isEmpty()) return;
+                c = mMetricConsumers.remove(transitionToken);
+            }
+            if (c != null) {
+                c.accept(startTime);
+            }
+        }
+    }
+
     class Lock {
         private int mTransitionWaiters = 0;
         void runWhenIdle(long timeout, Runnable r) {
diff --git a/services/core/java/com/android/server/wm/WallpaperController.java b/services/core/java/com/android/server/wm/WallpaperController.java
index a92e088..4b2aa0f 100644
--- a/services/core/java/com/android/server/wm/WallpaperController.java
+++ b/services/core/java/com/android/server/wm/WallpaperController.java
@@ -165,7 +165,8 @@
         boolean needsShowWhenLockedWallpaper = false;
         if ((w.mAttrs.flags & FLAG_SHOW_WHEN_LOCKED) != 0
                 && mService.mPolicy.isKeyguardLocked()
-                && mService.mPolicy.isKeyguardOccluded()) {
+                && (mService.mPolicy.isKeyguardOccluded()
+                || mService.mPolicy.isKeyguardUnoccluding())) {
             // The lowest show when locked window decides whether we need to put the wallpaper
             // behind.
             needsShowWhenLockedWallpaper = !isFullscreen(w.mAttrs)
@@ -801,6 +802,18 @@
                 wallpaperBuffer.getHardwareBuffer(), wallpaperBuffer.getColorSpace());
     }
 
+    /**
+     * Mirrors the visible wallpaper if it's available.
+     *
+     * @return A SurfaceControl for the parent of the mirrored wallpaper.
+     */
+    SurfaceControl mirrorWallpaperSurface() {
+        final WindowState wallpaperWindowState = getTopVisibleWallpaper();
+        return wallpaperWindowState != null
+                ? SurfaceControl.mirrorSurface(wallpaperWindowState.getSurfaceControl())
+                : null;
+    }
+
     WindowState getTopVisibleWallpaper() {
         mTmpTopWallpaper = null;
 
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 51ecce0..a68b09e 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -32,10 +32,6 @@
 import static android.view.SurfaceControl.Transaction;
 import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
 import static android.view.WindowManager.TRANSIT_CHANGE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_BACK;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_TO_FRONT;
 
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS;
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_APP_TRANSITIONS_ANIM;
@@ -43,6 +39,7 @@
 import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_SYNC_ENGINE;
 import static com.android.server.policy.WindowManagerPolicy.FINISH_LAYOUT_REDO_WALLPAPER;
 import static com.android.server.wm.AppTransition.MAX_APP_TRANSITION_DURATION;
+import static com.android.server.wm.AppTransition.isTaskTransitOld;
 import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
 import static com.android.server.wm.IdentifierProto.HASH_CODE;
 import static com.android.server.wm.IdentifierProto.TITLE;
@@ -70,7 +67,6 @@
 import android.annotation.IntDef;
 import android.annotation.NonNull;
 import android.annotation.Nullable;
-import android.app.ActivityThread;
 import android.content.Context;
 import android.content.pm.ActivityInfo;
 import android.content.res.Configuration;
@@ -91,6 +87,7 @@
 import android.view.SurfaceControl;
 import android.view.SurfaceControl.Builder;
 import android.view.SurfaceSession;
+import android.view.TaskTransitionSpec;
 import android.view.WindowManager;
 import android.view.WindowManager.TransitionOldType;
 import android.view.animation.Animation;
@@ -2825,33 +2822,15 @@
                 mSurfaceAnimationSources.addAll(sources);
             }
 
-            TaskDisplayArea taskDisplayArea = getTaskDisplayArea();
-            boolean isSettingBackgroundColor = taskDisplayArea != null
-                    && isTransitionWithBackgroundColor(transit);
+            AnimationRunnerBuilder animationRunnerBuilder = new AnimationRunnerBuilder();
 
-            if (isSettingBackgroundColor) {
-                Context uiContext = ActivityThread.currentActivityThread().getSystemUiContext();
-                @ColorInt int backgroundColor = uiContext.getColor(R.color.overview_background);
-
-                taskDisplayArea.setBackgroundColor(backgroundColor);
+            if (isTaskTransitOld(transit)) {
+                animationRunnerBuilder.setTaskBackgroundColor(getTaskAnimationBackgroundColor());
             }
 
-            // Atomic counter to make sure the clearColor callback is only called one.
-            // It will be called twice in the case we cancel the animation without restart
-            // (in that case it will run as the cancel and finished callbacks).
-            final AtomicInteger callbackCounter = new AtomicInteger(0);
-            final Runnable clearBackgroundColorHandler = () -> {
-                if (callbackCounter.getAndIncrement() == 0) {
-                    taskDisplayArea.clearBackgroundColor();
-                }
-            };
-
-            final Runnable cleanUpCallback = isSettingBackgroundColor
-                    ? clearBackgroundColorHandler : () -> {};
-
-            startAnimation(getPendingTransaction(), adapter, !isVisible(),
-                    ANIMATION_TYPE_APP_TRANSITION, (type, anim) -> cleanUpCallback.run(),
-                    cleanUpCallback, thumbnailAdapter);
+            animationRunnerBuilder.build()
+                    .startAnimation(getPendingTransaction(), adapter, !isVisible(),
+                            ANIMATION_TYPE_APP_TRANSITION, thumbnailAdapter);
 
             if (adapter.getShowWallpaper()) {
                 getDisplayContent().pendingLayoutChanges |= FINISH_LAYOUT_REDO_WALLPAPER;
@@ -2859,11 +2838,16 @@
         }
     }
 
-    private boolean isTransitionWithBackgroundColor(@TransitionOldType int transit) {
-        return transit == TRANSIT_OLD_TASK_OPEN
-                || transit == TRANSIT_OLD_TASK_CLOSE
-                || transit == TRANSIT_OLD_TASK_TO_FRONT
-                || transit == TRANSIT_OLD_TASK_TO_BACK;
+    private @ColorInt int getTaskAnimationBackgroundColor() {
+        Context uiContext = mDisplayContent.getDisplayPolicy().getSystemUiContext();
+        TaskTransitionSpec customSpec = mWmService.mTaskTransitionSpec;
+        @ColorInt int defaultFallbackColor = uiContext.getColor(R.color.overview_background);
+
+        if (customSpec != null && customSpec.backgroundColor != 0) {
+            return customSpec.backgroundColor;
+        }
+
+        return defaultFallbackColor;
     }
 
     final SurfaceAnimationRunner getSurfaceAnimationRunner() {
@@ -3551,4 +3535,53 @@
         getPendingTransaction().setSecure(mSurfaceControl, !canScreenshot);
         return true;
     }
+
+    private class AnimationRunnerBuilder {
+        /**
+         * Runs when the surface stops animating
+         */
+        private final List<Runnable> mOnAnimationFinished = new LinkedList<>();
+        /**
+         * Runs when the animation is cancelled but the surface is still animating
+         */
+        private final List<Runnable> mOnAnimationCancelled = new LinkedList<>();
+
+        private void setTaskBackgroundColor(@ColorInt int backgroundColor) {
+            TaskDisplayArea taskDisplayArea = getTaskDisplayArea();
+
+            if (taskDisplayArea != null) {
+                taskDisplayArea.setBackgroundColor(backgroundColor);
+
+                // Atomic counter to make sure the clearColor callback is only called one.
+                // It will be called twice in the case we cancel the animation without restart
+                // (in that case it will run as the cancel and finished callbacks).
+                final AtomicInteger callbackCounter = new AtomicInteger(0);
+                final Runnable clearBackgroundColorHandler = () -> {
+                    if (callbackCounter.getAndIncrement() == 0) {
+                        taskDisplayArea.clearBackgroundColor();
+                    }
+                };
+
+                // We want to make sure this is called both when the surface stops animating and
+                // also when an animation is cancelled (i.e. animation is replaced by another
+                // animation but and so the surface is still animating)
+                mOnAnimationFinished.add(clearBackgroundColorHandler);
+                mOnAnimationCancelled.add(clearBackgroundColorHandler);
+            }
+        }
+
+        private IAnimationStarter build() {
+            return (Transaction t, AnimationAdapter adapter, boolean hidden,
+                    @AnimationType int type, @Nullable AnimationAdapter snapshotAnim) -> {
+                startAnimation(getPendingTransaction(), adapter, !isVisible(), type,
+                        (animType, anim) -> mOnAnimationFinished.forEach(Runnable::run),
+                        () -> mOnAnimationCancelled.forEach(Runnable::run), snapshotAnim);
+            };
+        }
+    }
+
+    private interface IAnimationStarter {
+        void startAnimation(Transaction t, AnimationAdapter anim, boolean hidden,
+                @AnimationType int type, @Nullable AnimationAdapter snapshotAnim);
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 9e7bbcd..d17c9dd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -19,6 +19,7 @@
 import static android.Manifest.permission.CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS;
 import static android.Manifest.permission.INPUT_CONSUMER;
 import static android.Manifest.permission.INTERNAL_SYSTEM_WINDOW;
+import static android.Manifest.permission.MANAGE_ACTIVITY_TASKS;
 import static android.Manifest.permission.MANAGE_APP_TOKENS;
 import static android.Manifest.permission.READ_FRAME_BUFFER;
 import static android.Manifest.permission.REGISTER_WINDOW_MANAGER_LISTENERS;
@@ -266,6 +267,7 @@
 import android.view.Surface;
 import android.view.SurfaceControl;
 import android.view.SurfaceSession;
+import android.view.TaskTransitionSpec;
 import android.view.View;
 import android.view.WindowContentFrameStats;
 import android.view.WindowInsets;
@@ -433,7 +435,7 @@
             "persist.wm.enable_remote_keyguard_animation";
 
     private static final int sEnableRemoteKeyguardAnimation =
-            SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 0);
+            SystemProperties.getInt(ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY, 1);
 
     /**
      * @see #ENABLE_REMOTE_KEYGUARD_ANIMATION_PROPERTY
@@ -755,6 +757,11 @@
      */
     final Handler mAnimationHandler = new Handler(AnimationThread.getHandler().getLooper());
 
+    /**
+     * Used during task transitions to allow SysUI and launcher to customize task transitions.
+     */
+    TaskTransitionSpec mTaskTransitionSpec;
+
     boolean mHardKeyboardAvailable;
     WindowManagerInternal.OnHardKeyboardStatusChangeListener mHardKeyboardStatusChangeListener;
     SettingsObserver mSettingsObserver;
@@ -1775,6 +1782,7 @@
 
             win.mToken.addWindow(win);
             displayPolicy.addWindowLw(win, attrs);
+            displayPolicy.setDropInputModePolicy(win, win.mAttrs);
             if (type == TYPE_APPLICATION_STARTING && activity != null) {
                 activity.attachStartingWindow(win);
                 ProtoLog.v(WM_DEBUG_STARTING_WINDOW, "addWindow: %s startingWindow=%s",
@@ -3084,6 +3092,11 @@
         syncInputTransactions(true /* waitForAnimations */);
     }
 
+    @Override
+    public boolean isAppTransitionStateIdle() {
+        return getDefaultDisplayContentLocked().mAppTransition.isIdle();
+    }
+
     /**
      * Notifies activity manager that some Keyguard flags have changed and that it needs to
      * reevaluate the visibilities of the activities.
@@ -3792,6 +3805,14 @@
         }
     }
 
+    @Override
+    public SurfaceControl mirrorWallpaperSurface(int displayId) {
+        synchronized (mGlobalLock) {
+            final DisplayContent dc = mRoot.getDisplayContent(displayId);
+            return dc.mWallpaperController.mirrorWallpaperSurface();
+        }
+    }
+
     /**
      * Takes a snapshot of the screen.  In landscape mode this grabs the whole screen.
      * In portrait mode, it grabs the upper region of the screen based on the vertical dimension
@@ -5388,6 +5409,7 @@
                 case WINDOW_STATE_BLAST_SYNC_TIMEOUT: {
                     synchronized (mGlobalLock) {
                         final WindowState ws = (WindowState) msg.obj;
+                        Slog.i(TAG, "Blast sync timeout: " + ws);
                         ws.immediatelyNotifyBlastSync();
                     }
                     break;
@@ -5828,7 +5850,9 @@
             return;
         }
 
-        if (!displayContent.isReady() || !mPolicy.isScreenOn() || !displayContent.okToAnimate()) {
+        if (!displayContent.isReady() || !displayContent.getDisplayPolicy().isScreenOnFully()
+                || displayContent.getDisplayInfo().state == Display.STATE_OFF
+                || !displayContent.okToAnimate()) {
             // No need to freeze the screen before the display is ready,  if the screen is off,
             // or we can't currently animate.
             return;
@@ -8765,4 +8789,22 @@
                     : DEFAULT_DISPLAY;
         }
     }
+
+    @Override
+    public void setTaskTransitionSpec(TaskTransitionSpec spec) {
+        if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "setTaskTransitionSpec()")) {
+            throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
+        }
+
+        mTaskTransitionSpec = spec;
+    }
+
+    @Override
+    public void clearTaskTransitionSpec() {
+        if (!checkCallingPermission(MANAGE_ACTIVITY_TASKS, "clearTaskTransitionSpec()")) {
+            throw new SecurityException("Requires MANAGE_ACTIVITY_TASKS permission");
+        }
+
+        mTaskTransitionSpec = null;
+    }
 }
diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java
index 6288ab5..6e706e9 100644
--- a/services/core/java/com/android/server/wm/WindowOrganizerController.java
+++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java
@@ -66,6 +66,7 @@
 import android.window.ITaskFragmentOrganizer;
 import android.window.ITaskFragmentOrganizerController;
 import android.window.ITaskOrganizerController;
+import android.window.ITransitionMetricsReporter;
 import android.window.ITransitionPlayer;
 import android.window.IWindowContainerTransactionCallback;
 import android.window.IWindowOrganizerController;
@@ -1040,6 +1041,11 @@
         }
     }
 
+    @Override
+    public ITransitionMetricsReporter getTransitionMetricsReporter() {
+        return mTransitionController.mTransitionMetricsReporter;
+    }
+
     /** Whether the configuration changes are important to report back to an organizer. */
     static boolean configurationsAreEqualForOrganizer(
             Configuration newConfig, @Nullable Configuration oldConfig) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index af38641..81878e3 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1559,7 +1559,9 @@
                 // activity as it could lead to incorrect display metrics. For ex, IME services
                 // expect their config to match the config of the display with the IME window
                 // showing.
+                // If the configuration has been overridden by previous activity, empty it.
                 mIsActivityConfigOverrideAllowed = false;
+                unregisterActivityConfigurationListener();
                 break;
             default:
                 break;
diff --git a/services/core/java/com/android/server/wm/WindowState.java b/services/core/java/com/android/server/wm/WindowState.java
index 2410d7ec..ef0cba9 100644
--- a/services/core/java/com/android/server/wm/WindowState.java
+++ b/services/core/java/com/android/server/wm/WindowState.java
@@ -4967,20 +4967,27 @@
 
     private boolean applyImeWindowsIfNeeded(ToBooleanFunction<WindowState> callback,
             boolean traverseTopToBottom) {
-        // If this window is the current IME target, so we need to process the IME windows
-        // directly above it. The exception is if we are in split screen
-        // in which case we process the IME at the DisplayContent level to
-        // ensure it is above the docked divider.
-        // (i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
-        // window will be ignored to traverse when the IME target is still in split-screen mode).
-        if (isImeLayeringTarget()
-                && (!mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
-                         || getTask() == null)) {
-            if (mDisplayContent.forAllImeWindows(callback, traverseTopToBottom)) {
-                return true;
-            }
+        // No need to apply to IME window if the window is not the current IME layering target.
+        if (!isImeLayeringTarget()) {
+            return false;
         }
-        return false;
+        // If we are in split screen which case we process the IME at the DisplayContent level to
+        // ensure it is above the docked divider.
+        // i.e. Like {@link DisplayContent.ImeContainer#skipImeWindowsDuringTraversal}, the IME
+        // window will be ignored to traverse when the IME target is still in split-screen mode.
+        if (mDisplayContent.getDefaultTaskDisplayArea().isSplitScreenModeActivated()
+                && getTask() != null) {
+            return false;
+        }
+        // Note that we don't process IME window if the IME input target is not on the screen.
+        // In case some unexpected IME visibility cases happen like starting the remote
+        // animation on the keyguard but seeing the IME window that originally on the app
+        // which behinds the keyguard.
+        final WindowState imeInputTarget = getImeInputTarget();
+        if (imeInputTarget != null && !(imeInputTarget.isDrawn() || imeInputTarget.isVisible())) {
+            return false;
+        }
+        return mDisplayContent.forAllImeWindows(callback, traverseTopToBottom);
     }
 
     private boolean applyInOrderWithImeWindows(ToBooleanFunction<WindowState> callback,
@@ -6041,10 +6048,6 @@
         // in WAITING state rather than READY.
         mSyncState = SYNC_STATE_WAITING_FOR_DRAW;
         requestRedrawForSync();
-
-        mWmService.mH.removeMessages(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this);
-        mWmService.mH.sendNewMessageDelayed(WINDOW_STATE_BLAST_SYNC_TIMEOUT, this,
-            BLAST_TIMEOUT_DURATION);
         return true;
     }
 
diff --git a/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java b/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java
new file mode 100644
index 0000000..ea746d1
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/camera/CameraServiceProxyTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 2021 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.camera;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import androidx.test.InstrumentationRegistry;
+
+import android.content.Context;
+import android.hardware.camera2.CameraCharacteristics;
+import android.hardware.camera2.CameraMetadata;
+import android.view.Display;
+import android.view.Surface;
+
+import java.util.HashMap;
+
+@RunWith(JUnit4.class)
+public class CameraServiceProxyTest {
+
+    @Test
+    public void testGetCropRotateScale() {
+
+        Context ctx = InstrumentationRegistry.getContext();
+
+        // Check resizeability and SDK
+        CameraServiceProxy.TaskInfo taskInfo = new CameraServiceProxy.TaskInfo();
+        taskInfo.isResizeable = true;
+        taskInfo.displayId = Display.DEFAULT_DISPLAY;
+        taskInfo.isFixedOrientationLandscape = false;
+        taskInfo.isFixedOrientationPortrait = true;
+        // Resizeable apps should be ignored
+        assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                Surface.ROTATION_90 , CameraCharacteristics.LENS_FACING_BACK,
+                /*ignoreResizableAndSdkCheck*/false)).isEqualTo(
+                CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
+        // Resizeable apps will be considered in case the ignore flag is set
+        assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                Surface.ROTATION_90, CameraCharacteristics.LENS_FACING_BACK,
+                /*ignoreResizableAndSdkCheck*/true)).isEqualTo(
+                CameraMetadata.SCALER_ROTATE_AND_CROP_90);
+        taskInfo.isResizeable = false;
+        // Non-resizeable apps should be considered
+        assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                Surface.ROTATION_90, CameraCharacteristics.LENS_FACING_BACK,
+                /*ignoreResizableAndSdkCheck*/false)).isEqualTo(
+                CameraMetadata.SCALER_ROTATE_AND_CROP_90);
+        // The ignore flag for non-resizeable should have no effect
+        assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                Surface.ROTATION_90, CameraCharacteristics.LENS_FACING_BACK,
+                /*ignoreResizableAndSdkCheck*/true)).isEqualTo(
+                CameraMetadata.SCALER_ROTATE_AND_CROP_90);
+        // Non-fixed orientation should be ignored
+        taskInfo.isFixedOrientationLandscape = false;
+        taskInfo.isFixedOrientationPortrait = false;
+        assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                Surface.ROTATION_90, CameraCharacteristics.LENS_FACING_BACK,
+                /*ignoreResizableAndSdkCheck*/true)).isEqualTo(
+                CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
+        // Check rotation and lens facing combinations
+        HashMap<Integer, Integer> backFacingMap = new HashMap<Integer, Integer>() {{
+            put(Surface.ROTATION_0, CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
+            put(Surface.ROTATION_90, CameraMetadata.SCALER_ROTATE_AND_CROP_90);
+            put(Surface.ROTATION_270, CameraMetadata.SCALER_ROTATE_AND_CROP_270);
+            put(Surface.ROTATION_180, CameraMetadata.SCALER_ROTATE_AND_CROP_180);
+        }};
+        taskInfo.isFixedOrientationPortrait = true;
+        backFacingMap.forEach((key, value) -> {
+            assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                    key, CameraCharacteristics.LENS_FACING_BACK,
+                    /*ignoreResizableAndSdkCheck*/true)).isEqualTo(value);
+        });
+        HashMap<Integer, Integer> frontFacingMap = new HashMap<Integer, Integer>() {{
+            put(Surface.ROTATION_0, CameraMetadata.SCALER_ROTATE_AND_CROP_NONE);
+            put(Surface.ROTATION_90, CameraMetadata.SCALER_ROTATE_AND_CROP_270);
+            put(Surface.ROTATION_270, CameraMetadata.SCALER_ROTATE_AND_CROP_90);
+            put(Surface.ROTATION_180, CameraMetadata.SCALER_ROTATE_AND_CROP_180);
+        }};
+        frontFacingMap.forEach((key, value) -> {
+            assertThat(CameraServiceProxy.getCropRotateScale(ctx, ctx.getPackageName(), taskInfo,
+                    key, CameraCharacteristics.LENS_FACING_FRONT,
+                    /*ignoreResizableAndSdkCheck*/true)).isEqualTo(value);
+        });
+    }
+}
diff --git a/services/tests/servicestests/src/com/android/server/camera/OWNERS b/services/tests/servicestests/src/com/android/server/camera/OWNERS
new file mode 100644
index 0000000..f48a95c
--- /dev/null
+++ b/services/tests/servicestests/src/com/android/server/camera/OWNERS
@@ -0,0 +1 @@
+include platform/frameworks/av:/camera/OWNERS
diff --git a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
index 581ff54..9099bb5 100644
--- a/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
+++ b/services/tests/servicestests/src/com/android/server/pm/parsing/AndroidPackageParsingTestBase.kt
@@ -341,10 +341,8 @@
             launchToken=${this.launchToken}
             lockTaskLaunchMode=${this.lockTaskLaunchMode}
             logo=${this.logo}
-            maxAspectRatio=${this.maxAspectRatio}
             maxRecents=${this.maxRecents}
             metaData=${this.metaData.dumpToString()}
-            minAspectRatio=${this.minAspectRatio}
             name=${this.name}
             nonLocalizedLabel=${
                 // Per b/184574333, v1 mistakenly trimmed the label. v2 fixed this, but for test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index b093974..128bfa8 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -166,6 +166,8 @@
     @Before
     public void setUp() throws Exception {
         setBooted(mAtm);
+        // Because the booted state is set, avoid starting real home if there is no task.
+        doReturn(false).when(mRootWindowContainer).resumeHomeActivity(any(), anyString(), any());
     }
 
     private TestStartingWindowOrganizer registerTestStartingWindowOrganizer() {
@@ -1083,6 +1085,7 @@
      */
     @Test
     public void testFinishActivityIfPossible_nonVisibleNoAppTransition() {
+        registerTestTransitionPlayer();
         final ActivityRecord activity = createActivityWithTask();
         // Put an activity on top of test activity to make it invisible and prevent us from
         // accidentally resuming the topmost one again.
@@ -1093,6 +1096,7 @@
         activity.finishIfPossible("test", false /* oomAdj */);
 
         verify(activity.mDisplayContent, never()).prepareAppTransition(eq(TRANSIT_CLOSE));
+        assertFalse(activity.inTransition());
     }
 
     /**
@@ -1101,11 +1105,7 @@
      */
     @Test
     public void testFinishActivityIfPossible_lastInTaskRequestsTransitionWithTrigger() {
-        // Set-up mock shell transitions
-        final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
-                mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
-        mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
-
+        final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
         final ActivityRecord activity = createActivityWithTask();
         activity.finishing = false;
         activity.mVisibleRequested = true;
@@ -1117,6 +1117,29 @@
     }
 
     /**
+     * Verify that when collecting activity to the existing close transition, it should not affect
+     * ready state.
+     */
+    @Test
+    public void testFinishActivityIfPossible_collectToExistingTransition() {
+        final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
+        final ActivityRecord activity = createActivityWithTask();
+        activity.setState(PAUSED, "test");
+        activity.finishIfPossible("test", false /* oomAdj */);
+        final Transition lastTransition = testPlayer.mLastTransit;
+        assertTrue(lastTransition.allReady());
+        assertTrue(activity.inTransition());
+
+        // Collect another activity to the existing transition without changing ready state.
+        final ActivityRecord activity2 = createActivityRecord(activity.getTask());
+        activity2.setState(PAUSING, "test");
+        activity2.finishIfPossible("test", false /* oomAdj */);
+        assertTrue(activity2.inTransition());
+        assertEquals(lastTransition, testPlayer.mLastTransit);
+        assertTrue(lastTransition.allReady());
+    }
+
+    /**
      * Verify that complete finish request for non-finishing activity is invalid.
      */
     @Test(expected = IllegalArgumentException.class)
@@ -1752,6 +1775,11 @@
                 anyInt() /* orientation */, anyInt() /* lastRotation */);
         // Set to visible so the activity can freeze the screen.
         activity.setVisibility(true);
+        // Update the display policy to make the screen fully turned on so the freeze is allowed
+        display.getDisplayPolicy().screenTurnedOn(null);
+        display.getDisplayPolicy().finishKeyguardDrawn();
+        display.getDisplayPolicy().finishWindowsDrawn();
+        display.getDisplayPolicy().finishScreenTurningOn();
 
         display.rotateInDifferentOrientationIfNeeded(activity);
         display.setFixedRotationLaunchingAppUnchecked(activity);
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
index 24bbf46..f3c1ec5 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayContentTests.java
@@ -1674,11 +1674,7 @@
     public void testShellTransitRotation() {
         DisplayContent dc = createNewDisplay();
 
-        // Set-up mock shell transitions
-        final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
-                mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
-        mAtm.getTransitionController().registerTransitionPlayer(testPlayer);
-
+        final TestTransitionPlayer testPlayer = registerTestTransitionPlayer();
         final DisplayRotation dr = dc.getDisplayRotation();
         doCallRealMethod().when(dr).updateRotationUnchecked(anyBoolean());
         // Rotate 180 degree so the display doesn't have configuration change. This condition is
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
index 3982a83..1d2baab 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayPolicyTestsBase.java
@@ -31,6 +31,7 @@
 import static com.android.server.wm.utils.CoordinateTransforms.transformPhysicalToLogicalCoordinates;
 
 import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.anyInt;
 
 import android.content.Context;
 import android.content.ContextWrapper;
@@ -75,13 +76,12 @@
         final TestContextWrapper context = new TestContextWrapper(
                 mDisplayPolicy.getContext(), mDisplayPolicy.getCurrentUserResources());
         final TestableResources resources = context.getResourceMocker();
-        resources.addOverride(R.dimen.status_bar_height_portrait, STATUS_BAR_HEIGHT);
-        resources.addOverride(R.dimen.status_bar_height_landscape, STATUS_BAR_HEIGHT);
         resources.addOverride(R.dimen.navigation_bar_height, NAV_BAR_HEIGHT);
         resources.addOverride(R.dimen.navigation_bar_height_landscape, NAV_BAR_HEIGHT);
         resources.addOverride(R.dimen.navigation_bar_width, NAV_BAR_HEIGHT);
         resources.addOverride(R.dimen.navigation_bar_frame_height_landscape, NAV_BAR_HEIGHT);
         resources.addOverride(R.dimen.navigation_bar_frame_height, NAV_BAR_HEIGHT);
+        doReturn(STATUS_BAR_HEIGHT).when(mDisplayPolicy).getStatusBarHeightForRotation(anyInt());
         doReturn(resources.getResources()).when(mDisplayPolicy).getCurrentUserResources();
         doReturn(true).when(mDisplayPolicy).hasNavigationBar();
         doReturn(true).when(mDisplayPolicy).hasStatusBar();
diff --git a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
index 08312ef..575e082 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RemoteAnimationControllerTest.java
@@ -36,12 +36,14 @@
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
 import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_WINDOW_ANIMATION;
 
+import static junit.framework.Assert.assertFalse;
 import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyFloat;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
 import static org.mockito.Mockito.mock;
@@ -699,6 +701,51 @@
         }
     }
 
+    @UseTestDisplay(addWindows = W_INPUT_METHOD)
+    @Test
+    public void testLaunchRemoteAnimationWithoutImeBehind() {
+        final WindowState win1 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin1");
+        final WindowState win2 = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin2");
+
+        // Simulating win1 has shown IME and being IME layering/input target
+        mDisplayContent.setImeLayeringTarget(win1);
+        mDisplayContent.setImeInputTarget(win1);
+        mImeWindow.mWinAnimator.mSurfaceController = mock(WindowSurfaceController.class);
+        mImeWindow.mWinAnimator.hide(mDisplayContent.getPendingTransaction(), "test");
+        spyOn(mDisplayContent);
+        doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController).hasSurface();
+        doReturn(true).when(mImeWindow.mWinAnimator.mSurfaceController)
+                .prepareToShowInTransaction(any(), anyFloat());
+        makeWindowVisibleAndDrawn(mImeWindow);
+        assertTrue(mImeWindow.isOnScreen());
+        assertFalse(mImeWindow.isParentWindowHidden());
+
+        try {
+            // Simulating now win1 is being covered by the lockscreen which has no surface,
+            // and then launching an activity win2 with the remote animation
+            win1.mHasSurface = false;
+            mDisplayContent.mOpeningApps.add(win2.mActivityRecord);
+            final AnimationAdapter adapter = mController.createRemoteAnimationRecord(
+                    win2.mActivityRecord, new Point(50, 100), null,
+                    new Rect(50, 100, 150, 150), null).mAdapter;
+            adapter.startAnimation(mMockLeash, mMockTransaction, ANIMATION_TYPE_APP_TRANSITION,
+                    mFinishedCallback);
+
+            mDisplayContent.applySurfaceChangesTransaction();
+            mController.goodToGo(TRANSIT_OLD_TASK_OPEN);
+            mWm.mAnimator.executeAfterPrepareSurfacesRunnables();
+
+            verify(mMockRunner).onAnimationStart(eq(TRANSIT_OLD_TASK_OPEN),
+                    any(), any(), any(), any());
+            // Verify the IME window won't apply surface change transaction with forAllImeWindows
+            verify(mDisplayContent, never()).forAllImeWindows(any(), eq(true));
+        } catch (Exception e) {
+            // no-op
+        } finally {
+            mDisplayContent.mOpeningApps.clear();
+        }
+    }
+
     private AnimationAdapter setupForNonAppTargetNavBar(int transit, boolean shouldAttachNavBar) {
         final WindowState win = createWindow(null /* parent */, TYPE_BASE_APPLICATION, "testWin");
         mDisplayContent.mOpeningApps.add(win.mActivityRecord);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 7266631..bed0a94 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -83,6 +83,8 @@
 
 import androidx.test.filters.MediumTest;
 
+import com.android.internal.policy.SystemBarUtils;
+
 import libcore.junit.util.compat.CoreCompatChangeRule.DisableCompatChanges;
 import libcore.junit.util.compat.CoreCompatChangeRule.EnableCompatChanges;
 
@@ -1121,6 +1123,98 @@
     }
 
     @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+    public void testOverrideMinAspectRatioScreenOrientationNotSetThenChangedToPortrait() {
+        // In this test, the activity's orientation isn't fixed to portrait, therefore the override
+        // isn't applied.
+
+        setUpDisplaySizeWithApp(1000, 1200);
+
+        // Create a size compat activity on the same task.
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(mTask)
+                .setComponent(ComponentName.createRelative(mContext,
+                        SizeCompatTests.class.getName()))
+                .setUid(android.os.Process.myUid())
+                .build();
+
+        // The per-package override should have no effect
+        assertEquals(1200, activity.getBounds().height());
+        assertEquals(1000, activity.getBounds().width());
+
+        // After changing the orientation to portrait the override should be applied.
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        activity.clearSizeCompatMode();
+
+        // The per-package override forces the activity into a 3:2 aspect ratio
+        assertEquals(1200, activity.getBounds().height());
+        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
+                activity.getBounds().width(), 0.5);
+    }
+
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+    public void testOverrideMinAspectRatioScreenOrientationLandscapeThenChangedToPortrait() {
+        // In this test, the activity's orientation isn't fixed to portrait, therefore the override
+        // isn't applied.
+
+        setUpDisplaySizeWithApp(1000, 1200);
+
+        // Create a size compat activity on the same task.
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(mTask)
+                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
+                .setComponent(ComponentName.createRelative(mContext,
+                        SizeCompatTests.class.getName()))
+                .setUid(android.os.Process.myUid())
+                .build();
+
+        // The per-package override should have no effect
+        assertEquals(1200, activity.getBounds().height());
+        assertEquals(1000, activity.getBounds().width());
+
+        // After changing the orientation to portrait the override should be applied.
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
+        activity.clearSizeCompatMode();
+
+        // The per-package override forces the activity into a 3:2 aspect ratio
+        assertEquals(1200, activity.getBounds().height());
+        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
+                activity.getBounds().width(), 0.5);
+    }
+
+    @Test
+    @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO,
+            ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
+    public void testOverrideMinAspectRatioScreenOrientationPortraitThenChangedToUnspecified() {
+        setUpDisplaySizeWithApp(1000, 1200);
+
+        // Create a size compat activity on the same task.
+        final ActivityRecord activity = new ActivityBuilder(mAtm)
+                .setTask(mTask)
+                .setScreenOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
+                .setComponent(ComponentName.createRelative(mContext,
+                        SizeCompatTests.class.getName()))
+                .setUid(android.os.Process.myUid())
+                .build();
+
+        // The per-package override forces the activity into a 3:2 aspect ratio
+        assertEquals(1200, activity.getBounds().height());
+        assertEquals(1200 / ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM_VALUE,
+                activity.getBounds().width(), 0.5);
+
+        // After changing the orientation to landscape the override shouldn't be applied.
+        activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED);
+        activity.clearSizeCompatMode();
+
+        // The per-package override should have no effect
+        assertEquals(1200, activity.getBounds().height());
+        assertEquals(1000, activity.getBounds().width());
+    }
+
+    @Test
     @EnableCompatChanges({ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_MEDIUM})
     public void testOverrideMinAspectRatioWithoutGlobalOverride() {
         // In this test, only OVERRIDE_MIN_ASPECT_RATIO_1_5 is set, which has no effect without
@@ -2128,8 +2222,7 @@
                 displayContent.mWmService, mock(Session.class), new TestIWindow(), attrs, token);
         token.addWindow(statusBar);
         statusBar.setRequestedSize(displayContent.mBaseDisplayWidth,
-                displayContent.getDisplayUiContext().getResources().getDimensionPixelSize(
-                        com.android.internal.R.dimen.status_bar_height));
+                SystemBarUtils.getStatusBarHeight(displayContent.getDisplayUiContext()));
 
         displayPolicy.addWindowLw(statusBar, attrs);
         displayPolicy.layoutWindowLw(statusBar, null, displayContent.mDisplayFrames);
diff --git a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
index 7bac3e7..420ea8e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SyncEngineTests.java
@@ -62,7 +62,7 @@
     public void testTrivialSyncCallback() {
         TestWindowContainer mockWC = new TestWindowContainer(mWm, false /* waiter */);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -90,7 +90,7 @@
     public void testWaitingSyncCallback() {
         TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -114,7 +114,7 @@
     public void testInvisibleSyncCallback() {
         TestWindowContainer mockWC = new TestWindowContainer(mWm, true /* waiter */);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -142,7 +142,7 @@
         parentWC.addChild(childWC, POSITION_TOP);
         parentWC.addChild(childWC2, POSITION_TOP);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -175,7 +175,7 @@
         TestWindowContainer childWC = new TestWindowContainer(mWm, true /* waiter */);
         parentWC.addChild(childWC, POSITION_TOP);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -206,7 +206,7 @@
         parentWC.addChild(topChildWC, POSITION_TOP);
         parentWC.addChild(botChildWC, POSITION_BOTTOM);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -238,7 +238,7 @@
         parentWC.addChild(topChildWC, POSITION_TOP);
         parentWC.addChild(botChildWC, POSITION_BOTTOM);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -273,7 +273,7 @@
         parentWC.addChild(topChildWC, POSITION_TOP);
         nonMemberParentWC.addChild(botChildWC, POSITION_BOTTOM);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
@@ -312,7 +312,7 @@
         parentWC.addChild(topChildWC, POSITION_TOP);
         parentWC.addChild(botChildWC, POSITION_BOTTOM);
 
-        BLASTSyncEngine bse = new BLASTSyncEngine(mWm);
+        final BLASTSyncEngine bse = createTestBLASTSyncEngine();
 
         BLASTSyncEngine.TransactionReadyListener listener = mock(
                 BLASTSyncEngine.TransactionReadyListener.class);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index 16d75ca..9001578 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -128,10 +128,6 @@
     }
 
     @Override
-    public void setKeyguardCandidateLw(WindowState win) {
-    }
-
-    @Override
     public Animation createHiddenByKeyguardExit(boolean onWallpaper,
             boolean goingToNotificationShade, boolean subtleAnimation) {
         return null;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
index a1c24c2..4e77fa7 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TransitionTests.java
@@ -21,7 +21,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
 import static android.view.WindowManager.LayoutParams.TYPE_WALLPAPER;
 import static android.view.WindowManager.TRANSIT_CLOSE;
-import static android.view.WindowManager.TRANSIT_OLD_TASK_OPEN;
 import static android.view.WindowManager.TRANSIT_OPEN;
 import static android.view.WindowManager.TRANSIT_TO_BACK;
 import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -44,6 +43,7 @@
 import android.platform.test.annotations.Presubmit;
 import android.util.ArrayMap;
 import android.util.ArraySet;
+import android.view.SurfaceControl;
 import android.window.ITaskOrganizer;
 import android.window.ITransitionPlayer;
 import android.window.TransitionInfo;
@@ -53,9 +53,12 @@
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
 /**
  * Build/Install/Run:
- *  atest WmTests:TransitionRecordTests
+ *  atest WmTests:TransitionTests
  */
 @SmallTest
 @Presubmit
@@ -64,13 +67,13 @@
 
     private Transition createTestTransition(int transitType) {
         TransitionController controller = mock(TransitionController.class);
-        BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
-        return new Transition(transitType, 0 /* flags */, controller, sync);
+        final BLASTSyncEngine sync = createTestBLASTSyncEngine();
+        return new Transition(transitType, 0 /* flags */, 0 /* timeoutMs */, controller, sync);
     }
 
     @Test
     public void testCreateInfo_NewTask() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
         ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
         ArraySet<WindowContainer> participants = transition.mParticipants;
 
@@ -88,7 +91,7 @@
         closing.mVisibleRequested = false;
         opening.mVisibleRequested = true;
 
-        int transit = TRANSIT_OLD_TASK_OPEN;
+        final int transit = transition.mType;
         int flags = 0;
 
         // Check basic both tasks participating
@@ -127,7 +130,7 @@
 
     @Test
     public void testCreateInfo_NestedTasks() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
         ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
         ArraySet<WindowContainer> participants = transition.mParticipants;
 
@@ -152,7 +155,7 @@
         opening.mVisibleRequested = true;
         opening2.mVisibleRequested = true;
 
-        int transit = TRANSIT_OLD_TASK_OPEN;
+        final int transit = transition.mType;
         int flags = 0;
 
         // Check full promotion from leaf
@@ -177,7 +180,7 @@
 
     @Test
     public void testCreateInfo_DisplayArea() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
         ArrayMap<WindowContainer, Transition.ChangeInfo> changes = transition.mChanges;
         ArraySet<WindowContainer> participants = transition.mParticipants;
         final Task showTask = createTask(mDisplayContent);
@@ -199,7 +202,7 @@
         showing.mVisibleRequested = true;
         showing2.mVisibleRequested = true;
 
-        int transit = TRANSIT_OLD_TASK_OPEN;
+        final int transit = transition.mType;
         int flags = 0;
 
         // Check promotion to DisplayArea
@@ -228,7 +231,7 @@
 
     @Test
     public void testCreateInfo_existenceChange() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
 
         final Task openTask = createTask(mDisplayContent);
         final ActivityRecord opening = createActivityRecord(openTask);
@@ -258,7 +261,7 @@
 
     @Test
     public void testCreateInfo_ordering() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
         // pick some number with a high enough chance of being out-of-order when added to set.
         final int taskCount = 6;
 
@@ -294,7 +297,7 @@
 
     @Test
     public void testCreateInfo_wallpaper() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
         // pick some number with a high enough chance of being out-of-order when added to set.
         final int taskCount = 4;
         final int showWallpaperTask = 2;
@@ -345,7 +348,7 @@
 
     @Test
     public void testTargets_noIntermediatesToWallpaper() {
-        final Transition transition = createTestTransition(TRANSIT_OLD_TASK_OPEN);
+        final Transition transition = createTestTransition(TRANSIT_OPEN);
 
         final WallpaperWindowToken wallpaperWindowToken = new WallpaperWindowToken(mWm,
                 mock(IBinder.class), true, mDisplayContent, true /* ownerCanManageAppTokens */);
@@ -419,7 +422,7 @@
         openInOpen.mVisibleRequested = true;
         openInChange.mVisibleRequested = true;
 
-        int transit = TRANSIT_OLD_TASK_OPEN;
+        final int transit = transition.mType;
         int flags = 0;
 
         // Check full promotion from leaf
@@ -450,6 +453,22 @@
     }
 
     @Test
+    public void testTimeout() {
+        final TransitionController controller = new TransitionController(mAtm,
+                mock(TaskSnapshotController.class));
+        final BLASTSyncEngine sync = new BLASTSyncEngine(mWm);
+        final CountDownLatch latch = new CountDownLatch(1);
+        // When the timeout is reached, it will finish the sync-group and notify transaction ready.
+        new Transition(TRANSIT_OPEN, 0 /* flags */, 10 /* timeoutMs */, controller, sync) {
+            @Override
+            public void onTransactionReady(int syncId, SurfaceControl.Transaction transaction) {
+                latch.countDown();
+            }
+        };
+        assertTrue(awaitInWmLock(() -> latch.await(3, TimeUnit.SECONDS)));
+    }
+
+    @Test
     public void testIntermediateVisibility() {
         final TaskSnapshotController snapshotController = mock(TaskSnapshotController.class);
         final TransitionController controller = new TransitionController(mAtm, snapshotController);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
index b2d4eea..81b00ea 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowTestsBase.java
@@ -789,6 +789,23 @@
         };
     }
 
+    BLASTSyncEngine createTestBLASTSyncEngine() {
+        return new BLASTSyncEngine(mWm) {
+            @Override
+            void scheduleTimeout(SyncGroup s, long timeoutMs) {
+                // Disable timeout.
+            }
+        };
+    }
+
+    /** Sets up a simple implementation of transition player for shell transitions. */
+    TestTransitionPlayer registerTestTransitionPlayer() {
+        final TestTransitionPlayer testPlayer = new TestTransitionPlayer(
+                mAtm.getTransitionController(), mAtm.mWindowOrganizerController);
+        testPlayer.mController.registerTransitionPlayer(testPlayer);
+        return testPlayer;
+    }
+
     /**
      * Avoids rotating screen disturbed by some conditions. It is usually used for the default
      * display that is not the instance of {@link TestDisplayContent} (it bypasses the conditions).
@@ -1597,7 +1614,7 @@
         }
     }
 
-    class TestTransitionPlayer extends ITransitionPlayer.Stub {
+    static class TestTransitionPlayer extends ITransitionPlayer.Stub {
         final TransitionController mController;
         final WindowOrganizerController mOrganizer;
         Transition mLastTransit = null;
diff --git a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
index 22ea3d5..72b05c0 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ZOrderingTests.java
@@ -23,7 +23,6 @@
 import static android.app.WindowConfiguration.WINDOWING_MODE_MULTI_WINDOW;
 import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_PRIMARY;
-import static android.app.WindowConfiguration.WINDOWING_MODE_SPLIT_SCREEN_SECONDARY;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ABOVE_SUB_PANEL;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_MEDIA;
@@ -442,24 +441,42 @@
 
     @Test
     public void testDockedDividerPosition() {
-        final WindowState pinnedStackWindow = createWindow(null, WINDOWING_MODE_PINNED,
-                ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION, mDisplayContent,
-                "pinnedStackWindow");
-        final WindowState splitScreenWindow = createWindow(null,
-                WINDOWING_MODE_SPLIT_SCREEN_PRIMARY, ACTIVITY_TYPE_STANDARD, TYPE_BASE_APPLICATION,
-                mDisplayContent, "splitScreenWindow");
-        final WindowState splitScreenSecondaryWindow = createWindow(null,
-                WINDOWING_MODE_SPLIT_SCREEN_SECONDARY, ACTIVITY_TYPE_STANDARD,
-                TYPE_BASE_APPLICATION, mDisplayContent, "splitScreenSecondaryWindow");
-        final WindowState assistantStackWindow = createWindow(null,
-                WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_ASSISTANT, TYPE_BASE_APPLICATION,
-                mDisplayContent, "assistantStackWindow");
+        final Task pinnedTask =
+                createTask(mDisplayContent, WINDOWING_MODE_PINNED, ACTIVITY_TYPE_STANDARD);
+        final WindowState pinnedWindow =
+                createAppWindow(pinnedTask, ACTIVITY_TYPE_STANDARD, "pinnedWindow");
+
+        final Task belowTask =
+                createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowState belowTaskWindow =
+                createAppWindow(belowTask, ACTIVITY_TYPE_STANDARD, "belowTaskWindow");
+
+        final Task splitScreenTask1 =
+                createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+        final WindowState splitWindow1 =
+                createAppWindow(splitScreenTask1, ACTIVITY_TYPE_STANDARD, "splitWindow1");
+        final Task splitScreenTask2 =
+                createTask(mDisplayContent, WINDOWING_MODE_MULTI_WINDOW, ACTIVITY_TYPE_STANDARD);
+        final WindowState splitWindow2 =
+                createAppWindow(splitScreenTask2, ACTIVITY_TYPE_STANDARD, "splitWindow2");
+        splitScreenTask1.setAdjacentTaskFragment(splitScreenTask2);
+        splitScreenTask2.setAdjacentTaskFragment(splitScreenTask1);
+
+        final Task aboveTask =
+                createTask(mDisplayContent, WINDOWING_MODE_FULLSCREEN, ACTIVITY_TYPE_STANDARD);
+        final WindowState aboveTaskWindow =
+                createAppWindow(aboveTask, ACTIVITY_TYPE_STANDARD, "aboveTaskWindow");
 
         mDisplayContent.assignChildLayers(mTransaction);
 
-        assertWindowHigher(mDockedDividerWindow, splitScreenWindow);
-        assertWindowHigher(mDockedDividerWindow, splitScreenSecondaryWindow);
-        assertWindowHigher(pinnedStackWindow, mDockedDividerWindow);
+        assertWindowHigher(splitWindow1, belowTaskWindow);
+        assertWindowHigher(splitWindow1, belowTaskWindow);
+        assertWindowHigher(splitWindow2, belowTaskWindow);
+        assertWindowHigher(splitWindow2, belowTaskWindow);
+        assertWindowHigher(mDockedDividerWindow, splitWindow1);
+        assertWindowHigher(mDockedDividerWindow, splitWindow2);
+        assertWindowHigher(aboveTaskWindow, mDockedDividerWindow);
+        assertWindowHigher(pinnedWindow, aboveTaskWindow);
     }
 
     @Test
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 68ef754..cfc145a 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -1874,6 +1874,20 @@
             "lte_plus_threshold_bandwidth_khz_int";
 
     /**
+     * The combined channel bandwidth threshold (non-inclusive) in KHz required to display the
+     * NR advanced (i.e. 5G+) data icon. It is 0 by default, meaning minimum bandwidth check is
+     * not enabled. Other factors like bands or frequency can also determine whether the NR
+     * advanced data icon is shown or not.
+     *
+     * @see #KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY
+     * @see #KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT
+     *
+     * @hide
+     */
+    public static final String KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT =
+            "nr_advanced_threshold_bandwidth_khz_int";
+
+    /**
      * The string is used to filter redundant string from PLMN Network Name that's supplied by
      * specific carrier.
      *
@@ -3538,6 +3552,17 @@
             "nr_advanced_capable_pco_id_int";
 
     /**
+     * Enabled NR advanced (i.e. 5G+) icon while roaming. The default value is {@code true}, meaming
+     * the same NR advanced logic used for home network will be used for roaming network as well.
+     * Set this to {@code false} will disable NR advanced icon while the device is roaming,
+     * regardless meeting NR advanced criteria or not.
+     *
+     * @hide
+     */
+    public static final String KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL =
+            "enable_nr_advanced_for_roaming_bool";
+
+    /**
      * This configuration allows the framework to use user data communication to detect Idle state,
      * and this is used on the 5G icon.
      *
@@ -5171,6 +5196,16 @@
     public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool";
 
     /**
+     * Flag specifying whether VoNR should be enabled for carrier.
+     * If true, VoNr will be enabled. If false, hard disabled.
+     *
+     * Disabled by default.
+     *
+     * @hide
+     */
+    public static final String KEY_VONR_ENABLED_BOOL = "vonr_enabled_bool";
+
+    /**
      * Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes
      *
      * @hide
@@ -5565,6 +5600,7 @@
         sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, "");
         sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true);
         sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000);
+        sDefaults.putInt(KEY_NR_ADVANCED_THRESHOLD_BANDWIDTH_KHZ_INT, 0);
         sDefaults.putIntArray(KEY_CARRIER_NR_AVAILABILITIES_INT_ARRAY,
                 new int[]{CARRIER_NR_AVAILABILITY_NSA, CARRIER_NR_AVAILABILITY_SA});
         sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true);
@@ -5660,6 +5696,7 @@
         sDefaults.putLong(KEY_5G_WATCHDOG_TIME_MS_LONG, 3600000);
         sDefaults.putIntArray(KEY_ADDITIONAL_NR_ADVANCED_BANDS_INT_ARRAY, new int[0]);
         sDefaults.putInt(KEY_NR_ADVANCED_CAPABLE_PCO_ID_INT, 0);
+        sDefaults.putBoolean(KEY_ENABLE_NR_ADVANCED_WHILE_ROAMING_BOOL, true);
         sDefaults.putBoolean(KEY_LTE_ENDC_USING_USER_DATA_FOR_RRC_DETECTION_BOOL, false);
         sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_BOOL, false);
         sDefaults.putBoolean(KEY_UNMETERED_NR_NSA_MMWAVE_BOOL, false);
@@ -5785,6 +5822,7 @@
         sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false);
         sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false);
         sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false);
+        sDefaults.putBoolean(KEY_VONR_ENABLED_BOOL, false);
     }
 
     /**
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 114c90b..1be1f2f 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -949,6 +949,15 @@
     public static final String VOIMS_OPT_IN_STATUS = SimInfo.COLUMN_VOIMS_OPT_IN_STATUS;
 
     /**
+     * TelephonyProvider column name for NR Advanced calling
+     * Determines if the user has enabled VoNR settings for this subscription.
+     *
+     * @hide
+     */
+    public static final String NR_ADVANCED_CALLING_ENABLED =
+            SimInfo.COLUMN_NR_ADVANCED_CALLING_ENABLED;
+
+    /**
      * Profile class of the subscription
      * @hide
      */
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.cpp b/tools/aapt2/format/binary/BinaryResourceParser.cpp
index 72eaa35..a8845ef 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.cpp
+++ b/tools/aapt2/format/binary/BinaryResourceParser.cpp
@@ -120,6 +120,13 @@
                                   static_cast<int>(parser.chunk()->type)));
     }
   }
+
+  if (!staged_entries_to_remove_.empty()) {
+    diag_->Error(DiagMessage(source_) << "didn't find " << staged_entries_to_remove_.size()
+                                      << " original staged resources");
+    return false;
+  }
+
   return true;
 }
 
@@ -393,6 +400,12 @@
       return false;
     }
 
+    if (const auto to_remove_it = staged_entries_to_remove_.find({name, res_id});
+        to_remove_it != staged_entries_to_remove_.end()) {
+      staged_entries_to_remove_.erase(to_remove_it);
+      continue;
+    }
+
     NewResourceBuilder res_builder(name);
     res_builder.SetValue(std::move(resource_value), config)
         .SetId(res_id, OnIdConflict::CREATE_ENTRY)
@@ -533,9 +546,8 @@
     // Since a the finalized resource entry is cloned and added to the resource table under the
     // staged resource id, remove the cloned resource entry from the table.
     if (!table_->RemoveResource(resource_name, staged_id)) {
-      diag_->Error(DiagMessage(source_) << "failed to find resource entry for staged "
-                                        << " resource ID " << staged_id);
-      return false;
+      // If we haven't seen this resource yet let's add a record to skip it when parsing.
+      staged_entries_to_remove_.insert({resource_name, staged_id});
     }
   }
   return true;
diff --git a/tools/aapt2/format/binary/BinaryResourceParser.h b/tools/aapt2/format/binary/BinaryResourceParser.h
index cd71d16..1c83166 100644
--- a/tools/aapt2/format/binary/BinaryResourceParser.h
+++ b/tools/aapt2/format/binary/BinaryResourceParser.h
@@ -119,6 +119,10 @@
 
   // A mapping of resource ID to type spec flags.
   std::unordered_map<ResourceId, uint32_t> entry_type_spec_flags_;
+
+  // A collection of staged resources that got finalized already and we're supposed to prune -
+  // but the original staged resource record hasn't been parsed yet.
+  std::set<std::pair<ResourceName, ResourceId>> staged_entries_to_remove_;
 };
 
 }  // namespace aapt
diff --git a/tools/finalize_res/finalize_res.py b/tools/finalize_res/finalize_res.py
index aaf0187..724443c 100755
--- a/tools/finalize_res/finalize_res.py
+++ b/tools/finalize_res/finalize_res.py
@@ -17,6 +17,7 @@
 
 """
 Finalize resource values in <staging-public-group> tags
+and convert those to <staging-public-group-final>
 
 Usage: finalize_res.py core/res/res/values/public.xml public_finalized.xml
 """
@@ -24,18 +25,40 @@
 import re, sys, codecs
 
 def finalize_item(raw):
-    global _type, _id
-    _id += 1
-    return '<public type="%s" name="%s" id="%s" />' % (_type, raw.group(1), '0x{0:0{1}x}'.format(_id-1,8))
+    global _type_ids, _type
+    id = _type_ids[_type]
+    _type_ids[_type] += 1
+    name = raw.group(1)
+    val = '<public type="%s" name="%s" id="%s" />' % (_type, name, '0x{0:0{1}x}'.format(id,8))
+    if re.match(r'_*removed.+', name):
+        val = '<!-- ' + val.replace('<public', '< public') + ' -->'
+    return val
 
 def finalize_group(raw):
-    global _type, _id
+    global _type_ids, _type
     _type = raw.group(1)
-    _id = int(raw.group(2), 16)
-    return re.sub(r'<public name="(.+?)" */>', finalize_item, raw.group(3))
+    id = int(raw.group(2), 16)
+    _type_ids[_type] = _type_ids.get(_type, id)
+    (res, count) = re.subn(r' {0,2}<public name="(.+?)" */>', finalize_item, raw.group(3))
+    if count > 0:
+        res = raw.group(0).replace("staging-public-group", "staging-public-group-final") + '\n' + res
+    return res
+
+def collect_ids(raw):
+    global _type_ids
+    for m in re.finditer(r'<public type="(.+?)" name=".+?" id="(.+?)" />', raw):
+        type = m.group(1)
+        id = int(m.group(2), 16)
+        _type_ids[type] = max(id + 1, _type_ids.get(type, 0))
 
 with open(sys.argv[1]) as f:
+    global _type_ids, _type
+    _type_ids = {}
     raw = f.read()
+    collect_ids(raw)
     raw = re.sub(r'<staging-public-group type="(.+?)" first-id="(.+?)">(.+?)</staging-public-group>', finalize_group, raw, flags=re.DOTALL)
+    raw = re.sub(r' *\n', '\n', raw)
+    raw = re.sub(r'\n{3,}', '\n\n', raw)
     with open(sys.argv[2], "w") as f:
         f.write(raw)
+