Merge "Fix the transition from Split to PiP" into sc-v2-dev
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 8062832..7e38287 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -518,7 +518,9 @@
     public static final int GLOBAL_ACTION_POWER_DIALOG = 6;
 
     /**
-     * Action to toggle docking the current app's window
+     * Action to toggle docking the current app's window.
+     * <p>
+     * <strong>Note:</strong>  It is effective only if it appears in {@link #getSystemActions()}.
      */
     public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7;
 
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index 45df0d9..76e392d 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -321,7 +321,8 @@
 
     @UnsupportedAppUsage
     private ContextImpl mSystemContext;
-    private final SparseArray<ContextImpl> mDisplaySystemUiContexts = new SparseArray<>();
+    @GuardedBy("this")
+    private SparseArray<ContextImpl> mDisplaySystemUiContexts;
 
     @UnsupportedAppUsage
     static volatile IPackageManager sPackageManager;
@@ -2650,7 +2651,6 @@
         }
     }
 
-    @Override
     @NonNull
     public ContextImpl getSystemUiContext() {
         return getSystemUiContext(DEFAULT_DISPLAY);
@@ -2664,6 +2664,9 @@
     @NonNull
     public ContextImpl getSystemUiContext(int displayId) {
         synchronized (this) {
+            if (mDisplaySystemUiContexts == null) {
+                mDisplaySystemUiContexts = new SparseArray<>();
+            }
             ContextImpl systemUiContext = mDisplaySystemUiContexts.get(displayId);
             if (systemUiContext == null) {
                 systemUiContext = ContextImpl.createSystemUiContext(getSystemContext(), displayId);
@@ -2673,6 +2676,15 @@
         }
     }
 
+    @Nullable
+    @Override
+    public ContextImpl getSystemUiContextNoCreate() {
+        synchronized (this) {
+            if (mDisplaySystemUiContexts == null) return null;
+            return mDisplaySystemUiContexts.get(DEFAULT_DISPLAY);
+        }
+    }
+
     public void installSystemApplicationInfo(ApplicationInfo info, ClassLoader classLoader) {
         synchronized (this) {
             getSystemContext().installSystemApplicationInfo(info, classLoader);
diff --git a/core/java/android/app/ActivityThreadInternal.java b/core/java/android/app/ActivityThreadInternal.java
index bc698f6..b9ad5c3 100644
--- a/core/java/android/app/ActivityThreadInternal.java
+++ b/core/java/android/app/ActivityThreadInternal.java
@@ -28,7 +28,7 @@
 interface ActivityThreadInternal {
     ContextImpl getSystemContext();
 
-    ContextImpl getSystemUiContext();
+    ContextImpl getSystemUiContextNoCreate();
 
     boolean isInDensityCompatMode();
 
diff --git a/core/java/android/app/ConfigurationController.java b/core/java/android/app/ConfigurationController.java
index 8637e31..58f60a6 100644
--- a/core/java/android/app/ConfigurationController.java
+++ b/core/java/android/app/ConfigurationController.java
@@ -154,9 +154,12 @@
         int configDiff;
         boolean equivalent;
 
+        // Get theme outside of synchronization to avoid nested lock.
+        final Resources.Theme systemTheme = mActivityThread.getSystemContext().getTheme();
+        final ContextImpl systemUiContext = mActivityThread.getSystemUiContextNoCreate();
+        final Resources.Theme systemUiTheme =
+                systemUiContext != null ? systemUiContext.getTheme() : null;
         synchronized (mResourcesManager) {
-            final Resources.Theme systemTheme = mActivityThread.getSystemContext().getTheme();
-            final Resources.Theme systemUiTheme = mActivityThread.getSystemUiContext().getTheme();
             if (mPendingConfiguration != null) {
                 if (!mPendingConfiguration.isOtherSeqNewer(config)) {
                     config = mPendingConfiguration;
@@ -207,7 +210,8 @@
                 systemTheme.rebase();
             }
 
-            if ((systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
+            if (systemUiTheme != null
+                    && (systemUiTheme.getChangingConfigurations() & configDiff) != 0) {
                 systemUiTheme.rebase();
             }
         }
diff --git a/core/java/android/content/pm/ActivityInfo.java b/core/java/android/content/pm/ActivityInfo.java
index 8daf9f0..d1ef591 100644
--- a/core/java/android/content/pm/ActivityInfo.java
+++ b/core/java/android/content/pm/ActivityInfo.java
@@ -1367,18 +1367,18 @@
      * Returns if the activity should never be sandboxed to the activity window bounds.
      * @hide
      */
-    public boolean neverSandboxDisplayApis() {
+    public boolean neverSandboxDisplayApis(ConstrainDisplayApisConfig constrainDisplayApisConfig) {
         return isChangeEnabled(NEVER_SANDBOX_DISPLAY_APIS)
-                || ConstrainDisplayApisConfig.neverConstrainDisplayApis(applicationInfo);
+                || constrainDisplayApisConfig.getNeverConstrainDisplayApis(applicationInfo);
     }
 
     /**
      * Returns if the activity should always be sandboxed to the activity window bounds.
      * @hide
      */
-    public boolean alwaysSandboxDisplayApis() {
+    public boolean alwaysSandboxDisplayApis(ConstrainDisplayApisConfig constrainDisplayApisConfig) {
         return isChangeEnabled(ALWAYS_SANDBOX_DISPLAY_APIS)
-                || ConstrainDisplayApisConfig.alwaysConstrainDisplayApis(applicationInfo);
+                || constrainDisplayApisConfig.getAlwaysConstrainDisplayApis(applicationInfo);
     }
 
     /** @hide */
diff --git a/core/java/android/content/pm/ConstrainDisplayApisConfig.java b/core/java/android/content/pm/ConstrainDisplayApisConfig.java
index 11ba3d4..98b73aa 100644
--- a/core/java/android/content/pm/ConstrainDisplayApisConfig.java
+++ b/core/java/android/content/pm/ConstrainDisplayApisConfig.java
@@ -19,10 +19,15 @@
 import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
 
 import android.provider.DeviceConfig;
+import android.util.ArrayMap;
+import android.util.Pair;
 import android.util.Slog;
 
+import com.android.internal.os.BackgroundThread;
+
 import java.util.Arrays;
 import java.util.List;
+import java.util.Map;
 
 /**
  * Class for processing flags in the Device Config namespace 'constrain_display_apis'.
@@ -55,19 +60,45 @@
             "always_constrain_display_apis";
 
     /**
+     * Indicates that display APIs should never be constrained to the activity window bounds for all
+     * packages.
+     */
+    private boolean mNeverConstrainDisplayApisAllPackages;
+
+    /**
+     * Indicates that display APIs should never be constrained to the activity window bounds for
+     * a set of defined packages. Map keys are package names, and entries are a
+     * 'Pair(<min-version-code>, <max-version-code>)'.
+     */
+    private ArrayMap<String, Pair<Long, Long>> mNeverConstrainConfigMap;
+
+    /**
+     * Indicates that display APIs should always be constrained to the activity window bounds for
+     * a set of defined packages. Map keys are package names, and entries are a
+     * 'Pair(<min-version-code>, <max-version-code>)'.
+     */
+    private ArrayMap<String, Pair<Long, Long>> mAlwaysConstrainConfigMap;
+
+    public ConstrainDisplayApisConfig() {
+        updateCache();
+
+        DeviceConfig.addOnPropertiesChangedListener(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
+                BackgroundThread.getExecutor(), properties -> updateCache());
+    }
+
+    /**
      * Returns true if either the flag 'never_constrain_display_apis_all_packages' is true or the
      * flag 'never_constrain_display_apis' contains a package entry that matches the given {@code
      * applicationInfo}.
      *
      * @param applicationInfo Information about the application/package.
      */
-    public static boolean neverConstrainDisplayApis(ApplicationInfo applicationInfo) {
-        if (DeviceConfig.getBoolean(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
-                FLAG_NEVER_CONSTRAIN_DISPLAY_APIS_ALL_PACKAGES, /* defaultValue= */ false)) {
+    public boolean getNeverConstrainDisplayApis(ApplicationInfo applicationInfo) {
+        if (mNeverConstrainDisplayApisAllPackages) {
             return true;
         }
 
-        return flagHasMatchingPackageEntry(FLAG_NEVER_CONSTRAIN_DISPLAY_APIS, applicationInfo);
+        return flagHasMatchingPackageEntry(mNeverConstrainConfigMap, applicationInfo);
     }
 
     /**
@@ -76,73 +107,106 @@
      *
      * @param applicationInfo Information about the application/package.
      */
-    public static boolean alwaysConstrainDisplayApis(ApplicationInfo applicationInfo) {
-        return flagHasMatchingPackageEntry(FLAG_ALWAYS_CONSTRAIN_DISPLAY_APIS, applicationInfo);
+    public boolean getAlwaysConstrainDisplayApis(ApplicationInfo applicationInfo) {
+        return flagHasMatchingPackageEntry(mAlwaysConstrainConfigMap, applicationInfo);
+    }
+
+
+    /**
+     * Updates {@link #mNeverConstrainDisplayApisAllPackages}, {@link #mNeverConstrainConfigMap},
+     * and {@link #mAlwaysConstrainConfigMap} from the {@link DeviceConfig}.
+     */
+    private void updateCache() {
+        mNeverConstrainDisplayApisAllPackages = DeviceConfig.getBoolean(
+                NAMESPACE_CONSTRAIN_DISPLAY_APIS,
+                FLAG_NEVER_CONSTRAIN_DISPLAY_APIS_ALL_PACKAGES, /* defaultValue= */ false);
+
+        final String neverConstrainConfigStr = DeviceConfig.getString(
+                NAMESPACE_CONSTRAIN_DISPLAY_APIS,
+                FLAG_NEVER_CONSTRAIN_DISPLAY_APIS, /* defaultValue= */ "");
+        mNeverConstrainConfigMap = buildConfigMap(neverConstrainConfigStr);
+
+        final String alwaysConstrainConfigStr = DeviceConfig.getString(
+                NAMESPACE_CONSTRAIN_DISPLAY_APIS,
+                FLAG_ALWAYS_CONSTRAIN_DISPLAY_APIS, /* defaultValue= */ "");
+        mAlwaysConstrainConfigMap = buildConfigMap(alwaysConstrainConfigStr);
+    }
+
+    /**
+     * Processes the configuration string into a map of version codes, for the given
+     * configuration to be applied to the specified packages. If the given package
+     * entry string is invalid, then the map will not contain an entry for the package.
+     *
+     * @param configStr A configuration string expected to be in the format of a list of package
+     *                  entries separated by ','. A package entry expected to be in the format
+     *                  '<package-name>:<min-version-code>?:<max-version-code>?'.
+     * @return a map of configuration entries, where each key is a package name. Each value is
+     * a pair of version codes, in the format 'Pair(<min-version-code>, <max-version-code>)'.
+     */
+    private static ArrayMap<String, Pair<Long, Long>> buildConfigMap(String configStr) {
+        ArrayMap<String, Pair<Long, Long>> configMap = new ArrayMap<>();
+        // String#split returns a non-empty array given an empty string.
+        if (configStr.isEmpty()) {
+            return configMap;
+        }
+        for (String packageEntryString : configStr.split(",")) {
+            List<String> packageAndVersions = Arrays.asList(packageEntryString.split(":", 3));
+            if (packageAndVersions.size() != 3) {
+                Slog.w(TAG, "Invalid package entry in flag 'never/always_constrain_display_apis': "
+                        + packageEntryString);
+                // Skip this entry.
+                continue;
+            }
+            String packageName = packageAndVersions.get(0);
+            String minVersionCodeStr = packageAndVersions.get(1);
+            String maxVersionCodeStr = packageAndVersions.get(2);
+            try {
+                final long minVersion =
+                        minVersionCodeStr.isEmpty() ? Long.MIN_VALUE : Long.parseLong(
+                                minVersionCodeStr);
+                final long maxVersion =
+                        maxVersionCodeStr.isEmpty() ? Long.MAX_VALUE : Long.parseLong(
+                                maxVersionCodeStr);
+                Pair<Long, Long> minMaxVersionCodes = new Pair<>(minVersion, maxVersion);
+                configMap.put(packageName, minMaxVersionCodes);
+            } catch (NumberFormatException e) {
+                Slog.w(TAG, "Invalid APK version code in package entry: " + packageEntryString);
+                // Skip this entry.
+            }
+        }
+        return configMap;
     }
 
     /**
      * Returns true if the flag with the given {@code flagName} contains a package entry that
      * matches the given {@code applicationInfo}.
      *
+     * @param configMap the map representing the current configuration value to examine
      * @param applicationInfo Information about the application/package.
      */
-    private static boolean flagHasMatchingPackageEntry(String flagName,
+    private static boolean flagHasMatchingPackageEntry(Map<String, Pair<Long, Long>> configMap,
             ApplicationInfo applicationInfo) {
-        String configStr = DeviceConfig.getString(NAMESPACE_CONSTRAIN_DISPLAY_APIS,
-                flagName, /* defaultValue= */ "");
-
-        // String#split returns a non-empty array given an empty string.
-        if (configStr.isEmpty()) {
+        if (configMap.isEmpty()) {
             return false;
         }
-
-        for (String packageEntryString : configStr.split(",")) {
-            if (matchesApplicationInfo(packageEntryString, applicationInfo)) {
-                return true;
-            }
+        if (!configMap.containsKey(applicationInfo.packageName)) {
+            return false;
         }
-
-        return false;
+        return matchesApplicationInfo(configMap.get(applicationInfo.packageName), applicationInfo);
     }
 
     /**
-     * Parses the given {@code packageEntryString} and returns true if {@code
-     * applicationInfo.packageName} matches the package name in the config and {@code
-     * applicationInfo.longVersionCode} is within the version range in the config.
+     * Parses the given {@code minMaxVersionCodes} and returns true if {@code
+     * applicationInfo.longVersionCode} is within the version range in the pair.
+     * Returns false otherwise.
      *
-     * <p>Logs a warning and returns false in case the given {@code packageEntryString} is invalid.
-     *
-     * @param packageEntryStr A package entry expected to be in the format
-     *                        '<package-name>:<min-version-code>?:<max-version-code>?'.
+     * @param minMaxVersionCodes A pair expected to be in the format
+     *                        'Pair(<min-version-code>, <max-version-code>)'.
      * @param applicationInfo Information about the application/package.
      */
-    private static boolean matchesApplicationInfo(String packageEntryStr,
+    private static boolean matchesApplicationInfo(Pair<Long, Long> minMaxVersionCodes,
             ApplicationInfo applicationInfo) {
-        List<String> packageAndVersions = Arrays.asList(packageEntryStr.split(":", 3));
-        if (packageAndVersions.size() != 3) {
-            Slog.w(TAG, "Invalid package entry in flag 'never_constrain_display_apis': "
-                    + packageEntryStr);
-            return false;
-        }
-        String packageName = packageAndVersions.get(0);
-        String minVersionCodeStr = packageAndVersions.get(1);
-        String maxVersionCodeStr = packageAndVersions.get(2);
-
-        if (!packageName.equals(applicationInfo.packageName)) {
-            return false;
-        }
-        long version = applicationInfo.longVersionCode;
-        try {
-            if (!minVersionCodeStr.isEmpty() && version < Long.parseLong(minVersionCodeStr)) {
-                return false;
-            }
-            if (!maxVersionCodeStr.isEmpty() && version > Long.parseLong(maxVersionCodeStr)) {
-                return false;
-            }
-        } catch (NumberFormatException e) {
-            Slog.w(TAG, "Invalid APK version code in package entry: " + packageEntryStr);
-            return false;
-        }
-        return true;
+        return applicationInfo.longVersionCode >= minMaxVersionCodes.first
+                && applicationInfo.longVersionCode <= minMaxVersionCodes.second;
     }
 }
diff --git a/core/java/android/widget/RemoteViews.java b/core/java/android/widget/RemoteViews.java
index 3d4d9ec..dfd853a 100644
--- a/core/java/android/widget/RemoteViews.java
+++ b/core/java/android/widget/RemoteViews.java
@@ -3696,18 +3696,21 @@
     }
 
     private void initializeFrom(@NonNull RemoteViews src, @Nullable RemoteViews hierarchyRoot) {
+        if (hierarchyRoot == null) {
+            mBitmapCache = src.mBitmapCache;
+            mApplicationInfoCache = src.mApplicationInfoCache;
+        } else {
+            mBitmapCache = hierarchyRoot.mBitmapCache;
+            mApplicationInfoCache = hierarchyRoot.mApplicationInfoCache;
+        }
         if (hierarchyRoot == null || src.mIsRoot) {
             // If there's no provided root, or if src was itself a root, then this RemoteViews is
             // the root of the new hierarchy.
             mIsRoot = true;
-            mBitmapCache = new BitmapCache();
-            mApplicationInfoCache = new ApplicationInfoCache();
             hierarchyRoot = this;
         } else {
             // Otherwise, we're a descendant in the hierarchy.
             mIsRoot = false;
-            mBitmapCache = hierarchyRoot.mBitmapCache;
-            mApplicationInfoCache = hierarchyRoot.mApplicationInfoCache;
         }
         mApplication = src.mApplication;
         mLayoutId = src.mLayoutId;
diff --git a/core/proto/android/server/windowmanagerservice.proto b/core/proto/android/server/windowmanagerservice.proto
index c750ead..6faa046 100644
--- a/core/proto/android/server/windowmanagerservice.proto
+++ b/core/proto/android/server/windowmanagerservice.proto
@@ -366,6 +366,7 @@
     optional bool pip_auto_enter_enabled = 31;
     optional bool in_size_compat_mode = 32;
     optional float min_aspect_ratio = 33;
+    optional bool provides_max_bounds = 34;
 }
 
 /* represents WindowToken */
diff --git a/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java b/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
index 0456029..98485c0 100644
--- a/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
+++ b/core/tests/coretests/src/android/content/pm/ConstrainDisplayApisConfigTest.java
@@ -18,8 +18,7 @@
 
 import static android.provider.DeviceConfig.NAMESPACE_CONSTRAIN_DISPLAY_APIS;
 
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.assertEquals;
 
 import android.annotation.Nullable;
 import android.platform.test.annotations.Presubmit;
@@ -146,24 +145,17 @@
 
     private static void testNeverConstrainDisplayApis(String packageName, long version,
             boolean expected) {
-        boolean result = ConstrainDisplayApisConfig.neverConstrainDisplayApis(
-                buildApplicationInfo(packageName, version));
-        if (expected) {
-            assertTrue(result);
-        } else {
-            assertFalse(result);
-        }
+        ConstrainDisplayApisConfig config = new ConstrainDisplayApisConfig();
+        assertEquals(expected,
+                config.getNeverConstrainDisplayApis(buildApplicationInfo(packageName, version)));
     }
 
     private static void testAlwaysConstrainDisplayApis(String packageName, long version,
             boolean expected) {
-        boolean result = ConstrainDisplayApisConfig.alwaysConstrainDisplayApis(
-                buildApplicationInfo(packageName, version));
-        if (expected) {
-            assertTrue(result);
-        } else {
-            assertFalse(result);
-        }
+        ConstrainDisplayApisConfig config = new ConstrainDisplayApisConfig();
+
+        assertEquals(expected,
+                config.getAlwaysConstrainDisplayApis(buildApplicationInfo(packageName, version)));
     }
 
     private static ApplicationInfo buildApplicationInfo(String packageName, long version) {
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
index 8467cc5..92a3598 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/phone/PipDismissTargetHandler.java
@@ -122,7 +122,7 @@
 
         if (mTargetViewContainer != null) {
             // init can be called multiple times, remove the old one from view hierarchy first.
-            mWindowManager.removeViewImmediate(mTargetViewContainer);
+            cleanUpDismissTarget();
         }
 
         mTargetView = new DismissCircleView(mContext);
diff --git a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
index 36c2bda..7f17d26 100644
--- a/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
+++ b/packages/SettingsLib/ActivityEmbedding/src/com/android/settingslib/activityembedding/ActivityEmbeddingUtils.java
@@ -18,7 +18,6 @@
 
 import android.content.Context;
 import android.content.Intent;
-import android.content.pm.ResolveInfo;
 
 import com.android.settingslib.utils.BuildCompatUtils;
 
@@ -37,11 +36,10 @@
         if (BuildCompatUtils.isAtLeastS()) {
             final Intent intent = new Intent(ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY);
             intent.setPackage(PACKAGE_NAME_SETTINGS);
-            final ResolveInfo resolveInfo =
-                    context.getPackageManager().resolveActivity(intent, 0 /* flags */);
-            return resolveInfo != null
-                    && resolveInfo.activityInfo != null
-                    && resolveInfo.activityInfo.enabled;
+            final boolean isEmbeddingActivityEnabled =
+                    intent.resolveActivity(context.getPackageManager()) != null;
+
+            return isEmbeddingActivityEnabled;
         }
         return false;
     }
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
index 8b17be1..dee6894 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/EnableZenModeDialog.java
@@ -85,6 +85,7 @@
     @VisibleForTesting
     protected Context mContext;
     private final int mThemeResId;
+    private final boolean mCancelIsNeutral;
     @VisibleForTesting
     protected TextView mZenAlarmWarning;
     @VisibleForTesting
@@ -101,8 +102,13 @@
     }
 
     public EnableZenModeDialog(Context context, int themeResId) {
+        this(context, themeResId, false /* cancelIsNeutral */);
+    }
+
+    public EnableZenModeDialog(Context context, int themeResId, boolean cancelIsNeutral) {
         mContext = context;
         mThemeResId = themeResId;
+        mCancelIsNeutral = cancelIsNeutral;
     }
 
     public AlertDialog createDialog() {
@@ -115,7 +121,6 @@
 
         final AlertDialog.Builder builder = new AlertDialog.Builder(mContext, mThemeResId)
                 .setTitle(R.string.zen_mode_settings_turn_on_dialog_title)
-                .setNegativeButton(R.string.cancel, null)
                 .setPositiveButton(R.string.zen_mode_enable_dialog_turn_on,
                         new DialogInterface.OnClickListener() {
                             @Override
@@ -145,6 +150,12 @@
                             }
                         });
 
+        if (mCancelIsNeutral) {
+            builder.setNeutralButton(R.string.cancel, null);
+        } else {
+            builder.setNegativeButton(R.string.cancel, null);
+        }
+
         View contentView = getContentView();
         bindConditions(forever());
         builder.setView(contentView);
diff --git a/packages/SystemUI/res-keyguard/drawable/ic_unlocked_aod.xml b/packages/SystemUI/res-keyguard/drawable/ic_unlocked_aod.xml
new file mode 100644
index 0000000..230a256
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/ic_unlocked_aod.xml
@@ -0,0 +1,44 @@
+<?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
+  -->
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+        android:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46">
+    <group android:name="_R_G_L_2_G" android:translateX="23" android:translateY="32.125">
+        <path android:name="_R_G_L_2_G_D_0_P_0"
+              android:fillColor="#FF000000"
+              android:fillAlpha="1"
+              android:fillType="nonZero"
+              android:pathData=" M0 6.13 C0.97,6.13 1.75,5.34 1.75,4.38 C1.75,3.41 0.97,2.63 0,2.63 C-0.97,2.63 -1.75,3.41 -1.75,4.38 C-1.75,5.34 -0.97,6.13 0,6.13c " />
+    </group>
+    <group android:name="_R_G_L_1_G" android:translateX="23" android:translateY="32.125">
+        <path android:name="_R_G_L_1_G_D_0_P_0"
+              android:strokeColor="#FF000000"
+              android:strokeLineCap="round"
+              android:strokeLineJoin="round"
+              android:strokeWidth="1.5"
+              android:strokeAlpha="1"
+              android:pathData=" M7.88 -0.62 C7.88,-0.62 7.88,9.38 7.88,9.38 C7.88,10.48 6.98,11.38 5.88,11.38 C5.88,11.38 -5.87,11.38 -5.87,11.38 C-6.98,11.38 -7.87,10.48 -7.87,9.38 C-7.87,9.38 -7.87,-0.62 -7.87,-0.62 C-7.87,-1.73 -6.98,-2.62 -5.87,-2.62 C-5.87,-2.62 5.88,-2.62 5.88,-2.62 C6.98,-2.62 7.88,-1.73 7.88,-0.62c " />
+    </group>
+    <group android:name="_R_G_L_0_G" android:translateX="14" android:translateY="13.5">
+        <path android:name="_R_G_L_0_G_D_0_P_0"
+              android:strokeColor="#FF000000"
+              android:strokeLineCap="round"
+              android:strokeLineJoin="round"
+              android:strokeWidth="1.5"
+              android:strokeAlpha="1"
+              android:pathData=" M21.25 14.88 C21.25,14.88 21.25,10.74 21.25,10.74 C21.25,8.59 19.5,7.29 17.44,7.21 C15.24,7.13 13.5,8.47 13.5,10.62 C13.5,10.62 13.5,15.75 13.5,15.75 " />
+    </group>
+</vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
index c58e2e3..67a70bb 100644
--- a/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
+++ b/packages/SystemUI/res-keyguard/drawable/super_lock_icon.xml
@@ -50,6 +50,11 @@
         android:state_first="true"
         android:state_single="true"
         android:drawable="@drawable/ic_lock_aod" />
+    <item
+        android:id="@+id/unlocked_aod"
+        android:state_last="true"
+        android:state_single="true"
+        android:drawable="@drawable/ic_unlocked_aod" />
 
     <item
         android:id="@+id/no_icon"
@@ -79,4 +84,14 @@
         android:fromId="@id/locked"
         android:toId="@id/locked_aod"
         android:drawable="@drawable/lock_ls_to_aod" />
+
+    <transition
+        android:fromId="@id/unlocked_aod"
+        android:toId="@id/unlocked"
+        android:drawable="@drawable/unlocked_aod_to_ls" />
+
+    <transition
+        android:fromId="@id/unlocked"
+        android:toId="@id/unlocked_aod"
+        android:drawable="@drawable/unlocked_ls_to_aod" />
 </animated-selector>
diff --git a/packages/SystemUI/res-keyguard/drawable/unlocked_aod_to_ls.xml b/packages/SystemUI/res-keyguard/drawable/unlocked_aod_to_ls.xml
new file mode 100644
index 0000000..3b59ba8
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/unlocked_aod_to_ls.xml
@@ -0,0 +1,133 @@
+<?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.
+-->
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+                 xmlns:android="http://schemas.android.com/apk/res/android">
+    <aapt:attr name="android:drawable">
+        <vector android:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46">
+            <group android:name="_R_G">
+                <group android:name="_R_G_L_2_G" android:translateX="23" android:translateY="32.125">
+                    <path android:name="_R_G_L_2_G_D_0_P_0"
+                          android:fillColor="#FF000000"
+                          android:fillAlpha="1"
+                          android:fillType="nonZero"
+                          android:pathData=" M0 6.13 C0.97,6.13 1.75,5.34 1.75,4.38 C1.75,3.41 0.97,2.63 0,2.63 C-0.97,2.63 -1.75,3.41 -1.75,4.38 C-1.75,5.34 -0.97,6.13 0,6.13c " />
+                </group>
+                <group android:name="_R_G_L_1_G" android:translateX="23" android:translateY="32.125">
+                    <path android:name="_R_G_L_1_G_D_0_P_0"
+                          android:strokeColor="#FF000000"
+                          android:strokeLineCap="round"
+                          android:strokeLineJoin="round"
+                          android:strokeWidth="1.5"
+                          android:strokeAlpha="1"
+                          android:pathData=" M7.88 -0.62 C7.88,-0.62 7.88,9.38 7.88,9.38 C7.88,10.48 6.98,11.38 5.88,11.38 C5.88,11.38 -5.87,11.38 -5.87,11.38 C-6.98,11.38 -7.87,10.48 -7.87,9.38 C-7.87,9.38 -7.87,-0.62 -7.87,-0.62 C-7.87,-1.73 -6.98,-2.62 -5.87,-2.62 C-5.87,-2.62 5.88,-2.62 5.88,-2.62 C6.98,-2.62 7.88,-1.73 7.88,-0.62c " />
+                </group>
+                <group android:name="_R_G_L_0_G" android:translateX="14" android:translateY="13.5">
+                    <path android:name="_R_G_L_0_G_D_0_P_0"
+                          android:strokeColor="#FF000000"
+                          android:strokeLineCap="round"
+                          android:strokeLineJoin="round"
+                          android:strokeWidth="1.5"
+                          android:strokeAlpha="1"
+                          android:pathData=" M21.25 14.88 C21.25,14.88 21.25,10.74 21.25,10.74 C21.25,8.59 19.5,7.29 17.44,7.21 C15.24,7.13 13.5,8.47 13.5,10.62 C13.5,10.62 13.5,15.75 13.5,15.75 " />
+                </group>
+            </group>
+            <group android:name="time_group" />
+        </vector>
+    </aapt:attr>
+    <target android:name="_R_G_L_2_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData" android:duration="333" android:startOffset="0" android:valueFrom="M0 6.13 C0.97,6.13 1.75,5.34 1.75,4.38 C1.75,3.41 0.97,2.63 0,2.63 C-0.97,2.63 -1.75,3.41 -1.75,4.38 C-1.75,5.34 -0.97,6.13 0,6.13c " android:valueTo="M-0.09 8.63 C1.2,8.63 2.25,7.57 2.25,6.28 C2.25,4.99 1.2,3.94 -0.09,3.94 C-1.39,3.94 -2.44,4.99 -2.44,6.28 C-2.44,7.57 -1.39,8.63 -0.09,8.63c " android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.372,0 0.203,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_1_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="strokeWidth"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="1.5"
+                                android:valueTo="2"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.307,0 0.386,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_1_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="M7.88 -0.62 C7.88,-0.62 7.88,9.38 7.88,9.38 C7.88,10.48 6.98,11.38 5.88,11.38 C5.88,11.38 -5.87,11.38 -5.87,11.38 C-6.98,11.38 -7.87,10.48 -7.87,9.38 C-7.87,9.38 -7.87,-0.62 -7.87,-0.62 C-7.87,-1.73 -6.98,-2.62 -5.87,-2.62 C-5.87,-2.62 5.88,-2.62 5.88,-2.62 C6.98,-2.62 7.88,-1.73 7.88,-0.62c " android:valueTo="M11.25 -0.64 C11.25,-0.64 11.25,13.64 11.25,13.64 C11.25,15.22 9.97,16.5 8.39,16.5 C8.39,16.5 -8.39,16.5 -8.39,16.5 C-9.97,16.5 -11.25,15.22 -11.25,13.64 C-11.25,13.64 -11.25,-0.64 -11.25,-0.64 C-11.25,-2.22 -9.97,-3.5 -8.39,-3.5 C-8.39,-3.5 8.39,-3.5 8.39,-3.5 C9.97,-3.5 11.25,-2.22 11.25,-0.64c " android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.372,0 0.203,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="strokeWidth"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="1.5"
+                                android:valueTo="2.5"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.4,0 0.2,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="M21.25 14.88 C21.25,14.88 21.25,10.74 21.25,10.74 C21.25,8.59 19.5,7.29 17.44,7.21 C15.24,7.13 13.5,8.47 13.5,10.62 C13.5,10.62 13.5,15.75 13.5,15.75 " android:valueTo="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.347,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="time_group">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="translateX"
+                                android:duration="517"
+                                android:startOffset="0"
+                                android:valueFrom="0"
+                                android:valueTo="1"
+                                android:valueType="floatType" />
+            </set>
+        </aapt:attr>
+    </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res-keyguard/drawable/unlocked_ls_to_aod.xml b/packages/SystemUI/res-keyguard/drawable/unlocked_ls_to_aod.xml
new file mode 100644
index 0000000..1c6d0b5
--- /dev/null
+++ b/packages/SystemUI/res-keyguard/drawable/unlocked_ls_to_aod.xml
@@ -0,0 +1,136 @@
+<?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.
+-->
+<animated-vector xmlns:aapt="http://schemas.android.com/aapt"
+                 xmlns:android="http://schemas.android.com/apk/res/android">
+    <aapt:attr name="android:drawable">
+        <vector android:height="65dp" android:width="46dp" android:viewportHeight="65" android:viewportWidth="46">
+            <group android:name="_R_G">
+                <group android:name="_R_G_L_2_G" android:translateX="23" android:translateY="32.125">
+                    <path android:name="_R_G_L_2_G_D_0_P_0"
+                          android:fillColor="#FF000000"
+                          android:fillAlpha="1"
+                          android:fillType="nonZero"
+                          android:pathData=" M-0.09 8.63 C1.2,8.63 2.25,7.57 2.25,6.28 C2.25,4.99 1.2,3.94 -0.09,3.94 C-1.39,3.94 -2.44,4.99 -2.44,6.28 C-2.44,7.57 -1.39,8.63 -0.09,8.63c " />
+                </group>
+                <group android:name="_R_G_L_1_G" android:translateX="23" android:translateY="32.125">
+                    <path android:name="_R_G_L_1_G_D_0_P_0"
+                          android:strokeColor="#FF000000"
+                          android:strokeLineCap="round"
+                          android:strokeLineJoin="round"
+                          android:strokeWidth="2"
+                          android:strokeAlpha="1"
+                          android:pathData=" M11.25 -0.64 C11.25,-0.64 11.25,13.64 11.25,13.64 C11.25,15.22 9.97,16.5 8.39,16.5 C8.39,16.5 -8.39,16.5 -8.39,16.5 C-9.97,16.5 -11.25,15.22 -11.25,13.64 C-11.25,13.64 -11.25,-0.64 -11.25,-0.64 C-11.25,-2.22 -9.97,-3.5 -8.39,-3.5 C-8.39,-3.5 8.39,-3.5 8.39,-3.5 C9.97,-3.5 11.25,-2.22 11.25,-0.64c " />
+                </group>
+                <group android:name="_R_G_L_0_G" android:translateX="14" android:translateY="13.5">
+                    <path android:name="_R_G_L_0_G_D_0_P_0"
+                          android:strokeColor="#FF000000"
+                          android:strokeLineCap="round"
+                          android:strokeLineJoin="round"
+                          android:strokeWidth="2.5"
+                          android:strokeAlpha="1"
+                          android:pathData=" M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " />
+                </group>
+            </group>
+            <group android:name="time_group" />
+        </vector>
+    </aapt:attr>
+    <target android:name="_R_G_L_2_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="M-0.09 8.63 C1.2,8.63 2.25,7.57 2.25,6.28 C2.25,4.99 1.2,3.94 -0.09,3.94 C-1.39,3.94 -2.44,4.99 -2.44,6.28 C-2.44,7.57 -1.39,8.63 -0.09,8.63c " android:valueTo="M0 6.13 C0.97,6.13 1.75,5.34 1.75,4.38 C1.75,3.41 0.97,2.63 0,2.63 C-0.97,2.63 -1.75,3.41 -1.75,4.38 C-1.75,5.34 -0.97,6.13 0,6.13c " android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.347,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_1_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="strokeWidth"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="2"
+                                android:valueTo="1.5"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.516,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_1_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="M11.25 -0.64 C11.25,-0.64 11.25,13.64 11.25,13.64 C11.25,15.22 9.97,16.5 8.39,16.5 C8.39,16.5 -8.39,16.5 -8.39,16.5 C-9.97,16.5 -11.25,15.22 -11.25,13.64 C-11.25,13.64 -11.25,-0.64 -11.25,-0.64 C-11.25,-2.22 -9.97,-3.5 -8.39,-3.5 C-8.39,-3.5 8.39,-3.5 8.39,-3.5 C9.97,-3.5 11.25,-2.22 11.25,-0.64c " android:valueTo="M7.88 -0.62 C7.88,-0.62 7.88,9.38 7.88,9.38 C7.88,10.48 6.98,11.38 5.88,11.38 C5.88,11.38 -5.87,11.38 -5.87,11.38 C-6.98,11.38 -7.87,10.48 -7.87,9.38 C-7.87,9.38 -7.87,-0.62 -7.87,-0.62 C-7.87,-1.73 -6.98,-2.62 -5.87,-2.62 C-5.87,-2.62 5.88,-2.62 5.88,-2.62 C6.98,-2.62 7.88,-1.73 7.88,-0.62c " android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.347,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="strokeWidth"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="2.5"
+                                android:valueTo="1.5"
+                                android:valueType="floatType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.516,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="_R_G_L_0_G_D_0_P_0">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="pathData"
+                                android:duration="333"
+                                android:startOffset="0"
+                                android:valueFrom="M27.19 14.81 C27.19,14.81 27.19,8.3 27.19,8.3 C27.19,4.92 24.44,2.88 21.19,2.75 C17.74,2.62 15,4.74 15,8.11 C15,8.11 15,15 15,15 " android:valueTo="M21.25 14.88 C21.25,14.88 21.25,10.74 21.25,10.74 C21.25,8.59 19.5,7.29 17.44,7.21 C15.24,7.13 13.5,8.47 13.5,10.62 C13.5,10.62 13.5,15.75 13.5,15.75 " android:valueType="pathType">
+                    <aapt:attr name="android:interpolator">
+                        <pathInterpolator android:pathData="M 0.0,0.0 c0.333,0 0.347,1 1.0,1.0" />
+                    </aapt:attr>
+                </objectAnimator>
+            </set>
+        </aapt:attr>
+    </target>
+    <target android:name="time_group">
+        <aapt:attr name="android:animation">
+            <set android:ordering="together">
+                <objectAnimator android:propertyName="translateX"
+                                android:duration="517"
+                                android:startOffset="0"
+                                android:valueFrom="0"
+                                android:valueTo="1"
+                                android:valueType="floatType" />
+            </set>
+        </aapt:attr>
+    </target>
+</animated-vector>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/internet_dialog_footer_background.xml b/packages/SystemUI/res/drawable/internet_dialog_footer_background.xml
deleted file mode 100644
index 50267fd..0000000
--- a/packages/SystemUI/res/drawable/internet_dialog_footer_background.xml
+++ /dev/null
@@ -1,30 +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
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-       android:shape="rectangle">
-    <stroke
-        android:color="?androidprv:attr/colorAccentPrimaryVariant"
-        android:width="1dp"/>
-    <corners android:radius="20dp"/>
-    <padding
-        android:left="8dp"
-        android:right="8dp"
-        android:top="4dp"
-        android:bottom="4dp" />
-    <solid android:color="@android:color/transparent" />
-</shape>
\ No newline at end of file
diff --git a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
index 665b456..a47299d 100644
--- a/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
+++ b/packages/SystemUI/res/drawable/qs_dialog_btn_outline.xml
@@ -29,7 +29,7 @@
             <shape android:shape="rectangle">
                 <corners android:radius="?android:attr/buttonCornerRadius"/>
                 <solid android:color="@android:color/transparent"/>
-                <stroke android:color="?androidprv:attr/colorAccentPrimary"
+                <stroke android:color="?androidprv:attr/colorAccentPrimaryVariant"
                         android:width="1dp"
                 />
                 <padding android:left="@dimen/dialog_button_horizontal_padding"
diff --git a/packages/SystemUI/res/drawable/screenrecord_button_background_outline.xml b/packages/SystemUI/res/drawable/screenrecord_button_background_outline.xml
deleted file mode 100644
index 59a31e8..0000000
--- a/packages/SystemUI/res/drawable/screenrecord_button_background_outline.xml
+++ /dev/null
@@ -1,30 +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
-  -->
-<shape xmlns:android="http://schemas.android.com/apk/res/android"
-       xmlns:androidprv="http://schemas.android.com/apk/prv/res/android"
-       android:shape="rectangle">
-    <stroke
-        android:color="?androidprv:attr/colorAccentPrimary"
-        android:width="1dp"/>
-    <corners android:radius="24dp"/>
-    <padding
-        android:left="16dp"
-        android:right="16dp"
-        android:top="8dp"
-        android:bottom="8dp" />
-    <solid android:color="@android:color/transparent" />
-</shape>
diff --git a/packages/SystemUI/res/layout/auth_credential_password_view.xml b/packages/SystemUI/res/layout/auth_credential_password_view.xml
index 46cbc25..1e0ce00 100644
--- a/packages/SystemUI/res/layout/auth_credential_password_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_password_view.xml
@@ -18,71 +18,64 @@
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:elevation="@dimen/biometric_dialog_elevation"
-    android:orientation="vertical">
+    android:orientation="vertical"
+    android:gravity="center_horizontal"
+    android:elevation="@dimen/biometric_dialog_elevation">
 
-    <RelativeLayout
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:id="@+id/title"
         android:layout_width="match_parent"
-        android:layout_height="match_parent">
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Title"/>
 
-        <LinearLayout
-            android:id="@+id/auth_credential_header"
-            style="@style/AuthCredentialHeaderStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentTop="true">
+    <TextView
+        android:id="@+id/subtitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Subtitle"/>
 
-            <ImageView
-                android:id="@+id/icon"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:contentDescription="@null" />
+    <TextView
+        android:id="@+id/description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Description"/>
 
-            <TextView
-                android:id="@+id/title"
-                style="@style/TextAppearance.AuthCredential.Title"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
 
-            <TextView
-                android:id="@+id/subtitle"
-                style="@style/TextAppearance.AuthCredential.Subtitle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
+    <ImeAwareEditText
+        android:id="@+id/lockPassword"
+        android:layout_width="208dp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:minHeight="48dp"
+        android:gravity="center"
+        android:inputType="textPassword"
+        android:maxLength="500"
+        android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
+        style="@style/TextAppearance.AuthCredential.PasswordEntry"/>
 
-            <TextView
-                android:id="@+id/description"
-                style="@style/TextAppearance.AuthCredential.Description"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
+    <TextView
+        android:id="@+id/error"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Error"/>
 
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:gravity="center"
-            android:orientation="vertical"
-            android:layout_alignParentBottom="true">
-
-            <ImeAwareEditText
-                android:id="@+id/lockPassword"
-                style="@style/TextAppearance.AuthCredential.PasswordEntry"
-                android:layout_width="208dp"
-                android:layout_height="wrap_content"
-                android:layout_gravity="center"
-                android:imeOptions="actionNext|flagNoFullscreen|flagForceAscii"
-                android:inputType="textPassword"
-                android:minHeight="48dp" />
-
-            <TextView
-                android:id="@+id/error"
-                style="@style/TextAppearance.AuthCredential.Error"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
-
-        </LinearLayout>
-
-    </RelativeLayout>
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="5"/>
 
 </com.android.systemui.biometrics.AuthCredentialPasswordView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
index 470298e..4939ea2 100644
--- a/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
+++ b/packages/SystemUI/res/layout/auth_credential_pattern_view.xml
@@ -22,81 +22,76 @@
     android:gravity="center_horizontal"
     android:elevation="@dimen/biometric_dialog_elevation">
 
-    <RelativeLayout
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
+
+    <ImageView
+        android:id="@+id/icon"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"/>
+
+    <TextView
+        android:id="@+id/title"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:orientation="vertical">
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Title"/>
 
-        <LinearLayout
-            android:id="@+id/auth_credential_header"
-            style="@style/AuthCredentialHeaderStyle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content">
+    <TextView
+        android:id="@+id/subtitle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Subtitle"/>
 
-            <ImageView
-                android:id="@+id/icon"
-                android:layout_width="48dp"
-                android:layout_height="48dp"
-                android:contentDescription="@null" />
+    <TextView
+        android:id="@+id/description"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        style="@style/TextAppearance.AuthCredential.Description"/>
 
-            <TextView
-                android:id="@+id/title"
-                style="@style/TextAppearance.AuthCredential.Title"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
 
-            <TextView
-                android:id="@+id/subtitle"
-                style="@style/TextAppearance.AuthCredential.Subtitle"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:gravity="center"
+        android:paddingLeft="0dp"
+        android:paddingRight="0dp"
+        android:paddingTop="0dp"
+        android:paddingBottom="16dp"
+        android:clipToPadding="false">
 
-            <TextView
-                android:id="@+id/description"
-                style="@style/TextAppearance.AuthCredential.Description"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content" />
-        </LinearLayout>
+        <FrameLayout
+            android:layout_width="wrap_content"
+            android:layout_height="0dp"
+            android:layout_weight="1"
+            style="@style/LockPatternContainerStyle">
 
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_below="@id/auth_credential_header"
-            android:gravity="center"
-            android:orientation="vertical"
-            android:paddingBottom="16dp"
-            android:paddingTop="60dp">
-
-            <FrameLayout
-                style="@style/LockPatternContainerStyle"
-                android:layout_width="wrap_content"
-                android:layout_height="0dp"
-                android:layout_weight="1">
-
-                <com.android.internal.widget.LockPatternView
-                    android:id="@+id/lockPattern"
-                    style="@style/LockPatternStyle"
-                    android:layout_width="match_parent"
-                    android:layout_height="match_parent"
-                    android:layout_gravity="center" />
-
-            </FrameLayout>
-
-        </LinearLayout>
-
-        <LinearLayout
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_alignParentBottom="true">
-
-            <TextView
-                android:id="@+id/error"
-                style="@style/TextAppearance.AuthCredential.Error"
+            <com.android.internal.widget.LockPatternView
+                android:id="@+id/lockPattern"
                 android:layout_width="match_parent"
-                android:layout_height="wrap_content" />
+                android:layout_height="match_parent"
+                android:layout_gravity="center"
+                style="@style/LockPatternStyleBiometricPrompt"/>
 
-        </LinearLayout>
+        </FrameLayout>
 
-    </RelativeLayout>
+        <TextView
+            android:id="@+id/error"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            style="@style/TextAppearance.AuthCredential.Error"/>
+
+    </LinearLayout>
+
+    <Space
+        android:layout_width="0dp"
+        android:layout_height="0dp"
+        android:layout_weight="1"/>
 
 </com.android.systemui.biometrics.AuthCredentialPatternView>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
index c575855..275e0a5 100644
--- a/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
+++ b/packages/SystemUI/res/layout/internet_connectivity_dialog.xml
@@ -37,7 +37,7 @@
             android:ellipsize="end"
             android:gravity="center_vertical|center_horizontal"
             android:layout_width="wrap_content"
-            android:layout_height="32dp"
+            android:layout_height="wrap_content"
             android:textAppearance="@style/TextAppearance.InternetDialog"
             android:textSize="24sp"/>
 
@@ -45,7 +45,7 @@
             android:id="@+id/internet_dialog_subtitle"
             android:gravity="center_vertical|center_horizontal"
             android:layout_width="wrap_content"
-            android:layout_height="20dp"
+            android:layout_height="wrap_content"
             android:layout_marginTop="4dp"
             android:ellipsize="end"
             android:maxLines="1"
@@ -150,6 +150,7 @@
                         android:gravity="start|center_vertical">
                         <TextView
                             android:id="@+id/mobile_title"
+                            android:maxLines="1"
                             style="@style/InternetDialog.NetworkTitle"/>
                         <TextView
                             android:id="@+id/mobile_summary"
@@ -380,54 +381,44 @@
                 android:id="@+id/button_layout"
                 android:orientation="horizontal"
                 android:layout_width="match_parent"
-                android:layout_height="48dp"
-                android:layout_marginStart="24dp"
-                android:layout_marginEnd="24dp"
+                android:layout_height="wrap_content"
                 android:layout_marginTop="8dp"
-                android:layout_marginBottom="34dp"
+                android:layout_marginStart="@dimen/dialog_side_padding"
+                android:layout_marginEnd="@dimen/dialog_side_padding"
+                android:layout_marginBottom="@dimen/dialog_bottom_padding"
                 android:clickable="false"
                 android:focusable="false">
 
                 <FrameLayout
                     android:id="@+id/apm_layout"
                     android:layout_width="wrap_content"
-                    android:layout_height="48dp"
+                    android:layout_height="wrap_content"
                     android:clickable="true"
                     android:focusable="true"
                     android:layout_gravity="start|center_vertical"
                     android:orientation="vertical">
                     <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
                         android:text="@string/turn_off_airplane_mode"
                         android:ellipsize="end"
-                        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
-                        android:layout_width="wrap_content"
-                        android:layout_height="36dp"
-                        android:layout_gravity="start|center_vertical"
-                        android:textAppearance="@style/TextAppearance.InternetDialog"
-                        android:textSize="14sp"
-                        android:background="@drawable/internet_dialog_footer_background"
+                        style="@style/Widget.Dialog.Button.BorderButton"
                         android:clickable="false"/>
                 </FrameLayout>
 
                 <FrameLayout
                     android:id="@+id/done_layout"
                     android:layout_width="wrap_content"
-                    android:layout_height="48dp"
+                    android:layout_height="wrap_content"
                     android:layout_marginStart="16dp"
-                    android:clickable="true"
-                    android:focusable="true"
                     android:layout_gravity="end|center_vertical"
-                    android:orientation="vertical">
+                    android:clickable="true"
+                    android:focusable="true">
                     <Button
+                        android:layout_width="wrap_content"
+                        android:layout_height="wrap_content"
                         android:text="@string/inline_done_button"
-                        android:ellipsize="end"
-                        style="@*android:style/Widget.DeviceDefault.Button.Borderless.Colored"
-                        android:layout_width="67dp"
-                        android:layout_height="36dp"
-                        android:layout_gravity="end|center_vertical"
-                        android:textAppearance="@style/TextAppearance.InternetDialog"
-                        android:textSize="14sp"
-                        android:background="@drawable/internet_dialog_footer_background"
+                        style="@style/Widget.Dialog.Button"
                         android:clickable="false"/>
                 </FrameLayout>
             </FrameLayout>
diff --git a/packages/SystemUI/res/layout/media_output_dialog.xml b/packages/SystemUI/res/layout/media_output_dialog.xml
index 07fd1b0..3a186d2 100644
--- a/packages/SystemUI/res/layout/media_output_dialog.xml
+++ b/packages/SystemUI/res/layout/media_output_dialog.xml
@@ -89,17 +89,16 @@
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_marginTop="16dp"
-        android:layout_marginStart="24dp"
-        android:layout_marginBottom="24dp"
-        android:layout_marginEnd="24dp"
+        android:layout_marginStart="@dimen/dialog_side_padding"
+        android:layout_marginEnd="@dimen/dialog_side_padding"
+        android:layout_marginBottom="@dimen/dialog_bottom_padding"
         android:orientation="horizontal">
 
         <Button
             android:id="@+id/stop"
-            style="@style/MediaOutputRoundedOutlinedButton"
+            style="@style/Widget.Dialog.Button.BorderButton"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:minWidth="0dp"
             android:text="@string/keyboard_key_media_stop"
             android:visibility="gone"/>
 
@@ -110,10 +109,9 @@
 
         <Button
             android:id="@+id/done"
-            style="@style/MediaOutputRoundedOutlinedButton"
+            style="@style/Widget.Dialog.Button"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:minWidth="0dp"
             android:text="@string/inline_done_button"/>
     </LinearLayout>
 </LinearLayout>
\ No newline at end of file
diff --git a/packages/SystemUI/res/layout/screen_record_dialog.xml b/packages/SystemUI/res/layout/screen_record_dialog.xml
index 6c5ad50..6012b58 100644
--- a/packages/SystemUI/res/layout/screen_record_dialog.xml
+++ b/packages/SystemUI/res/layout/screen_record_dialog.xml
@@ -27,10 +27,10 @@
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
-            android:paddingStart="24dp"
-            android:paddingEnd="24dp"
-            android:paddingTop="26dp"
-            android:paddingBottom="30dp"
+            android:paddingStart="@dimen/dialog_side_padding"
+            android:paddingEnd="@dimen/dialog_side_padding"
+            android:paddingTop="@dimen/dialog_top_padding"
+            android:paddingBottom="@dimen/dialog_bottom_padding"
             android:orientation="vertical">
 
             <!-- Header -->
@@ -108,10 +108,7 @@
                     android:layout_weight="0"
                     android:layout_gravity="start"
                     android:text="@string/cancel"
-                    android:textColor="?android:textColorPrimary"
-                    android:background="@drawable/screenrecord_button_background_outline"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    android:textSize="14sp"/>
+                    style="@style/Widget.Dialog.Button.BorderButton" />
                 <Space
                     android:layout_width="0dp"
                     android:layout_height="match_parent"
@@ -123,10 +120,7 @@
                     android:layout_weight="0"
                     android:layout_gravity="end"
                     android:text="@string/screenrecord_start"
-                    android:textColor="@android:color/system_neutral1_900"
-                    android:background="@drawable/screenrecord_button_background_solid"
-                    android:textAppearance="?android:attr/textAppearanceMedium"
-                    android:textSize="14sp"/>
+                    style="@style/Widget.Dialog.Button" />
             </LinearLayout>
         </LinearLayout>
     </ScrollView>
diff --git a/packages/SystemUI/res/values/config.xml b/packages/SystemUI/res/values/config.xml
index 475f70f..e00b941 100644
--- a/packages/SystemUI/res/values/config.xml
+++ b/packages/SystemUI/res/values/config.xml
@@ -595,17 +595,6 @@
         280
     </integer>
 
-    <!-- Haptic feedback intensity for ticks used for the udfps dwell time -->
-    <item name="config_udfpsTickIntensity" translatable="false" format="float"
-          type="dimen">.5</item>
-
-    <!-- Haptic feedback delay between ticks used for udfps dwell time -->
-    <integer name="config_udfpsTickDelay" translatable="false">25</integer>
-
-    <!-- Haptic feedback tick type - if true, uses VibrationEffect.Composition.PRIMITIVE_LOW_TICK
-         else uses VibrationEffect.Composition.PRIMITIVE_TICK -->
-    <bool name="config_udfpsUseLowTick">true</bool>
-
     <!-- package name of a built-in camera app to use to restrict implicit intent resolution
          when the double-press power gesture is used. Ignored if empty. -->
     <string translatable="false" name="config_cameraGesturePackage"></string>
diff --git a/packages/SystemUI/res/values/styles.xml b/packages/SystemUI/res/values/styles.xml
index 0cfd8d6..051a30c 100644
--- a/packages/SystemUI/res/values/styles.xml
+++ b/packages/SystemUI/res/values/styles.xml
@@ -200,9 +200,9 @@
 
     <style name="TextAppearance.DeviceManagementDialog.Title" parent="@android:style/TextAppearance.DeviceDefault.DialogWindowTitle"/>
 
-    <style name="TextAppearance.AuthCredential"
-        parent="@android:style/TextAppearance.DeviceDefault">
+    <style name="TextAppearance.AuthCredential">
         <item name="android:accessibilityLiveRegion">polite</item>
+        <item name="android:gravity">center_horizontal</item>
         <item name="android:textAlignment">gravity</item>
         <item name="android:layout_gravity">top</item>
         <item name="android:textColor">?android:attr/textColorPrimary</item>
@@ -210,57 +210,44 @@
 
     <style name="TextAppearance.AuthCredential.Title">
         <item name="android:fontFamily">google-sans</item>
-        <item name="android:layout_marginTop">20dp</item>
-        <item name="android:textSize">36sp</item>
+        <item name="android:paddingTop">12dp</item>
+        <item name="android:paddingHorizontal">24dp</item>
+        <item name="android:textSize">24sp</item>
     </style>
 
     <style name="TextAppearance.AuthCredential.Subtitle">
         <item name="android:fontFamily">google-sans</item>
-        <item name="android:layout_marginTop">20dp</item>
-        <item name="android:textSize">18sp</item>
+        <item name="android:paddingTop">8dp</item>
+        <item name="android:paddingHorizontal">24dp</item>
+        <item name="android:textSize">16sp</item>
     </style>
 
     <style name="TextAppearance.AuthCredential.Description">
         <item name="android:fontFamily">google-sans</item>
-        <item name="android:layout_marginTop">20dp</item>
-        <item name="android:textSize">16sp</item>
+        <item name="android:paddingTop">8dp</item>
+        <item name="android:paddingHorizontal">24dp</item>
+        <item name="android:textSize">14sp</item>
     </style>
 
     <style name="TextAppearance.AuthCredential.Error">
         <item name="android:paddingTop">6dp</item>
-        <item name="android:paddingBottom">18dp</item>
         <item name="android:paddingHorizontal">24dp</item>
         <item name="android:textSize">14sp</item>
         <item name="android:textColor">?android:attr/colorError</item>
-        <item name="android:gravity">center</item>
     </style>
 
-    <style name="TextAppearance.AuthCredential.PasswordEntry">
+    <style name="TextAppearance.AuthCredential.PasswordEntry" parent="@android:style/TextAppearance.DeviceDefault">
         <item name="android:gravity">center</item>
         <item name="android:singleLine">true</item>
         <item name="android:textColor">?android:attr/colorForeground</item>
         <item name="android:textSize">24sp</item>
     </style>
 
-    <style name="AuthCredentialHeaderStyle">
-        <item name="android:paddingStart">48dp</item>
-        <item name="android:paddingEnd">24dp</item>
-        <item name="android:paddingTop">28dp</item>
-        <item name="android:paddingBottom">20dp</item>
-        <item name="android:orientation">vertical</item>
-        <item name="android:layout_gravity">top</item>
-    </style>
-
     <style name="DeviceManagementDialogTitle">
         <item name="android:gravity">center</item>
         <item name="android:textAppearance">@style/TextAppearance.DeviceManagementDialog.Title</item>
     </style>
 
-    <style name="AuthCredentialPasswordTheme" parent="@style/Theme.MaterialComponents.DayNight">
-        <item name="colorPrimary">?android:attr/colorPrimary</item>
-        <item name="colorPrimaryDark">?android:attr/colorPrimary</item>
-    </style>
-
     <style name="TextAppearance.DeviceManagementDialog.Content" parent="@*android:style/TextAppearance.DeviceDefault.Subhead"/>
 
     <style name="BaseBrightnessDialogContainer" parent="@style/Theme.SystemUI">
@@ -320,8 +307,9 @@
         <item name="android:maxWidth">420dp</item>
         <item name="android:minHeight">0dp</item>
         <item name="android:minWidth">0dp</item>
-        <item name="android:paddingHorizontal">60dp</item>
-        <item name="android:paddingBottom">40dp</item>
+        <item name="android:paddingBottom">0dp</item>
+        <item name="android:paddingHorizontal">44dp</item>
+        <item name="android:paddingTop">0dp</item>
     </style>
 
     <style name="LockPatternStyle">
@@ -462,10 +450,6 @@
         <item name="android:background">@drawable/btn_borderless_rect</item>
     </style>
 
-    <style name="MediaOutputRoundedOutlinedButton" parent="@android:style/Widget.Material.Button">
-        <item name="android:background">@drawable/media_output_dialog_button_background</item>
-    </style>
-
     <style name="TunerSettings" parent="@android:style/Theme.DeviceDefault.Settings">
         <item name="android:windowActionBar">false</item>
         <item name="preferenceTheme">@style/TunerPreferenceTheme</item>
@@ -893,13 +877,18 @@
         <item name="android:textAlignment">center</item>
     </style>
 
-    <style name="Widget.Dialog.Button" parent = "Theme.SystemUI.Dialog">
+
+    <style name="Widget" />
+    <style name="Widget.Dialog" />
+    <style name="Widget.Dialog.Button">
+        <item name="android:buttonCornerRadius">28dp</item>
         <item name="android:background">@drawable/qs_dialog_btn_filled</item>
         <item name="android:textColor">?androidprv:attr/textColorOnAccent</item>
         <item name="android:textSize">14sp</item>
         <item name="android:lineHeight">20sp</item>
         <item name="android:fontFamily">@*android:string/config_bodyFontFamilyMedium</item>
         <item name="android:stateListAnimator">@null</item>
+        <item name="android:minWidth">0dp</item>
     </style>
 
     <style name="Widget.Dialog.Button.BorderButton">
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index e267c5c..7ac3ca6 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -35,12 +35,10 @@
 import android.hardware.fingerprint.FingerprintSensorPropertiesInternal;
 import android.media.AudioAttributes;
 import android.os.Process;
-import android.os.VibrationEffect;
 import android.os.Vibrator;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.util.MathUtils;
-import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.VelocityTracker;
 import android.view.View;
@@ -68,8 +66,6 @@
 import com.android.systemui.util.ViewController;
 import com.android.systemui.util.concurrency.DelayableExecutor;
 
-import com.airbnb.lottie.LottieAnimationView;
-
 import java.io.FileDescriptor;
 import java.io.PrintWriter;
 import java.util.Objects;
@@ -104,10 +100,8 @@
     @NonNull private final AccessibilityManager mAccessibilityManager;
     @NonNull private final ConfigurationController mConfigurationController;
     @NonNull private final DelayableExecutor mExecutor;
-    @NonNull private final LayoutInflater mLayoutInflater;
     private boolean mUdfpsEnrolled;
 
-    @Nullable private LottieAnimationView mAodFp;
     @NonNull private final AnimatedStateListDrawable mIcon;
 
     @NonNull private CharSequence mUnlockedLabel;
@@ -119,7 +113,6 @@
     private VelocityTracker mVelocityTracker;
     // The ID of the pointer for which ACTION_DOWN has occurred. -1 means no pointer is active.
     private int mActivePointerId = -1;
-    private VibrationEffect mTick;
 
     private boolean mIsDozing;
     private boolean mIsBouncerShowing;
@@ -143,7 +136,7 @@
 
     // for udfps when strong auth is required or unlocked on AOD
     private boolean mShowAodLockIcon;
-    private boolean mShowAODFpIcon;
+    private boolean mShowAodUnlockedIcon;
     private final int mMaxBurnInOffsetX;
     private final int mMaxBurnInOffsetY;
     private float mInterpolatedDarkAmount;
@@ -166,8 +159,7 @@
             @NonNull @Main DelayableExecutor executor,
             @Nullable Vibrator vibrator,
             @Nullable AuthRippleController authRippleController,
-            @NonNull @Main Resources resources,
-            @NonNull LayoutInflater inflater
+            @NonNull @Main Resources resources
     ) {
         super(view);
         mStatusBarStateController = statusBarStateController;
@@ -181,7 +173,6 @@
         mExecutor = executor;
         mVibrator = vibrator;
         mAuthRippleController = authRippleController;
-        mLayoutInflater = inflater;
 
         mMaxBurnInOffsetX = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_x);
         mMaxBurnInOffsetY = resources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
@@ -263,11 +254,12 @@
         }
 
         boolean wasShowingUnlock = mShowUnlockIcon;
-        boolean wasShowingFpIcon = mUdfpsEnrolled && !mShowUnlockIcon && !mShowLockIcon;
+        boolean wasShowingFpIcon = mUdfpsEnrolled && !mShowUnlockIcon && !mShowLockIcon
+                && !mShowAodUnlockedIcon && !mShowAodLockIcon;
         mShowLockIcon = !mCanDismissLockScreen && !mUserUnlockedWithBiometric && isLockScreen()
                 && (!mUdfpsEnrolled || !mRunningFPS);
         mShowUnlockIcon = (mCanDismissLockScreen || mUserUnlockedWithBiometric) && isLockScreen();
-        mShowAODFpIcon = mIsDozing && mUdfpsEnrolled && !mRunningFPS && mCanDismissLockScreen;
+        mShowAodUnlockedIcon = mIsDozing && mUdfpsEnrolled && !mRunningFPS && mCanDismissLockScreen;
         mShowAodLockIcon = mIsDozing && mUdfpsEnrolled && !mRunningFPS && !mCanDismissLockScreen;
 
         final CharSequence prevContentDescription = mView.getContentDescription();
@@ -284,14 +276,9 @@
             mView.updateIcon(ICON_UNLOCK, false);
             mView.setContentDescription(mUnlockedLabel);
             mView.setVisibility(View.VISIBLE);
-        } else if (mShowAODFpIcon) {
-            // AOD fp icon is special cased as a lottie view (it updates for each burn-in offset),
-            // this state shows a transparent view
-            mView.setContentDescription(null);
-            mAodFp.setVisibility(View.VISIBLE);
-            mAodFp.setContentDescription(mCanDismissLockScreen ? mUnlockedLabel : mLockedLabel);
-
-            mView.updateIcon(ICON_FINGERPRINT, true); // this shows no icon
+        } else if (mShowAodUnlockedIcon) {
+            mView.updateIcon(ICON_UNLOCK, true);
+            mView.setContentDescription(mUnlockedLabel);
             mView.setVisibility(View.VISIBLE);
         } else if (mShowAodLockIcon) {
             if (wasShowingUnlock) {
@@ -307,11 +294,6 @@
             mView.setContentDescription(null);
         }
 
-        if (!mShowAODFpIcon && mAodFp != null) {
-            mAodFp.setVisibility(View.INVISIBLE);
-            mAodFp.setContentDescription(null);
-        }
-
         if (!Objects.equals(prevContentDescription, mView.getContentDescription())
                 && mView.getContentDescription() != null) {
             mView.announceForAccessibility(mView.getContentDescription());
@@ -399,7 +381,7 @@
         pw.println();
         pw.println(" mShowUnlockIcon: " + mShowUnlockIcon);
         pw.println(" mShowLockIcon: " + mShowLockIcon);
-        pw.println(" mShowAODFpIcon: " + mShowAODFpIcon);
+        pw.println(" mShowAodUnlockedIcon: " + mShowAodUnlockedIcon);
         pw.println("  mIsDozing: " + mIsDozing);
         pw.println("  mIsBouncerShowing: " + mIsBouncerShowing);
         pw.println("  mUserUnlockedWithBiometric: " + mUserUnlockedWithBiometric);
@@ -428,13 +410,6 @@
                         - mMaxBurnInOffsetY, mInterpolatedDarkAmount);
         float progress = MathUtils.lerp(0f, getBurnInProgressOffset(), mInterpolatedDarkAmount);
 
-        if (mAodFp != null) {
-            mAodFp.setTranslationX(offsetX);
-            mAodFp.setTranslationY(offsetY);
-            mAodFp.setProgress(progress);
-            mAodFp.setAlpha(255 * mInterpolatedDarkAmount);
-        }
-
         mView.setTranslationX(offsetX);
         mView.setTranslationY(offsetY);
     }
@@ -447,10 +422,6 @@
         mView.setUseBackground(mUdfpsSupported);
 
         mUdfpsEnrolled = mKeyguardUpdateMonitor.isUdfpsEnrolled();
-        if (!wasUdfpsEnrolled && mUdfpsEnrolled && mAodFp == null) {
-            mLayoutInflater.inflate(R.layout.udfps_aod_lock_icon, mView);
-            mAodFp = mView.findViewById(R.id.lock_udfps_aod_fp);
-        }
         if (wasUdfpsSupported != mUdfpsSupported || wasUdfpsEnrolled != mUdfpsEnrolled) {
             updateVisibility();
         }
@@ -597,15 +568,11 @@
             case MotionEvent.ACTION_DOWN:
             case MotionEvent.ACTION_HOVER_ENTER:
                 if (mVibrator != null && !mDownDetected) {
-                    if (mTick == null) {
-                        mTick = UdfpsController.lowTick(getContext(), true,
-                                LONG_PRESS_TIMEOUT);
-                    }
                     mVibrator.vibrate(
                             Process.myUid(),
                             getContext().getOpPackageName(),
-                            mTick,
-                            "lock-icon-tick",
+                            UdfpsController.EFFECT_CLICK,
+                            "lock-icon-down",
                             VIBRATION_SONIFICATION_ATTRIBUTES);
                 }
 
@@ -718,8 +685,7 @@
 
     private boolean inLockIconArea(MotionEvent event) {
         return mSensorTouchLocation.contains((int) event.getX(), (int) event.getY())
-                && (mView.getVisibility() == View.VISIBLE
-                || (mAodFp != null && mAodFp.getVisibility() == View.VISIBLE));
+                && mView.getVisibility() == View.VISIBLE;
     }
 
     private boolean isActionable() {
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java
index fb4616a..07aec69 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsAnimationViewController.java
@@ -23,6 +23,7 @@
 import com.android.systemui.Dumpable;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.util.ViewController;
@@ -44,6 +45,7 @@
         extends ViewController<T> implements Dumpable {
     @NonNull final StatusBarStateController mStatusBarStateController;
     @NonNull final PanelExpansionStateManager mPanelExpansionStateManager;
+    @NonNull final SystemUIDialogManager mDialogManager;
     @NonNull final DumpManager mDumpManger;
 
     boolean mNotificationShadeVisible;
@@ -52,10 +54,12 @@
             T view,
             @NonNull StatusBarStateController statusBarStateController,
             @NonNull PanelExpansionStateManager panelExpansionStateManager,
+            @NonNull SystemUIDialogManager dialogManager,
             @NonNull DumpManager dumpManager) {
         super(view);
         mStatusBarStateController = statusBarStateController;
         mPanelExpansionStateManager = panelExpansionStateManager;
+        mDialogManager = dialogManager;
         mDumpManger = dumpManager;
     }
 
@@ -64,12 +68,14 @@
     @Override
     protected void onViewAttached() {
         mPanelExpansionStateManager.addExpansionListener(mPanelExpansionListener);
+        mDialogManager.registerListener(mDialogListener);
         mDumpManger.registerDumpable(getDumpTag(), this);
     }
 
     @Override
     protected void onViewDetached() {
         mPanelExpansionStateManager.removeExpansionListener(mPanelExpansionListener);
+        mDialogManager.registerListener(mDialogListener);
         mDumpManger.unregisterDumpable(getDumpTag());
     }
 
@@ -95,7 +101,8 @@
      * authentication.
      */
     boolean shouldPauseAuth() {
-        return mNotificationShadeVisible;
+        return mNotificationShadeVisible
+                || mDialogManager.shouldHideAffordance();
     }
 
     /**
@@ -189,4 +196,7 @@
             updatePauseAuth();
         }
     };
+
+    private final SystemUIDialogManager.Listener mDialogListener =
+            (shouldHide) -> updatePauseAuth();
 }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.java
index 894b295..3732100 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsBpViewController.java
@@ -20,6 +20,7 @@
 
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 
 /**
@@ -30,8 +31,10 @@
             @NonNull UdfpsBpView view,
             @NonNull StatusBarStateController statusBarStateController,
             @NonNull PanelExpansionStateManager panelExpansionStateManager,
+            @NonNull SystemUIDialogManager systemUIDialogManager,
             @NonNull DumpManager dumpManager) {
-        super(view, statusBarStateController, panelExpansionStateManager, dumpManager);
+        super(view, statusBarStateController, panelExpansionStateManager,
+                systemUIDialogManager, dumpManager);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
index 9808045..3e9d6b0 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsController.java
@@ -47,7 +47,6 @@
 import android.os.Trace;
 import android.os.VibrationEffect;
 import android.os.Vibrator;
-import android.provider.Settings;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -71,6 +70,7 @@
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -119,6 +119,7 @@
     @NonNull private final KeyguardStateController mKeyguardStateController;
     @NonNull private final StatusBarKeyguardViewManager mKeyguardViewManager;
     @NonNull private final DumpManager mDumpManager;
+    @NonNull private final SystemUIDialogManager mDialogManager;
     @NonNull private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Nullable private final Vibrator mVibrator;
     @NonNull private final FalsingManager mFalsingManager;
@@ -165,9 +166,6 @@
     private boolean mAttemptedToDismissKeyguard;
     private Set<Callback> mCallbacks = new HashSet<>();
 
-    private static final int DEFAULT_TICK = VibrationEffect.Composition.PRIMITIVE_LOW_TICK;
-    private final VibrationEffect mTick;
-
     @VisibleForTesting
     public static final AudioAttributes VIBRATION_SONIFICATION_ATTRIBUTES =
             new AudioAttributes.Builder()
@@ -282,9 +280,6 @@
                     return;
                 }
                 mGoodCaptureReceived = true;
-                if (mVibrator != null) {
-                    mVibrator.cancel();
-                }
                 mView.stopIllumination();
                 if (mServerRequest != null) {
                     mServerRequest.onAcquiredGood();
@@ -559,7 +554,8 @@
             @Main Handler mainHandler,
             @NonNull ConfigurationController configurationController,
             @NonNull SystemClock systemClock,
-            @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController) {
+            @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+            @NonNull SystemUIDialogManager dialogManager) {
         mContext = context;
         mExecution = execution;
         mVibrator = vibrator;
@@ -574,6 +570,7 @@
         mKeyguardStateController = keyguardStateController;
         mKeyguardViewManager = statusBarKeyguardViewManager;
         mDumpManager = dumpManager;
+        mDialogManager = dialogManager;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mFalsingManager = falsingManager;
         mPowerManager = powerManager;
@@ -586,7 +583,6 @@
         mConfigurationController = configurationController;
         mSystemClock = systemClock;
         mUnlockedScreenOffAnimationController = unlockedScreenOffAnimationController;
-        mTick = lowTick(context, false /* useShortRampup */, DEFAULT_VIBRATION_DURATION);
 
         mSensorProps = findFirstUdfps();
         // At least one UDFPS sensor exists
@@ -622,47 +618,6 @@
     }
 
     /**
-     * Returns the continuous low tick effect that starts playing on the udfps finger-down event.
-     */
-    public static VibrationEffect lowTick(
-            Context context,
-            boolean useShortRampUp,
-            long duration
-    ) {
-        boolean useLowTickDefault = context.getResources()
-                .getBoolean(R.bool.config_udfpsUseLowTick);
-        int primitiveTick = DEFAULT_TICK;
-        if (Settings.Global.getFloat(
-                context.getContentResolver(),
-                "tick-low", useLowTickDefault ? 1 : 0) == 0) {
-            primitiveTick = VibrationEffect.Composition.PRIMITIVE_TICK;
-        }
-        float tickIntensity = Settings.Global.getFloat(
-                context.getContentResolver(),
-                "tick-intensity",
-                context.getResources().getFloat(R.dimen.config_udfpsTickIntensity));
-        int tickDelay = Settings.Global.getInt(
-                context.getContentResolver(),
-                "tick-delay",
-                context.getResources().getInteger(R.integer.config_udfpsTickDelay));
-
-        VibrationEffect.Composition composition = VibrationEffect.startComposition();
-        composition.addPrimitive(primitiveTick, tickIntensity, 0);
-        int primitives = (int) (duration / tickDelay);
-        float[] rampUp = new float[]{.48f, .58f, .69f, .83f};
-        if (useShortRampUp) {
-            rampUp = new float[]{.5f, .7f};
-        }
-        for (int i = 0; i < rampUp.length; i++) {
-            composition.addPrimitive(primitiveTick, tickIntensity * rampUp[i], tickDelay);
-        }
-        for (int i = rampUp.length; i < primitives; i++) {
-            composition.addPrimitive(primitiveTick, tickIntensity, tickDelay);
-        }
-        return composition.compose();
-    }
-
-    /**
      * Play haptic to signal udfps scanning started.
      */
     @VisibleForTesting
@@ -671,8 +626,8 @@
             mVibrator.vibrate(
                     Process.myUid(),
                     mContext.getOpPackageName(),
-                    mTick,
-                    "udfps-onStart-tick",
+                    EFFECT_CLICK,
+                    "udfps-onStart-click",
                     VIBRATION_SONIFICATION_ATTRIBUTES);
         }
     }
@@ -864,6 +819,7 @@
                         mServerRequest.mEnrollHelper,
                         mStatusBarStateController,
                         mPanelExpansionStateManager,
+                        mDialogManager,
                         mDumpManager
                 );
             case BiometricOverlayConstants.REASON_AUTH_KEYGUARD:
@@ -882,6 +838,7 @@
                         mSystemClock,
                         mKeyguardStateController,
                         mUnlockedScreenOffAnimationController,
+                        mDialogManager,
                         this
                 );
             case BiometricOverlayConstants.REASON_AUTH_BP:
@@ -892,6 +849,7 @@
                         bpView,
                         mStatusBarStateController,
                         mPanelExpansionStateManager,
+                        mDialogManager,
                         mDumpManager
                 );
             case BiometricOverlayConstants.REASON_AUTH_OTHER:
@@ -903,6 +861,7 @@
                         authOtherView,
                         mStatusBarStateController,
                         mPanelExpansionStateManager,
+                        mDialogManager,
                         mDumpManager
                 );
             default:
@@ -1059,7 +1018,6 @@
             }
         }
         mOnFingerDown = false;
-        mVibrator.cancel();
         if (mView.isIlluminationRequested()) {
             mView.stopIllumination();
         }
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
index 292a904..ac9e92e 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsEnrollViewController.java
@@ -22,6 +22,7 @@
 import com.android.systemui.R;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 
 /**
@@ -54,8 +55,10 @@
             @NonNull UdfpsEnrollHelper enrollHelper,
             @NonNull StatusBarStateController statusBarStateController,
             @NonNull PanelExpansionStateManager panelExpansionStateManager,
+            @NonNull SystemUIDialogManager systemUIDialogManager,
             @NonNull DumpManager dumpManager) {
-        super(view, statusBarStateController, panelExpansionStateManager, dumpManager);
+        super(view, statusBarStateController, panelExpansionStateManager, systemUIDialogManager,
+                dumpManager);
         mEnrollProgressBarRadius = getContext().getResources()
                 .getInteger(R.integer.config_udfpsEnrollProgressBar);
         mEnrollHelper = enrollHelper;
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.java
index 6198733..97dca0f 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsFpmOtherViewController.java
@@ -20,6 +20,7 @@
 
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.plugins.statusbar.StatusBarStateController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 
 /**
@@ -33,8 +34,10 @@
             @NonNull UdfpsFpmOtherView view,
             @NonNull StatusBarStateController statusBarStateController,
             @NonNull PanelExpansionStateManager panelExpansionStateManager,
+            @NonNull SystemUIDialogManager systemUIDialogManager,
             @NonNull DumpManager dumpManager) {
-        super(view, statusBarStateController, panelExpansionStateManager, dumpManager);
+        super(view, statusBarStateController, panelExpansionStateManager, systemUIDialogManager,
+                dumpManager);
     }
 
     @Override
diff --git a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
index 8f4d6f6..3e8a568 100644
--- a/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/biometrics/UdfpsKeyguardViewController.java
@@ -31,6 +31,7 @@
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.KeyguardBouncer;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
@@ -86,8 +87,10 @@
             @NonNull SystemClock systemClock,
             @NonNull KeyguardStateController keyguardStateController,
             @NonNull UnlockedScreenOffAnimationController unlockedScreenOffAnimationController,
+            @NonNull SystemUIDialogManager systemUIDialogManager,
             @NonNull UdfpsController udfpsController) {
-        super(view, statusBarStateController, panelExpansionStateManager, dumpManager);
+        super(view, statusBarStateController, panelExpansionStateManager, systemUIDialogManager,
+                dumpManager);
         mKeyguardViewManager = statusBarKeyguardViewManager;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mLockScreenShadeTransitionController = transitionController;
@@ -217,6 +220,10 @@
             return false;
         }
 
+        if (mDialogManager.shouldHideAffordance()) {
+            return true;
+        }
+
         if (mLaunchTransitionFadingAway) {
             return true;
         }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
index d3d6e03..6f30ac3 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/ControlActionCoordinatorImpl.kt
@@ -18,6 +18,7 @@
 
 import android.annotation.MainThread
 import android.app.Dialog
+import android.app.PendingIntent
 import android.content.Context
 import android.content.Intent
 import android.content.pm.PackageManager
@@ -88,7 +89,7 @@
         bouncerOrRun(createAction(cvh.cws.ci.controlId, {
             cvh.layout.performHapticFeedback(HapticFeedbackConstants.CONTEXT_CLICK)
             if (cvh.usePanel()) {
-                showDetail(cvh, control.getAppIntent().getIntent())
+                showDetail(cvh, control.getAppIntent())
             } else {
                 cvh.action(CommandAction(templateId))
             }
@@ -116,7 +117,7 @@
             // Long press snould only be called when there is valid control state, otherwise ignore
             cvh.cws.control?.let {
                 cvh.layout.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS)
-                showDetail(cvh, it.getAppIntent().getIntent())
+                showDetail(cvh, it.getAppIntent())
             }
         }, false /* blockable */))
     }
@@ -167,10 +168,10 @@
         bgExecutor.execute { vibrator.vibrate(effect) }
     }
 
-    private fun showDetail(cvh: ControlViewHolder, intent: Intent) {
+    private fun showDetail(cvh: ControlViewHolder, pendingIntent: PendingIntent) {
         bgExecutor.execute {
             val activities: List<ResolveInfo> = context.packageManager.queryIntentActivities(
-                intent,
+                pendingIntent.getIntent(),
                 PackageManager.MATCH_DEFAULT_ONLY
             )
 
@@ -178,7 +179,7 @@
                 // make sure the intent is valid before attempting to open the dialog
                 if (activities.isNotEmpty() && taskViewFactory.isPresent) {
                     taskViewFactory.get().create(context, uiExecutor, {
-                        dialog = DetailDialog(activityContext, it, intent, cvh).also {
+                        dialog = DetailDialog(activityContext, it, pendingIntent, cvh).also {
                             it.setOnDismissListener { _ -> dialog = null }
                             it.show()
                         }
diff --git a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
index 8a47a36..4758ab0 100644
--- a/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
+++ b/packages/SystemUI/src/com/android/systemui/controls/ui/DetailDialog.kt
@@ -43,7 +43,7 @@
 class DetailDialog(
     val activityContext: Context?,
     val taskView: TaskView,
-    val intent: Intent,
+    val pendingIntent: PendingIntent,
     val cvh: ControlViewHolder
 ) : Dialog(
     activityContext ?: cvh.context,
@@ -59,6 +59,14 @@
 
     var detailTaskId = INVALID_TASK_ID
 
+    private val fillInIntent = Intent().apply {
+        putExtra(EXTRA_USE_PANEL, true)
+
+        // Apply flags to make behaviour match documentLaunchMode=always.
+        addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
+        addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
+    }
+
     fun removeDetailTask() {
         if (detailTaskId == INVALID_TASK_ID) return
         ActivityTaskManager.getInstance().removeTask(detailTaskId)
@@ -67,13 +75,6 @@
 
     val stateCallback = object : TaskView.Listener {
         override fun onInitialized() {
-            val launchIntent = Intent(intent)
-            launchIntent.putExtra(EXTRA_USE_PANEL, true)
-
-            // Apply flags to make behaviour match documentLaunchMode=always.
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_DOCUMENT)
-            launchIntent.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK)
-
             val options = activityContext?.let {
                 ActivityOptions.makeCustomAnimation(
                     it,
@@ -82,9 +83,8 @@
                 )
             } ?: ActivityOptions.makeBasic()
             taskView.startActivity(
-                PendingIntent.getActivity(context, 0, launchIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE),
-                null /* fillInIntent */,
+                pendingIntent,
+                fillInIntent,
                 options,
                 getTaskViewBounds()
             )
@@ -97,6 +97,9 @@
 
         override fun onTaskCreated(taskId: Int, name: ComponentName?) {
             detailTaskId = taskId
+            requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
+                setAlpha(1f)
+            }
         }
 
         override fun onReleased() {
@@ -121,6 +124,7 @@
 
         requireViewById<ViewGroup>(R.id.controls_activity_view).apply {
             addView(taskView)
+            setAlpha(0f)
         }
 
         requireViewById<ImageView>(R.id.control_detail_close).apply {
@@ -134,7 +138,7 @@
                 removeDetailTask()
                 dismiss()
                 context.sendBroadcast(Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS))
-                v.context.startActivity(intent)
+                pendingIntent.send()
             }
         }
 
diff --git a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
index ff14064..2ebcd853 100644
--- a/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
+++ b/packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialogLite.java
@@ -121,6 +121,7 @@
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.telephony.TelephonyListenerManager;
@@ -236,6 +237,7 @@
     protected Handler mMainHandler;
     private int mSmallestScreenWidthDp;
     private final Optional<StatusBar> mStatusBarOptional;
+    private final SystemUIDialogManager mDialogManager;
     private final KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     private final DialogLaunchAnimator mDialogLaunchAnimator;
 
@@ -346,7 +348,8 @@
             PackageManager packageManager,
             Optional<StatusBar> statusBarOptional,
             KeyguardUpdateMonitor keyguardUpdateMonitor,
-            DialogLaunchAnimator dialogLaunchAnimator) {
+            DialogLaunchAnimator dialogLaunchAnimator,
+            SystemUIDialogManager dialogManager) {
         mContext = context;
         mWindowManagerFuncs = windowManagerFuncs;
         mAudioManager = audioManager;
@@ -378,6 +381,7 @@
         mStatusBarOptional = statusBarOptional;
         mKeyguardUpdateMonitor = keyguardUpdateMonitor;
         mDialogLaunchAnimator = dialogLaunchAnimator;
+        mDialogManager = dialogManager;
 
         // receive broadcasts
         IntentFilter filter = new IntentFilter();
@@ -677,7 +681,8 @@
                 mAdapter, mOverflowAdapter, mSysuiColorExtractor,
                 mStatusBarService, mNotificationShadeWindowController,
                 mSysUiState, this::onRefresh, mKeyguardShowing, mPowerAdapter, mUiEventLogger,
-                mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils);
+                mStatusBarOptional, mKeyguardUpdateMonitor, mLockPatternUtils,
+                mDialogManager);
 
         dialog.setOnDismissListener(this);
         dialog.setOnShowListener(this);
@@ -2219,10 +2224,12 @@
                 SysUiState sysuiState, Runnable onRefreshCallback, boolean keyguardShowing,
                 MyPowerOptionsAdapter powerAdapter, UiEventLogger uiEventLogger,
                 Optional<StatusBar> statusBarOptional,
-                KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils) {
+                KeyguardUpdateMonitor keyguardUpdateMonitor, LockPatternUtils lockPatternUtils,
+                SystemUIDialogManager systemUiDialogManager) {
             // We set dismissOnDeviceLock to false because we have a custom broadcast receiver to
             // dismiss this dialog when the device is locked.
-            super(context, themeRes, false /* dismissOnDeviceLock */);
+            super(context, themeRes, false /* dismissOnDeviceLock */,
+                    systemUiDialogManager);
             mContext = context;
             mAdapter = adapter;
             mOverflowAdapter = overflowAdapter;
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 c12d48d..f2cb254 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputBaseDialog.java
@@ -44,6 +44,7 @@
 
 import com.android.systemui.R;
 import com.android.systemui.statusbar.phone.SystemUIDialog;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 /**
  * Base dialog for media output UI
@@ -52,6 +53,7 @@
         MediaOutputController.Callback, Window.Callback {
 
     private static final String TAG = "MediaOutputDialog";
+    private static final String EMPTY_TITLE = " ";
 
     private final Handler mMainThreadHandler = new Handler(Looper.getMainLooper());
     private final RecyclerView.LayoutManager mLayoutManager;
@@ -82,9 +84,12 @@
         }
     };
 
-    public MediaOutputBaseDialog(Context context, MediaOutputController mediaOutputController) {
-        super(context);
-        mContext = context;
+    public MediaOutputBaseDialog(Context context, MediaOutputController mediaOutputController,
+            SystemUIDialogManager dialogManager) {
+        super(context, dialogManager);
+
+        // Save the context that is wrapped with our theme.
+        mContext = getContext();
         mMediaOutputController = mediaOutputController;
         mLayoutManager = new LinearLayoutManager(mContext);
         mListMaxHeight = context.getResources().getDimensionPixelSize(
@@ -105,6 +110,9 @@
         lp.setFitInsetsIgnoringVisibility(true);
         window.setAttributes(lp);
         window.setContentView(mDialogView);
+        // Sets window to a blank string to avoid talkback announce app label first when pop up,
+        // which doesn't make sense.
+        window.setTitle(EMPTY_TITLE);
 
         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/MediaOutputController.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
index ad6901f..a1e2c57 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputController.java
@@ -56,6 +56,7 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 import java.util.ArrayList;
 import java.util.Collection;
@@ -80,6 +81,7 @@
     private final ShadeController mShadeController;
     private final ActivityStarter mActivityStarter;
     private final DialogLaunchAnimator mDialogLaunchAnimator;
+    private final SystemUIDialogManager mDialogManager;
     private final List<MediaDevice> mGroupMediaDevices = new CopyOnWriteArrayList<>();
     private final boolean mAboveStatusbar;
     private final boolean mVolumeAdjustmentForRemoteGroupSessions;
@@ -101,7 +103,7 @@
             boolean aboveStatusbar, MediaSessionManager mediaSessionManager, LocalBluetoothManager
             lbm, ShadeController shadeController, ActivityStarter starter,
             NotificationEntryManager notificationEntryManager, UiEventLogger uiEventLogger,
-            DialogLaunchAnimator dialogLaunchAnimator) {
+            DialogLaunchAnimator dialogLaunchAnimator, SystemUIDialogManager dialogManager) {
         mContext = context;
         mPackageName = packageName;
         mMediaSessionManager = mediaSessionManager;
@@ -117,6 +119,7 @@
         mDialogLaunchAnimator = dialogLaunchAnimator;
         mVolumeAdjustmentForRemoteGroupSessions = mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_volumeAdjustmentForRemoteGroupSessions);
+        mDialogManager = dialogManager;
     }
 
     void start(@NonNull Callback cb) {
@@ -478,9 +481,10 @@
         // We show the output group dialog from the output dialog.
         MediaOutputController controller = new MediaOutputController(mContext, mPackageName,
                 mAboveStatusbar, mMediaSessionManager, mLocalBluetoothManager, mShadeController,
-                mActivityStarter, mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mActivityStarter, mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator,
+                mDialogManager);
         MediaOutputGroupDialog dialog = new MediaOutputGroupDialog(mContext, mAboveStatusbar,
-                controller);
+                controller, mDialogManager);
         mDialogLaunchAnimator.showFromView(dialog, mediaOutputDialog);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
index eca8ac9..7e2558c 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialog.java
@@ -28,6 +28,7 @@
 import com.android.internal.logging.UiEventLogger;
 import com.android.systemui.R;
 import com.android.systemui.dagger.SysUISingleton;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 /**
  * Dialog for media output transferring.
@@ -37,8 +38,9 @@
     final UiEventLogger mUiEventLogger;
 
     MediaOutputDialog(Context context, boolean aboveStatusbar, MediaOutputController
-            mediaOutputController, UiEventLogger uiEventLogger) {
-        super(context, mediaOutputController);
+            mediaOutputController, UiEventLogger uiEventLogger,
+            SystemUIDialogManager dialogManager) {
+        super(context, mediaOutputController, dialogManager);
         mUiEventLogger = uiEventLogger;
         mAdapter = new MediaOutputAdapter(mMediaOutputController, this);
         if (!aboveStatusbar) {
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
index b91901d..a7bc852 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputDialogFactory.kt
@@ -25,6 +25,7 @@
 import com.android.systemui.plugins.ActivityStarter
 import com.android.systemui.statusbar.notification.NotificationEntryManager
 import com.android.systemui.statusbar.phone.ShadeController
+import com.android.systemui.statusbar.phone.SystemUIDialogManager
 import javax.inject.Inject
 
 /**
@@ -38,7 +39,8 @@
     private val starter: ActivityStarter,
     private val notificationEntryManager: NotificationEntryManager,
     private val uiEventLogger: UiEventLogger,
-    private val dialogLaunchAnimator: DialogLaunchAnimator
+    private val dialogLaunchAnimator: DialogLaunchAnimator,
+    private val dialogManager: SystemUIDialogManager
 ) {
     companion object {
         var mediaOutputDialog: MediaOutputDialog? = null
@@ -51,8 +53,9 @@
 
         val controller = MediaOutputController(context, packageName, aboveStatusBar,
             mediaSessionManager, lbm, shadeController, starter, notificationEntryManager,
-            uiEventLogger, dialogLaunchAnimator)
-        val dialog = MediaOutputDialog(context, aboveStatusBar, controller, uiEventLogger)
+            uiEventLogger, dialogLaunchAnimator, dialogManager)
+        val dialog = MediaOutputDialog(context, aboveStatusBar, controller, uiEventLogger,
+                dialogManager)
         mediaOutputDialog = dialog
 
         // Show the dialog.
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
index b41e813..478b890 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputGroupDialog.java
@@ -25,6 +25,7 @@
 import androidx.core.graphics.drawable.IconCompat;
 
 import com.android.systemui.R;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 /**
  * Dialog for media output group.
@@ -32,8 +33,8 @@
 public class MediaOutputGroupDialog extends MediaOutputBaseDialog {
 
     MediaOutputGroupDialog(Context context, boolean aboveStatusbar, MediaOutputController
-            mediaOutputController) {
-        super(context, mediaOutputController);
+            mediaOutputController, SystemUIDialogManager dialogManager) {
+        super(context, mediaOutputController, dialogManager);
         mMediaOutputController.resetGroupMediaDevices();
         mAdapter = new MediaOutputGroupAdapter(mMediaOutputController);
         if (!aboveStatusbar) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
index 7ba9cc2..a2577d6 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DataSaverTile.java
@@ -98,7 +98,7 @@
                         toggleDataSaver();
                         Prefs.putBoolean(mContext, Prefs.Key.QS_DATA_SAVER_DIALOG_SHOWN, true);
                     });
-            dialog.setNegativeButton(com.android.internal.R.string.cancel, null);
+            dialog.setNeutralButton(com.android.internal.R.string.cancel, null);
             dialog.setShowForAllUsers(true);
 
             if (view != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
index 20805a1..a339dcf 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
+++ b/packages/SystemUI/src/com/android/systemui/qs/tiles/DndTile.java
@@ -190,7 +190,6 @@
                 case Settings.Secure.ZEN_DURATION_PROMPT:
                     mUiHandler.post(() -> {
                         Dialog dialog = makeZenModeDialog();
-                        SystemUIDialog.registerDismissListener(dialog);
                         if (view != null) {
                             mDialogLaunchAnimator.showFromView(dialog, view, false);
                         } else {
@@ -211,10 +210,12 @@
     }
 
     private Dialog makeZenModeDialog() {
-        AlertDialog dialog = new EnableZenModeDialog(mContext, R.style.Theme_SystemUI_Dialog)
-                .createDialog();
+        AlertDialog dialog = new EnableZenModeDialog(mContext, R.style.Theme_SystemUI_Dialog,
+                true /* cancelIsNeutral */).createDialog();
         SystemUIDialog.applyFlags(dialog);
         SystemUIDialog.setShowForAllUsers(dialog, true);
+        SystemUIDialog.registerDismissListener(dialog);
+        SystemUIDialog.setDialogSize(dialog);
         return dialog;
     }
 
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 ba4257f..e3f085c 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
@@ -159,7 +159,9 @@
         if (DEBUG) {
             Log.d(TAG, "Init InternetDialog");
         }
-        mContext = context;
+
+        // Save the context that is wrapped with our theme.
+        mContext = getContext();
         mHandler = handler;
         mBackgroundExecutor = executor;
         mInternetDialogFactory = internetDialogFactory;
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 1fee1b4..7dd24b4 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
@@ -316,15 +316,11 @@
     }
 
     CharSequence getSubtitleText(boolean isProgressBarVisible) {
-        if (isAirplaneModeEnabled()) {
-            return null;
-        }
-
         if (mCanConfigWifi && !mWifiManager.isWifiEnabled()) {
-            // When the airplane mode is off and Wi-Fi is disabled.
+            // When Wi-Fi is disabled.
             //   Sub-Title: Wi-Fi is off
             if (DEBUG) {
-                Log.d(TAG, "Airplane mode off + Wi-Fi off.");
+                Log.d(TAG, "Wi-Fi off.");
             }
             return mContext.getText(SUBTITLE_TEXT_WIFI_IS_OFF);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
index 85bf98c..7f130cb 100644
--- a/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
+++ b/packages/SystemUI/src/com/android/systemui/recents/ScreenPinningRequest.java
@@ -16,6 +16,7 @@
 
 package com.android.systemui.recents;
 
+import static com.android.systemui.shared.recents.utilities.Utilities.isTablet;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_LANDSCAPE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_NONE;
 import static com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE;
@@ -248,8 +249,8 @@
                     .setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
             View buttons = mLayout.findViewById(R.id.screen_pinning_buttons);
             WindowManagerWrapper wm = WindowManagerWrapper.getInstance();
-            if (!QuickStepContract.isGesturalMode(mNavBarMode) 
-            	    && wm.hasSoftNavigationBar(mContext.getDisplayId())) {
+            if (!QuickStepContract.isGesturalMode(mNavBarMode)
+            	    && wm.hasSoftNavigationBar(mContext.getDisplayId()) && !isTablet(mContext)) {
                 buttons.setLayoutDirection(View.LAYOUT_DIRECTION_LOCALE);
                 swapChildrenIfRtlAndVertical(buttons);
             } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
index f43d9c3..d7b4738 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/KeyguardIndicationController.java
@@ -887,7 +887,13 @@
                 mStatusBarKeyguardViewManager.showBouncerMessage(message, mInitialTextColorState);
             }
         } else {
-            showBiometricMessage(mContext.getString(R.string.keyguard_unlock));
+            if (mKeyguardUpdateMonitor.isUdfpsSupported()
+                    && mKeyguardUpdateMonitor.getUserCanSkipBouncer(
+                    KeyguardUpdateMonitor.getCurrentUser())) {
+                showBiometricMessage(mContext.getString(R.string.keyguard_unlock_press));
+            } else {
+                showBiometricMessage(mContext.getString(R.string.keyguard_unlock));
+            }
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
index c4fadff..4551807 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/UserUtil.java
@@ -40,7 +40,7 @@
             super(context);
             setTitle(R.string.user_remove_user_title);
             setMessage(context.getString(R.string.user_remove_user_message));
-            setButton(DialogInterface.BUTTON_NEGATIVE,
+            setButton(DialogInterface.BUTTON_NEUTRAL,
                     context.getString(android.R.string.cancel), this);
             setButton(DialogInterface.BUTTON_POSITIVE,
                     context.getString(R.string.user_remove_user_remove), this);
@@ -51,7 +51,7 @@
 
         @Override
         public void onClick(DialogInterface dialog, int which) {
-            if (which == BUTTON_NEGATIVE) {
+            if (which == BUTTON_NEUTRAL) {
                 cancel();
             } else {
                 dismiss();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt b/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
new file mode 100644
index 0000000..a1d086b
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/charging/DwellRippleShader.kt
@@ -0,0 +1,145 @@
+/*
+ * 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.charging
+
+import android.graphics.Color
+import android.graphics.PointF
+import android.graphics.RuntimeShader
+import android.util.MathUtils
+
+/**
+ * Shader class that renders a distorted ripple for the UDFPS dwell effect.
+ * Adjustable shader parameters:
+ *   - progress
+ *   - origin
+ *   - color
+ *   - time
+ *   - maxRadius
+ *   - distortionStrength.
+ * See per field documentation for more details.
+ *
+ * Modeled after frameworks/base/graphics/java/android/graphics/drawable/RippleShader.java.
+ */
+class DwellRippleShader internal constructor() : RuntimeShader(SHADER, false) {
+    companion object {
+        private const val SHADER_UNIFORMS = """uniform vec2 in_origin;
+                uniform float in_time;
+                uniform float in_radius;
+                uniform float in_blur;
+                uniform vec4 in_color;
+                uniform float in_phase1;
+                uniform float in_phase2;
+                uniform float in_distortion_strength;"""
+        private const val SHADER_LIB = """
+                float softCircle(vec2 uv, vec2 xy, float radius, float blur) {
+                  float blurHalf = blur * 0.5;
+                  float d = distance(uv, xy);
+                  return 1. - smoothstep(1. - blurHalf, 1. + blurHalf, d / radius);
+                }
+
+                float softRing(vec2 uv, vec2 xy, float radius, float blur) {
+                  float thickness_half = radius * 0.25;
+                  float circle_outer = softCircle(uv, xy, radius + thickness_half, blur);
+                  float circle_inner = softCircle(uv, xy, radius - thickness_half, blur);
+                  return circle_outer - circle_inner;
+                }
+
+                vec2 distort(vec2 p, float time, float distort_amount_xy, float frequency) {
+                    return p + vec2(sin(p.x * frequency + in_phase1),
+                                    cos(p.y * frequency * 1.23 + in_phase2)) * distort_amount_xy;
+                }
+
+                vec4 ripple(vec2 p, float distort_xy, float frequency) {
+                    vec2 p_distorted = distort(p, in_time, distort_xy, frequency);
+                    float circle = softCircle(p_distorted, in_origin, in_radius * 1.2, in_blur);
+                    float rippleAlpha = max(circle,
+                        softRing(p_distorted, in_origin, in_radius, in_blur)) * 0.25;
+                    return in_color * rippleAlpha;
+                }
+                """
+        private const val SHADER_MAIN = """vec4 main(vec2 p) {
+                    vec4 color1 = ripple(p,
+                        12 * in_distortion_strength, // distort_xy
+                        0.012 // frequency
+                    );
+                    vec4 color2 = ripple(p,
+                        17.5 * in_distortion_strength, // distort_xy
+                        0.018 // frequency
+                    );
+                    // Alpha blend between two layers.
+                    return vec4(color1.xyz + color2.xyz
+                        * (1 - color1.w), color1.w + color2.w * (1-color1.w));
+                }"""
+        private const val SHADER = SHADER_UNIFORMS + SHADER_LIB + SHADER_MAIN
+    }
+
+    /**
+     * Maximum radius of the ripple.
+     */
+    var maxRadius: Float = 0.0f
+
+    /**
+     * Origin coordinate of the ripple.
+     */
+    var origin: PointF = PointF()
+        set(value) {
+            field = value
+            setUniform("in_origin", floatArrayOf(value.x, value.y))
+        }
+
+    /**
+     * Progress of the ripple. Float value between [0, 1].
+     */
+    var progress: Float = 0.0f
+        set(value) {
+            field = value
+            setUniform("in_radius",
+                    (1 - (1 - value) * (1 - value) * (1 - value))* maxRadius)
+            setUniform("in_blur", MathUtils.lerp(1f, 0.7f, value))
+        }
+
+    /**
+     * Distortion strength between [0, 1], with 0 being no distortion and 1 being full distortion.
+     */
+    var distortionStrength: Float = 0.0f
+        set(value) {
+            field = value
+            setUniform("in_distortion_strength", value)
+        }
+
+    /**
+     * Play time since the start of the effect in seconds.
+     */
+    var time: Float = 0.0f
+        set(value) {
+            field = value * 0.001f
+            setUniform("in_time", field)
+            setUniform("in_phase1", field * 2f + 0.367f)
+            setUniform("in_phase2", field * 5.2f * 1.531f)
+        }
+
+    /**
+     * A hex value representing the ripple color, in the format of ARGB
+     */
+    var color: Int = 0xffffff.toInt()
+        set(value) {
+            field = value
+            val color = Color.valueOf(value)
+            setUniform("in_color", floatArrayOf(color.red(),
+                    color.green(), color.blue(), color.alpha()))
+        }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
index aa3b3e1..ad1c232 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/BiometricUnlockController.java
@@ -74,7 +74,7 @@
     private static final long BIOMETRIC_WAKELOCK_TIMEOUT_MS = 15 * 1000;
     private static final String BIOMETRIC_WAKE_LOCK_NAME = "wake-and-unlock:wakelock";
     private static final UiEventLogger UI_EVENT_LOGGER = new UiEventLoggerImpl();
-    private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 3;
+    private static final int FP_ATTEMPTS_BEFORE_SHOW_BOUNCER = 2;
 
     @IntDef(prefix = { "MODE_" }, value = {
             MODE_NONE,
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 261b5db..5eb35ac 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelViewController.java
@@ -3262,12 +3262,6 @@
                     mStatusBarStateController.setState(KEYGUARD);
                 }
                 return true;
-            case StatusBarState.SHADE:
-
-                // This gets called in the middle of the touch handling, where the state is still
-                // that we are tracking the panel. Collapse the panel after this is done.
-                mView.post(mPostCollapseRunnable);
-                return false;
             default:
                 return true;
         }
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 2823d98..2bf16fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelViewController.java
@@ -928,7 +928,6 @@
 
     private void abortAnimations() {
         cancelHeightAnimator();
-        mView.removeCallbacks(mPostCollapseRunnable);
         mView.removeCallbacks(mFlingCollapseRunnable);
     }
 
@@ -1105,13 +1104,6 @@
         return onMiddleClicked();
     }
 
-    protected final Runnable mPostCollapseRunnable = new Runnable() {
-        @Override
-        public void run() {
-            collapse(false /* delayed */, 1.0f /* speedUpFactor */);
-        }
-    };
-
     protected abstract boolean onMiddleClicked();
 
     protected abstract boolean isDozing();
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 43264b6..93f9892 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialog.java
@@ -45,6 +45,10 @@
 
 /**
  * Base class for dialogs that should appear over panels and keyguard.
+ *
+ * Optionally provide a {@link SystemUIDialogManager} to its constructor to send signals to
+ * listeners on whether this dialog is showing.
+ *
  * The SystemUIDialog registers a listener for the screen off / close system dialogs broadcast,
  * and dismisses itself when it receives the broadcast.
  */
@@ -54,8 +58,9 @@
             "persist.systemui.flag_tablet_dialog_width";
 
     private final Context mContext;
-    private final DismissReceiver mDismissReceiver;
+    @Nullable private final DismissReceiver mDismissReceiver;
     private final Handler mHandler = new Handler();
+    @Nullable private final SystemUIDialogManager mDialogManager;
 
     private int mLastWidth = Integer.MIN_VALUE;
     private int mLastHeight = Integer.MIN_VALUE;
@@ -66,11 +71,22 @@
         this(context, R.style.Theme_SystemUI_Dialog);
     }
 
+    public SystemUIDialog(Context context, SystemUIDialogManager dialogManager) {
+        this(context, R.style.Theme_SystemUI_Dialog, true, dialogManager);
+    }
+
     public SystemUIDialog(Context context, int theme) {
         this(context, theme, true /* dismissOnDeviceLock */);
     }
-
     public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock) {
+        this(context, theme, dismissOnDeviceLock, null);
+    }
+
+    /**
+     * @param udfpsDialogManager If set, UDFPS will hide if this dialog is showing.
+     */
+    public SystemUIDialog(Context context, int theme, boolean dismissOnDeviceLock,
+            SystemUIDialogManager dialogManager) {
         super(context, theme);
         mContext = context;
 
@@ -80,6 +96,7 @@
         getWindow().setAttributes(attrs);
 
         mDismissReceiver = dismissOnDeviceLock ? new DismissReceiver(this) : null;
+        mDialogManager = dialogManager;
     }
 
     @Override
@@ -126,30 +143,7 @@
      * the device configuration changes, and the result will be used to resize this dialog window.
      */
     protected int getWidth() {
-        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);
-        }
+        return getDefaultDialogWidth(mContext);
     }
 
     /**
@@ -157,7 +151,7 @@
      * the device configuration changes, and the result will be used to resize this dialog window.
      */
     protected int getHeight() {
-        return ViewGroup.LayoutParams.WRAP_CONTENT;
+        return getDefaultDialogHeight();
     }
 
     @Override
@@ -168,6 +162,10 @@
             mDismissReceiver.register();
         }
 
+        if (mDialogManager != null) {
+            mDialogManager.setShowing(this, true);
+        }
+
         // Listen for configuration changes to resize this dialog window. This is mostly necessary
         // for foldables that often go from large <=> small screen when folding/unfolding.
         ViewRootImpl.addConfigCallback(this);
@@ -181,6 +179,10 @@
             mDismissReceiver.unregister();
         }
 
+        if (mDialogManager != null) {
+            mDialogManager.setShowing(this, false);
+        }
+
         ViewRootImpl.removeConfigCallback(this);
     }
 
@@ -267,6 +269,45 @@
         dismissReceiver.register();
     }
 
+    /** Set an appropriate size to {@code dialog} depending on the current configuration. */
+    public static void setDialogSize(Dialog dialog) {
+        // We need to create the dialog first, otherwise the size will be overridden when it is
+        // created.
+        dialog.create();
+        dialog.getWindow().setLayout(getDefaultDialogWidth(dialog.getContext()),
+                getDefaultDialogHeight());
+    }
+
+    private static int getDefaultDialogWidth(Context context) {
+        boolean isOnTablet = context.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,
+                    context.getResources().getDisplayMetrics()));
+        } else if (flagValue == -2) {
+            // The suggested small width for all dialogs (348dp)
+            return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 348,
+                    context.getResources().getDisplayMetrics()));
+        } else if (flagValue > 0) {
+            // Any given width.
+            return Math.round(
+                    TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, flagValue,
+                            context.getResources().getDisplayMetrics()));
+        } else {
+            // By default we use the same width as the notification shade in portrait mode (504dp).
+            return context.getResources().getDimensionPixelSize(R.dimen.large_dialog_width);
+        }
+    }
+
+    private static int getDefaultDialogHeight() {
+        return ViewGroup.LayoutParams.WRAP_CONTENT;
+    }
+
     private static class DismissReceiver extends BroadcastReceiver {
         private static final IntentFilter INTENT_FILTER = new IntentFilter();
         static {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java
new file mode 100644
index 0000000..204f710
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/SystemUIDialogManager.java
@@ -0,0 +1,118 @@
+/*
+ * 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 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 java.util.HashSet;
+import java.util.Set;
+
+import javax.inject.Inject;
+
+/**
+ * Register dialogs to this manager if extraneous affordances (like the UDFPS sensor area)
+ * should be hidden from the screen when the dialog shows.
+ *
+ * Currently, only used if UDFPS is supported on the device; however, can be extended in the future
+ * for other use cases.
+ */
+@SysUISingleton
+public class SystemUIDialogManager implements Dumpable {
+    private final StatusBarKeyguardViewManager mKeyguardViewManager;
+
+    private final Set<SystemUIDialog> mDialogsShowing = new HashSet<>();
+    private final Set<Listener> mListeners = new HashSet<>();
+
+    @Inject
+    public SystemUIDialogManager(
+            DumpManager dumpManager,
+            StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
+        dumpManager.registerDumpable(this);
+        mKeyguardViewManager = statusBarKeyguardViewManager;
+    }
+
+    /**
+     * Whether listeners should hide affordances like the UDFPS sensor icon.
+     */
+    public boolean shouldHideAffordance() {
+        return !mDialogsShowing.isEmpty();
+    }
+
+    /**
+     * Register a listener to receive callbacks.
+     */
+    public void registerListener(@NonNull Listener listener) {
+        mListeners.add(listener);
+    }
+
+    /**
+     * Unregister a listener from receiving callbacks.
+     */
+    public void unregisterListener(@NonNull Listener listener) {
+        mListeners.remove(listener);
+    }
+
+    void setShowing(SystemUIDialog dialog, boolean showing) {
+        final boolean wasHidingAffordances = shouldHideAffordance();
+        if (showing) {
+            mDialogsShowing.add(dialog);
+        } else {
+            mDialogsShowing.remove(dialog);
+        }
+
+        if (wasHidingAffordances != shouldHideAffordance()) {
+            updateDialogListeners();
+        }
+    }
+
+    private void updateDialogListeners() {
+        if (shouldHideAffordance()) {
+            mKeyguardViewManager.resetAlternateAuth(true);
+        }
+
+        for (Listener listener : mListeners) {
+            listener.shouldHideAffordances(shouldHideAffordance());
+        }
+    }
+
+    @Override
+    public void dump(@NonNull FileDescriptor fd, @NonNull PrintWriter pw, @NonNull String[] args) {
+        pw.println("listeners:");
+        for (Listener listener : mListeners) {
+            pw.println("\t" + listener);
+        }
+        pw.println("dialogs tracked:");
+        for (SystemUIDialog dialog : mDialogsShowing) {
+            pw.println("\t" + dialog);
+        }
+    }
+
+    /** SystemUIDialogManagerListener */
+    public interface Listener {
+        /**
+         * Callback where shouldHide=true if listeners should hide their views that may overlap
+         * a showing dialog.
+         */
+        void shouldHideAffordances(boolean shouldHide);
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
index 36e56f9..ebf5a6d 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/UserSwitcherController.java
@@ -1161,7 +1161,7 @@
                     ? com.android.settingslib.R.string.guest_reset_guest_dialog_title
                     : R.string.guest_exit_guest_dialog_title);
             setMessage(context.getString(R.string.guest_exit_guest_dialog_message));
-            setButton(DialogInterface.BUTTON_NEGATIVE,
+            setButton(DialogInterface.BUTTON_NEUTRAL,
                     context.getString(android.R.string.cancel), this);
             setButton(DialogInterface.BUTTON_POSITIVE,
                     context.getString(mGuestUserAutoCreated
@@ -1180,7 +1180,7 @@
             if (mFalsingManager.isFalseTap(penalty)) {
                 return;
             }
-            if (which == BUTTON_NEGATIVE) {
+            if (which == BUTTON_NEUTRAL) {
                 cancel();
             } else {
                 mUiEventLogger.log(QSUserSwitcherEvent.QS_USER_GUEST_REMOVE);
@@ -1198,7 +1198,7 @@
             super(context);
             setTitle(R.string.user_add_user_title);
             setMessage(context.getString(R.string.user_add_user_message_short));
-            setButton(DialogInterface.BUTTON_NEGATIVE,
+            setButton(DialogInterface.BUTTON_NEUTRAL,
                     context.getString(android.R.string.cancel), this);
             setButton(DialogInterface.BUTTON_POSITIVE,
                     context.getString(android.R.string.ok), this);
@@ -1212,7 +1212,7 @@
             if (mFalsingManager.isFalseTap(penalty)) {
                 return;
             }
-            if (which == BUTTON_NEGATIVE) {
+            if (which == BUTTON_NEUTRAL) {
                 cancel();
             } else {
                 mDialogLaunchAnimator.dismissStack(this);
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
index 9e42ff3..ac221a9 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsControllerTest.java
@@ -65,6 +65,7 @@
 import com.android.systemui.statusbar.phone.KeyguardBypassController;
 import com.android.systemui.statusbar.phone.StatusBar;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
@@ -170,6 +171,8 @@
     private TypedArray mBrightnessValues;
     @Mock
     private TypedArray mBrightnessBacklight;
+    @Mock
+    private SystemUIDialogManager mSystemUIDialogManager;
 
     // Capture listeners so that they can be used to send events
     @Captor private ArgumentCaptor<IUdfpsOverlayController> mOverlayCaptor;
@@ -179,8 +182,6 @@
     @Captor private ArgumentCaptor<ScreenLifecycle.Observer> mScreenObserverCaptor;
     private ScreenLifecycle.Observer mScreenObserver;
 
-    @Captor private ArgumentCaptor<UdfpsAnimationViewController> mAnimViewControllerCaptor;
-
     @Before
     public void setUp() {
         setUpResources();
@@ -238,7 +239,8 @@
                 mHandler,
                 mConfigurationController,
                 mSystemClock,
-                mUnlockedScreenOffAnimationController);
+                mUnlockedScreenOffAnimationController,
+                mSystemUIDialogManager);
         verify(mFingerprintManager).setUdfpsOverlayController(mOverlayCaptor.capture());
         mOverlayController = mOverlayCaptor.getValue();
         verify(mScreenLifecycle).addObserver(mScreenObserverCaptor.capture());
@@ -642,12 +644,12 @@
         mTouchListenerCaptor.getValue().onTouch(mUdfpsView, moveEvent);
         moveEvent.recycle();
 
-        // THEN low-tick haptic is played
+        // THEN click haptic is played
         verify(mVibrator).vibrate(
                 anyInt(),
                 anyString(),
                 any(),
-                eq("udfps-onStart-tick"),
+                eq("udfps-onStart-click"),
                 eq(UdfpsController.VIBRATION_SONIFICATION_ATTRIBUTES));
 
         // THEN make sure vibration attributes has so that it always will play the haptic,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
index 1cf21ac..0ae3c39 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/biometrics/UdfpsKeyguardViewControllerTest.java
@@ -42,6 +42,7 @@
 import com.android.systemui.statusbar.LockscreenShadeTransitionController;
 import com.android.systemui.statusbar.StatusBarState;
 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.phone.UnlockedScreenOffAnimationController;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionListener;
 import com.android.systemui.statusbar.phone.panelstate.PanelExpansionStateManager;
@@ -92,6 +93,8 @@
     @Mock
     private UnlockedScreenOffAnimationController mUnlockedScreenOffAnimationController;
     @Mock
+    private SystemUIDialogManager mDialogManager;
+    @Mock
     private UdfpsController mUdfpsController;
     private FakeSystemClock mSystemClock = new FakeSystemClock();
 
@@ -130,6 +133,7 @@
                 mSystemClock,
                 mKeyguardStateController,
                 mUnlockedScreenOffAnimationController,
+                mDialogManager,
                 mUdfpsController);
     }
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
new file mode 100644
index 0000000..87b9172
--- /dev/null
+++ b/packages/SystemUI/tests/src/com/android/systemui/controls/ui/DetailDialogTest.kt
@@ -0,0 +1,71 @@
+/*
+ * 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.controls.ui
+
+import android.app.PendingIntent
+import android.testing.AndroidTestingRunner
+import android.testing.TestableLooper
+import androidx.test.filters.SmallTest
+import com.android.systemui.SysuiTestCase
+import com.android.wm.shell.TaskView
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.mockito.ArgumentMatchers.eq
+import org.mockito.Mock
+import org.mockito.Mockito.any
+import org.mockito.Mockito.verify
+import org.mockito.MockitoAnnotations
+
+@SmallTest
+@RunWith(AndroidTestingRunner::class)
+@TestableLooper.RunWithLooper
+class DetailDialogTest : SysuiTestCase() {
+
+    @Mock
+    private lateinit var taskView: TaskView
+    @Mock
+    private lateinit var controlViewHolder: ControlViewHolder
+    @Mock
+    private lateinit var pendingIntent: PendingIntent
+
+    @Before
+    fun setUp() {
+        MockitoAnnotations.initMocks(this)
+    }
+
+    @Test
+    fun testPendingIntentIsUnModified() {
+        // GIVEN the dialog is created with a PendingIntent
+        val dialog = createDialog(pendingIntent)
+
+        // WHEN the TaskView is initialized
+        dialog.stateCallback.onInitialized()
+
+        // THEN the PendingIntent used to call startActivity is unmodified by systemui
+        verify(taskView).startActivity(eq(pendingIntent), any(), any(), any())
+    }
+
+    private fun createDialog(pendingIntent: PendingIntent): DetailDialog {
+        return DetailDialog(
+            mContext,
+            taskView,
+            pendingIntent,
+            controlViewHolder
+        )
+    }
+}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
index bf5522c..e3a7e3b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/globalactions/GlobalActionsDialogLiteTest.java
@@ -62,6 +62,7 @@
 import com.android.systemui.settings.UserContextProvider;
 import com.android.systemui.statusbar.NotificationShadeWindowController;
 import com.android.systemui.statusbar.phone.StatusBar;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 import com.android.systemui.statusbar.policy.ConfigurationController;
 import com.android.systemui.statusbar.policy.KeyguardStateController;
 import com.android.systemui.telephony.TelephonyListenerManager;
@@ -117,6 +118,7 @@
     @Mock private StatusBar mStatusBar;
     @Mock private KeyguardUpdateMonitor mKeyguardUpdateMonitor;
     @Mock private DialogLaunchAnimator mDialogLaunchAnimator;
+    @Mock private SystemUIDialogManager mDialogManager;
 
     private TestableLooper mTestableLooper;
 
@@ -162,7 +164,8 @@
                 mPackageManager,
                 Optional.of(mStatusBar),
                 mKeyguardUpdateMonitor,
-                mDialogLaunchAnimator);
+                mDialogLaunchAnimator,
+                mDialogManager);
         mGlobalActionsDialogLite.setZeroDialogPressDelayForTesting();
 
         ColorExtractor.GradientColors backdropColors = new ColorExtractor.GradientColors();
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 81bcbfb..d7c00fb 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/LockIconViewControllerTest.java
@@ -26,7 +26,6 @@
 import static org.mockito.Mockito.anyBoolean;
 import static org.mockito.Mockito.anyInt;
 import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.never;
 import static org.mockito.Mockito.reset;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
@@ -43,7 +42,6 @@
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.util.Pair;
-import android.view.LayoutInflater;
 import android.view.View;
 import android.view.WindowManager;
 import android.view.accessibility.AccessibilityManager;
@@ -69,8 +67,6 @@
 import com.android.systemui.util.concurrency.FakeExecutor;
 import com.android.systemui.util.time.FakeSystemClock;
 
-import com.airbnb.lottie.LottieAnimationView;
-
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
@@ -110,8 +106,6 @@
     private @Mock ConfigurationController mConfigurationController;
     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;
@@ -149,7 +143,6 @@
 
         when(mLockIconView.getResources()).thenReturn(mResources);
         when(mLockIconView.getContext()).thenReturn(mContext);
-        when(mLockIconView.findViewById(R.layout.udfps_aod_lock_icon)).thenReturn(mAodFp);
         when(mContext.getResources()).thenReturn(mResources);
         when(mContext.getSystemService(WindowManager.class)).thenReturn(mWindowManager);
         Rect windowBounds = new Rect(0, 0, 800, 1200);
@@ -176,8 +169,7 @@
                 mDelayableExecutor,
                 mVibrator,
                 mAuthRippleController,
-                mResources,
-                mLayoutInflater
+                mResources
         );
     }
 
@@ -187,35 +179,6 @@
     }
 
     @Test
-    public void testIgnoreUdfpsWhenNotSupported() {
-        // GIVEN Udpfs sensor is NOT available
-        mLockIconViewController.init();
-        captureAttachListener();
-
-        // WHEN the view is attached
-        mAttachListener.onViewAttachedToWindow(mLockIconView);
-
-        // THEN lottie animation should NOT be inflated
-        verify(mLayoutInflater, never()).inflate(eq(R.layout.udfps_aod_lock_icon), any());
-    }
-
-    @Test
-    public void testInflateUdfpsWhenSupported() {
-        // GIVEN Udpfs sensor is available
-        setupUdfps();
-        when(mKeyguardUpdateMonitor.isUdfpsEnrolled()).thenReturn(true);
-
-        mLockIconViewController.init();
-        captureAttachListener();
-
-        // WHEN the view is attached
-        mAttachListener.onViewAttachedToWindow(mLockIconView);
-
-        // THEN lottie animation should be inflated
-        verify(mLayoutInflater).inflate(eq(R.layout.udfps_aod_lock_icon), any());
-    }
-
-    @Test
     public void testUpdateFingerprintLocationOnInit() {
         // GIVEN fp sensor location is available pre-attached
         Pair<Integer, PointF> udfps = setupUdfps();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
index 053851e..451291d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputBaseDialogTest.java
@@ -43,6 +43,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -65,6 +66,7 @@
             mock(NotificationEntryManager.class);
     private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
     private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
+    private final SystemUIDialogManager mDialogManager = mock(SystemUIDialogManager.class);
 
     private MediaOutputBaseDialogImpl mMediaOutputBaseDialogImpl;
     private MediaOutputController mMediaOutputController;
@@ -77,7 +79,7 @@
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
         mMediaOutputBaseDialogImpl = new MediaOutputBaseDialogImpl(mContext,
                 mMediaOutputController);
         mMediaOutputBaseDialogImpl.onCreate(new Bundle());
@@ -167,7 +169,7 @@
     class MediaOutputBaseDialogImpl extends MediaOutputBaseDialog {
 
         MediaOutputBaseDialogImpl(Context context, MediaOutputController mediaOutputController) {
-            super(context, mediaOutputController);
+            super(context, mediaOutputController, mDialogManager);
 
             mAdapter = mMediaOutputBaseAdapter;
         }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
index 09ec4ca..cd26e0d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputControllerTest.java
@@ -54,6 +54,7 @@
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.notification.collection.NotificationEntry;
 import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 import org.junit.Before;
 import org.junit.Test;
@@ -93,6 +94,7 @@
             mock(NotificationEntryManager.class);
     private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
     private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
+    private final SystemUIDialogManager mDialogManager = mock(SystemUIDialogManager.class);
 
     private Context mSpyContext;
     private MediaOutputController mMediaOutputController;
@@ -115,7 +117,7 @@
 
         mMediaOutputController = new MediaOutputController(mSpyContext, TEST_PACKAGE_NAME, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
         mLocalMediaManager = spy(mMediaOutputController.mLocalMediaManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         MediaDescription.Builder builder = new MediaDescription.Builder();
@@ -159,7 +161,7 @@
     public void start_withoutPackageName_verifyMediaControllerInit() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
 
         mMediaOutputController.start(mCb);
 
@@ -180,7 +182,7 @@
     public void stop_withoutPackageName_verifyMediaControllerDeinit() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
 
         mMediaOutputController.start(mCb);
 
@@ -451,7 +453,7 @@
     public void getNotificationLargeIcon_withoutPackageName_returnsNull() {
         mMediaOutputController = new MediaOutputController(mSpyContext, null, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
 
         assertThat(mMediaOutputController.getNotificationIcon()).isNull();
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
index 8a3ea56..ada8d35 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputDialogTest.java
@@ -40,6 +40,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 import org.junit.After;
 import org.junit.Before;
@@ -67,6 +68,7 @@
             mock(NotificationEntryManager.class);
     private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
     private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
+    private final SystemUIDialogManager mDialogManager = mock(SystemUIDialogManager.class);
 
     private MediaOutputDialog mMediaOutputDialog;
     private MediaOutputController mMediaOutputController;
@@ -76,10 +78,10 @@
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputDialog = new MediaOutputDialog(mContext, false,
-                mMediaOutputController, mUiEventLogger);
+                mMediaOutputController, mUiEventLogger, mDialogManager);
         mMediaOutputDialog.show();
 
         when(mLocalMediaManager.getCurrentConnectedDevice()).thenReturn(mMediaDevice);
@@ -125,7 +127,7 @@
     // and verify if the calling times increases.
     public void onCreate_ShouldLogVisibility() {
         MediaOutputDialog testDialog = new MediaOutputDialog(mContext, false,
-                mMediaOutputController, mUiEventLogger);
+                mMediaOutputController, mUiEventLogger, mDialogManager);
         testDialog.show();
 
         testDialog.dismissDialog();
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
index e8cd6c8..b114452 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputGroupDialogTest.java
@@ -38,6 +38,7 @@
 import com.android.systemui.plugins.ActivityStarter;
 import com.android.systemui.statusbar.notification.NotificationEntryManager;
 import com.android.systemui.statusbar.phone.ShadeController;
+import com.android.systemui.statusbar.phone.SystemUIDialogManager;
 
 import org.junit.After;
 import org.junit.Before;
@@ -66,6 +67,7 @@
             mock(NotificationEntryManager.class);
     private final UiEventLogger mUiEventLogger = mock(UiEventLogger.class);
     private final DialogLaunchAnimator mDialogLaunchAnimator = mock(DialogLaunchAnimator.class);
+    private final SystemUIDialogManager mDialogManager = mock(SystemUIDialogManager.class);
 
     private MediaOutputGroupDialog mMediaOutputGroupDialog;
     private MediaOutputController mMediaOutputController;
@@ -75,10 +77,10 @@
     public void setUp() {
         mMediaOutputController = new MediaOutputController(mContext, TEST_PACKAGE, false,
                 mMediaSessionManager, mLocalBluetoothManager, mShadeController, mStarter,
-                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator);
+                mNotificationEntryManager, mUiEventLogger, mDialogLaunchAnimator, mDialogManager);
         mMediaOutputController.mLocalMediaManager = mLocalMediaManager;
         mMediaOutputGroupDialog = new MediaOutputGroupDialog(mContext, false,
-                mMediaOutputController);
+                mMediaOutputController, mDialogManager);
         mMediaOutputGroupDialog.show();
         when(mLocalMediaManager.getSelectedMediaDevice()).thenReturn(mMediaDevices);
     }
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 6dca2a7..47f6e5c 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
@@ -235,10 +235,18 @@
     }
 
     @Test
-    public void getSubtitleText_withAirplaneModeOn_returnNull() {
+    public void getSubtitleText_withApmOnAndWifiOff_returnWifiIsOff() {
         fakeAirplaneModeEnabled(true);
+        when(mWifiManager.isWifiEnabled()).thenReturn(false);
 
-        assertThat(mInternetDialogController.getSubtitleText(false)).isNull();
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isEqualTo(getResourcesString("wifi_is_off"));
+
+        // if the Wi-Fi disallow config, then don't return Wi-Fi related string.
+        mInternetDialogController.mCanConfigWifi = false;
+
+        assertThat(mInternetDialogController.getSubtitleText(false))
+                .isNotEqualTo(getResourcesString("wifi_is_off"));
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
index 07debe6..c3349f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/phone/BiometricsUnlockControllerTest.java
@@ -381,16 +381,15 @@
     }
 
     @Test
-    public void onUdfpsConsecutivelyFailedThreeTimes_showBouncer() {
+    public void onUdfpsConsecutivelyFailedTwoTimes_showBouncer() {
         // GIVEN UDFPS is supported
         when(mUpdateMonitor.isUdfpsSupported()).thenReturn(true);
 
-        // WHEN udfps fails twice - then don't show the bouncer
-        mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
+        // WHEN udfps fails once - then don't show the bouncer
         mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
         verify(mStatusBarKeyguardViewManager, never()).showBouncer(anyBoolean());
 
-        // WHEN udfps fails the third time
+        // WHEN udfps fails the second time
         mBiometricUnlockController.onBiometricAuthFailed(BiometricSourceType.FINGERPRINT);
 
         // THEN show the bouncer
diff --git a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
index eaf2694..6744ea8 100644
--- a/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
+++ b/services/accessibility/java/com/android/server/accessibility/SystemActionPerformer.java
@@ -288,8 +288,6 @@
                     showGlobalActions();
                     return true;
                 }
-                case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN:
-                    return toggleSplitScreen();
                 case AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN:
                     return lockScreen();
                 case AccessibilityService.GLOBAL_ACTION_TAKE_SCREENSHOT:
@@ -369,21 +367,6 @@
         mWindowManagerService.showGlobalActions();
     }
 
-    private boolean toggleSplitScreen() {
-        final long token = Binder.clearCallingIdentity();
-        try {
-            StatusBarManagerInternal statusBarService = LocalServices.getService(
-                    StatusBarManagerInternal.class);
-            if (statusBarService == null) {
-                return false;
-            }
-            statusBarService.toggleSplitScreen();
-        } finally {
-            Binder.restoreCallingIdentity(token);
-        }
-        return true;
-    }
-
     private boolean lockScreen() {
         mContext.getSystemService(PowerManager.class).goToSleep(SystemClock.uptimeMillis(),
                 PowerManager.GO_TO_SLEEP_REASON_ACCESSIBILITY, 0);
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 53b1608..ec15af3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -4184,7 +4184,7 @@
 
             didSomething |= mProcessList.killPackageProcessesLSP(packageName, appId, userId,
                     ProcessList.INVALID_ADJ, callerWillRestart, false /* allowRestart */, doit,
-                    evenPersistent, true /* setRemoved */,
+                    evenPersistent, true /* setRemoved */, uninstalling,
                     packageName == null ? ApplicationExitInfo.REASON_USER_STOPPED
                     : ApplicationExitInfo.REASON_USER_REQUESTED,
                     ApplicationExitInfo.SUBREASON_UNKNOWN,
@@ -7220,6 +7220,7 @@
                             ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
                             true /* callerWillRestart */, true /* doit */,
                             true /* evenPersistent */, false /* setRemoved */,
+                            false /* uninstalling */,
                             ApplicationExitInfo.REASON_OTHER,
                             ApplicationExitInfo.SUBREASON_KILL_UID,
                             reason != null ? reason : "kill uid");
@@ -7241,6 +7242,7 @@
                             ProcessList.PERSISTENT_PROC_ADJ, false /* callerWillRestart */,
                             true /* callerWillRestart */, true /* doit */,
                             true /* evenPersistent */, false /* setRemoved */,
+                            false /* uninstalling */,
                             ApplicationExitInfo.REASON_PERMISSION_CHANGE,
                             ApplicationExitInfo.SUBREASON_UNKNOWN,
                             reason != null ? reason : "kill uid");
diff --git a/services/core/java/com/android/server/am/OomAdjuster.java b/services/core/java/com/android/server/am/OomAdjuster.java
index ff480d1..7673123 100644
--- a/services/core/java/com/android/server/am/OomAdjuster.java
+++ b/services/core/java/com/android/server/am/OomAdjuster.java
@@ -1633,7 +1633,7 @@
         int schedGroup;
         int procState;
         int cachedAdjSeq;
-        int capability = 0;
+        int capability = cycleReEval ? app.mState.getCurCapability() : 0;
 
         boolean foregroundActivities = false;
         boolean hasVisibleActivities = false;
@@ -2018,10 +2018,6 @@
                     }
 
                     if ((cr.flags & Context.BIND_WAIVE_PRIORITY) == 0) {
-                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
-                            continue;
-                        }
-
                         if (cr.hasFlag(Context.BIND_INCLUDE_CAPABILITIES)) {
                             capability |= cstate.getCurCapability();
                         }
@@ -2042,6 +2038,10 @@
                             }
                         }
 
+                        if (shouldSkipDueToCycle(app, cstate, procState, adj, cycleReEval)) {
+                            continue;
+                        }
+
                         if (clientProcState >= PROCESS_STATE_CACHED_ACTIVITY) {
                             // If the other app is cached for any reason, for purposes here
                             // we are going to consider it empty.  The specific cached state
diff --git a/services/core/java/com/android/server/am/ProcessList.java b/services/core/java/com/android/server/am/ProcessList.java
index b77270f..92c8223 100644
--- a/services/core/java/com/android/server/am/ProcessList.java
+++ b/services/core/java/com/android/server/am/ProcessList.java
@@ -2750,8 +2750,8 @@
             int reasonCode, int subReason, String reason) {
         return killPackageProcessesLSP(packageName, appId, userId, minOomAdj,
                 false /* callerWillRestart */, true /* allowRestart */, true /* doit */,
-                false /* evenPersistent */, false /* setRemoved */, reasonCode,
-                subReason, reason);
+                false /* evenPersistent */, false /* setRemoved */, false /* uninstalling */,
+                reasonCode, subReason, reason);
     }
 
     @GuardedBy("mService")
@@ -2784,9 +2784,10 @@
     @GuardedBy({"mService", "mProcLock"})
     boolean killPackageProcessesLSP(String packageName, int appId,
             int userId, int minOomAdj, boolean callerWillRestart, boolean allowRestart,
-            boolean doit, boolean evenPersistent, boolean setRemoved, int reasonCode,
-            int subReason, String reason) {
-        ArrayList<ProcessRecord> procs = new ArrayList<>();
+            boolean doit, boolean evenPersistent, boolean setRemoved, boolean uninstalling,
+            int reasonCode, int subReason, String reason) {
+        final PackageManagerInternal pm = mService.getPackageManagerInternal();
+        final ArrayList<Pair<ProcessRecord, Boolean>> procs = new ArrayList<>();
 
         // Remove all processes this package may have touched: all with the
         // same UID (except for the system or root user), and all whose name
@@ -2803,7 +2804,18 @@
                 }
                 if (app.isRemoved()) {
                     if (doit) {
-                        procs.add(app);
+                        boolean shouldAllowRestart = false;
+                        if (!uninstalling && packageName != null) {
+                            // This package has a dependency on the given package being stopped,
+                            // while it's not being frozen nor uninstalled, allow to restart it.
+                            shouldAllowRestart = !app.getPkgList().containsKey(packageName)
+                                    && app.getPkgDeps() != null
+                                    && app.getPkgDeps().contains(packageName)
+                                    && app.info != null
+                                    && !pm.isPackageFrozen(app.info.packageName, app.uid,
+                                            app.userId);
+                        }
+                        procs.add(new Pair<>(app, shouldAllowRestart));
                     }
                     continue;
                 }
@@ -2818,6 +2830,8 @@
                     continue;
                 }
 
+                boolean shouldAllowRestart = false;
+
                 // If no package is specified, we call all processes under the
                 // give user id.
                 if (packageName == null) {
@@ -2839,9 +2853,16 @@
                     if (userId != UserHandle.USER_ALL && app.userId != userId) {
                         continue;
                     }
-                    if (!app.getPkgList().containsKey(packageName) && !isDep) {
+                    final boolean isInPkgList = app.getPkgList().containsKey(packageName);
+                    if (!isInPkgList && !isDep) {
                         continue;
                     }
+                    if (!isInPkgList && isDep && !uninstalling && app.info != null
+                            && !pm.isPackageFrozen(app.info.packageName, app.uid, app.userId)) {
+                        // This package has a dependency on the given package being stopped,
+                        // while it's not being frozen nor uninstalled, allow to restart it.
+                        shouldAllowRestart = true;
+                    }
                 }
 
                 // Process has passed all conditions, kill it!
@@ -2851,14 +2872,15 @@
                 if (setRemoved) {
                     app.setRemoved(true);
                 }
-                procs.add(app);
+                procs.add(new Pair<>(app, shouldAllowRestart));
             }
         }
 
         int N = procs.size();
         for (int i=0; i<N; i++) {
-            removeProcessLocked(procs.get(i), callerWillRestart, allowRestart,
-                    reasonCode, subReason, reason);
+            final Pair<ProcessRecord, Boolean> proc = procs.get(i);
+            removeProcessLocked(proc.first, callerWillRestart, allowRestart || proc.second,
+                     reasonCode, subReason, reason);
         }
         killAppZygotesLocked(packageName, appId, userId, false /* force */);
         mService.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_PROCESS_END);
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 7341e74..358263d 100644
--- a/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
+++ b/services/core/java/com/android/server/biometrics/sensors/AuthenticationClient.java
@@ -503,10 +503,14 @@
     protected int getShowOverlayReason() {
         if (isKeyguard()) {
             return BiometricOverlayConstants.REASON_AUTH_KEYGUARD;
-        } else if (isSettings()) {
-            return BiometricOverlayConstants.REASON_AUTH_SETTINGS;
         } else if (isBiometricPrompt()) {
+            // BP reason always takes precedent over settings, since callers from within
+            // settings can always invoke BP.
             return BiometricOverlayConstants.REASON_AUTH_BP;
+        } else if (isSettings()) {
+            // This is pretty much only for FingerprintManager#authenticate usage from
+            // FingerprintSettings.
+            return BiometricOverlayConstants.REASON_AUTH_SETTINGS;
         } else {
             return BiometricOverlayConstants.REASON_AUTH_OTHER;
         }
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 7ed897d..7455cec 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -266,7 +266,6 @@
 import com.android.internal.logging.MetricsLogger;
 import com.android.internal.logging.nano.MetricsProto;
 import com.android.internal.logging.nano.MetricsProto.MetricsEvent;
-import com.android.internal.messages.nano.SystemMessageProto;
 import com.android.internal.notification.SystemNotificationChannels;
 import com.android.internal.os.BackgroundThread;
 import com.android.internal.os.SomeArgs;
@@ -615,12 +614,6 @@
     private NotificationRecordLogger mNotificationRecordLogger;
     private InstanceIdSequence mNotificationInstanceIdSequence;
     private Set<String> mMsgPkgsAllowedAsConvos = new HashSet();
-    protected static final String ACTION_ENABLE_NAS =
-            "android.server.notification.action.ENABLE_NAS";
-    protected static final String ACTION_DISABLE_NAS =
-            "android.server.notification.action.DISABLE_NAS";
-    protected static final String ACTION_LEARNMORE_NAS =
-            "android.server.notification.action.LEARNMORE_NAS";
 
     static class Archive {
         final SparseArray<Boolean> mEnabled;
@@ -755,97 +748,27 @@
         setDefaultAssistantForUser(userId);
     }
 
-    protected void migrateDefaultNASShowNotificationIfNecessary() {
+    protected void migrateDefaultNAS() {
         final List<UserInfo> activeUsers = mUm.getUsers();
         for (UserInfo userInfo : activeUsers) {
             int userId = userInfo.getUserHandle().getIdentifier();
             if (isNASMigrationDone(userId) || mUm.isManagedProfile(userId)) {
                 continue;
             }
-            if (mAssistants.hasUserSet(userId)) {
-                ComponentName defaultFromConfig = mAssistants.getDefaultFromConfig();
-                List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
-                if (allowedComponents.size() == 0) {
-                    setNASMigrationDone(userId);
-                    mAssistants.clearDefaults();
-                    continue;
-                } else if (allowedComponents.contains(defaultFromConfig)) {
-                    setNASMigrationDone(userId);
-                    mAssistants.resetDefaultFromConfig();
-                    continue;
-                }
-                // TODO(b/192450820): re-enable when "user set" isn't over triggering
-                //User selected different NAS, need onboarding
-                /*enqueueNotificationInternal(getContext().getPackageName(),
-                        getContext().getOpPackageName(), Binder.getCallingUid(),
-                        Binder.getCallingPid(), TAG,
-                        SystemMessageProto.SystemMessage.NOTE_NAS_UPGRADE,
-                        createNASUpgradeNotification(userId), userId);*/
+            List<ComponentName> allowedComponents = mAssistants.getAllowedComponents(userId);
+            if (allowedComponents.size() == 0) { // user set to none
+                Slog.d(TAG, "NAS Migration: user set to none, disable new NAS setting");
+                setNASMigrationDone(userId);
+                mAssistants.clearDefaults();
+            } else {
+                Slog.d(TAG, "Reset NAS setting and migrate to new default");
+                resetAssistantUserSet(userId);
+                // migrate to new default and set migration done
+                mAssistants.resetDefaultAssistantsIfNecessary();
             }
         }
     }
 
-    protected Notification createNASUpgradeNotification(int userId) {
-        final Bundle extras = new Bundle();
-        extras.putString(Notification.EXTRA_SUBSTITUTE_APP_NAME,
-                getContext().getResources().getString(R.string.global_action_settings));
-        int title = R.string.nas_upgrade_notification_title;
-        int content = R.string.nas_upgrade_notification_content;
-
-        Intent onboardingIntent = new Intent(Settings.ACTION_NOTIFICATION_ASSISTANT_SETTINGS);
-        onboardingIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
-
-        Intent enableIntent = new Intent(ACTION_ENABLE_NAS);
-        enableIntent.putExtra(Intent.EXTRA_USER_ID, userId);
-        PendingIntent enableNASPendingIntent = PendingIntent.getBroadcast(getContext(),
-                0, enableIntent, PendingIntent.FLAG_IMMUTABLE);
-
-        Intent disableIntent = new Intent(ACTION_DISABLE_NAS);
-        disableIntent.putExtra(Intent.EXTRA_USER_ID, userId);
-        PendingIntent disableNASPendingIntent = PendingIntent.getBroadcast(getContext(),
-                0, disableIntent, PendingIntent.FLAG_IMMUTABLE);
-
-        Intent learnMoreIntent = new Intent(ACTION_LEARNMORE_NAS);
-        learnMoreIntent.putExtra(Intent.EXTRA_USER_ID, userId);
-        PendingIntent learnNASPendingIntent = PendingIntent.getBroadcast(getContext(),
-                0, learnMoreIntent, PendingIntent.FLAG_IMMUTABLE);
-
-        Notification.Action enableNASAction = new Notification.Action.Builder(
-                0,
-                getContext().getResources().getString(
-                        R.string.nas_upgrade_notification_enable_action),
-                enableNASPendingIntent).build();
-
-        Notification.Action disableNASAction = new Notification.Action.Builder(
-                0,
-                getContext().getResources().getString(
-                        R.string.nas_upgrade_notification_disable_action),
-                disableNASPendingIntent).build();
-
-        Notification.Action learnMoreNASAction = new Notification.Action.Builder(
-                0,
-                getContext().getResources().getString(
-                        R.string.nas_upgrade_notification_learn_more_action),
-                learnNASPendingIntent).build();
-
-
-        return new Notification.Builder(getContext(), SystemNotificationChannels.SYSTEM_CHANGES)
-                .setAutoCancel(false)
-                .setOngoing(true)
-                .setTicker(getContext().getResources().getString(title))
-                .setSmallIcon(R.drawable.ic_settings_24dp)
-                .setContentTitle(getContext().getResources().getString(title))
-                .setContentText(getContext().getResources().getString(content))
-                .setContentIntent(PendingIntent.getActivity(getContext(), 0, onboardingIntent,
-                        PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE))
-                .setLocalOnly(true)
-                .setStyle(new Notification.BigTextStyle())
-                .addAction(enableNASAction)
-                .addAction(disableNASAction)
-                .addAction(learnMoreNASAction)
-                .build();
-    }
-
     @VisibleForTesting
     void setNASMigrationDone(int baseUserId) {
         for (int profileId : mUm.getProfileIds(baseUserId, false)) {
@@ -1861,41 +1784,6 @@
         }
     };
 
-    private final BroadcastReceiver mNASIntentReceiver = new BroadcastReceiver() {
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            final String action = intent.getAction();
-            int userId = intent.getIntExtra(Intent.EXTRA_USER_ID, -1);
-            if (ACTION_ENABLE_NAS.equals(action)) {
-                mAssistants.resetDefaultFromConfig();
-                setNotificationAssistantAccessGrantedForUserInternal(
-                        CollectionUtils.firstOrNull(mAssistants.getDefaultComponents()),
-                        userId, true, true);
-                setNASMigrationDone(userId);
-                cancelNotificationInternal(getContext().getPackageName(),
-                        getContext().getOpPackageName(), Binder.getCallingUid(),
-                        Binder.getCallingPid(), TAG,
-                        SystemMessageProto.SystemMessage.NOTE_NAS_UPGRADE, userId);
-            } else if (ACTION_DISABLE_NAS.equals(action)) {
-                //Set default NAS to be null if user selected none during migration
-                mAssistants.clearDefaults();
-                setNotificationAssistantAccessGrantedForUserInternal(
-                        null, userId, true, true);
-                setNASMigrationDone(userId);
-                cancelNotificationInternal(getContext().getPackageName(),
-                        getContext().getOpPackageName(), Binder.getCallingUid(),
-                        Binder.getCallingPid(), TAG,
-                        SystemMessageProto.SystemMessage.NOTE_NAS_UPGRADE, userId);
-            } else if (ACTION_LEARNMORE_NAS.equals(action)) {
-                Intent i = new Intent(getContext(), NASLearnMoreActivity.class);
-                i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-                getContext().sendBroadcastAsUser(
-                        new Intent(Intent.ACTION_CLOSE_SYSTEM_DIALOGS), UserHandle.of(userId));
-                getContext().startActivity(i);
-            }
-        }
-    };
-
     private final class SettingsObserver extends ContentObserver {
         private final Uri NOTIFICATION_BADGING_URI
                 = Settings.Secure.getUriFor(Settings.Secure.NOTIFICATION_BADGING);
@@ -2407,12 +2295,6 @@
 
         IntentFilter localeChangedFilter = new IntentFilter(Intent.ACTION_LOCALE_CHANGED);
         getContext().registerReceiver(mLocaleChangeReceiver, localeChangedFilter);
-
-        IntentFilter nasFilter = new IntentFilter();
-        nasFilter.addAction(ACTION_ENABLE_NAS);
-        nasFilter.addAction(ACTION_DISABLE_NAS);
-        nasFilter.addAction(ACTION_LEARNMORE_NAS);
-        getContext().registerReceiver(mNASIntentReceiver, nasFilter);
     }
 
     /**
@@ -2424,7 +2306,6 @@
         getContext().unregisterReceiver(mNotificationTimeoutReceiver);
         getContext().unregisterReceiver(mRestoreReceiver);
         getContext().unregisterReceiver(mLocaleChangeReceiver);
-        getContext().unregisterReceiver(mNASIntentReceiver);
 
         if (mDeviceConfigChangedListener != null) {
             DeviceConfig.removeOnPropertiesChangedListener(mDeviceConfigChangedListener);
@@ -2691,7 +2572,7 @@
             mConditionProviders.onBootPhaseAppsCanStart();
             mHistoryManager.onBootPhaseAppsCanStart();
             registerDeviceConfigChange();
-            migrateDefaultNASShowNotificationIfNecessary();
+            migrateDefaultNAS();
         } else if (phase == SystemService.PHASE_ACTIVITY_MANAGER_READY) {
             mSnoozeHelper.scheduleRepostsForPersistedNotifications(System.currentTimeMillis());
         }
@@ -5229,10 +5110,6 @@
         public void setNASMigrationDoneAndResetDefault(int userId, boolean loadFromConfig) {
             checkCallerIsSystem();
             setNASMigrationDone(userId);
-            cancelNotificationInternal(getContext().getPackageName(),
-                    getContext().getOpPackageName(), Binder.getCallingUid(),
-                    Binder.getCallingPid(), TAG,
-                    SystemMessageProto.SystemMessage.NOTE_NAS_UPGRADE, userId);
             if (loadFromConfig) {
                 mAssistants.resetDefaultFromConfig();
             } else {
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b469a80..393d101 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -160,6 +160,7 @@
 import static com.android.server.wm.ActivityRecordProto.NUM_INTERESTING_WINDOWS;
 import static com.android.server.wm.ActivityRecordProto.PIP_AUTO_ENTER_ENABLED;
 import static com.android.server.wm.ActivityRecordProto.PROC_ID;
+import static com.android.server.wm.ActivityRecordProto.PROVIDES_MAX_BOUNDS;
 import static com.android.server.wm.ActivityRecordProto.REPORTED_DRAWN;
 import static com.android.server.wm.ActivityRecordProto.REPORTED_VISIBLE;
 import static com.android.server.wm.ActivityRecordProto.STARTING_DISPLAYED;
@@ -261,6 +262,7 @@
 import android.content.LocusId;
 import android.content.pm.ActivityInfo;
 import android.content.pm.ApplicationInfo;
+import android.content.pm.ConstrainDisplayApisConfig;
 import android.content.pm.PackageManager;
 import android.content.res.CompatibilityInfo;
 import android.content.res.Configuration;
@@ -596,6 +598,8 @@
      */
     private CompatDisplayInsets mCompatDisplayInsets;
 
+    private static ConstrainDisplayApisConfig sConstrainDisplayApisConfig;
+
     boolean pendingVoiceInteractionStart;   // Waiting for activity-invoked voice session
     IVoiceInteractionSession voiceSession;  // Voice interaction session for this activity
 
@@ -1162,8 +1166,10 @@
             if (info.configChanges != 0) {
                 pw.println(prefix + "configChanges=0x" + Integer.toHexString(info.configChanges));
             }
-            pw.println(prefix + "neverSandboxDisplayApis=" + info.neverSandboxDisplayApis());
-            pw.println(prefix + "alwaysSandboxDisplayApis=" + info.alwaysSandboxDisplayApis());
+            pw.println(prefix + "neverSandboxDisplayApis=" + info.neverSandboxDisplayApis(
+                    sConstrainDisplayApisConfig));
+            pw.println(prefix + "alwaysSandboxDisplayApis=" + info.alwaysSandboxDisplayApis(
+                    sConstrainDisplayApisConfig));
         }
         if (mLastParentBeforePip != null) {
             pw.println(prefix + "lastParentTaskIdBeforePip=" + mLastParentBeforePip.mTaskId);
@@ -1769,6 +1775,10 @@
             info.windowLayout.windowLayoutAffinity =
                     uid + ":" + info.windowLayout.windowLayoutAffinity;
         }
+        // Initialize once, when we know all system services are available.
+        if (sConstrainDisplayApisConfig == null) {
+            sConstrainDisplayApisConfig = new ConstrainDisplayApisConfig();
+        }
         stateNotNeeded = (aInfo.flags & FLAG_STATE_NOT_NEEDED) != 0;
         nonLocalizedLabel = aInfo.nonLocalizedLabel;
         labelRes = aInfo.labelRes;
@@ -7465,8 +7475,8 @@
                                 + "should create compatDisplayInsets = %s",
                         getUid(),
                         mTmpBounds,
-                        info.neverSandboxDisplayApis(),
-                        info.alwaysSandboxDisplayApis(),
+                        info.neverSandboxDisplayApis(sConstrainDisplayApisConfig),
+                        info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig),
                         !matchParentBounds(),
                         mCompatDisplayInsets != null,
                         shouldCreateCompatDisplayInsets());
@@ -8027,11 +8037,11 @@
             return false;
         }
         // Never apply sandboxing to an app that should be explicitly excluded from the config.
-        if (info != null && info.neverSandboxDisplayApis()) {
+        if (info.neverSandboxDisplayApis(sConstrainDisplayApisConfig)) {
             return false;
         }
         // Always apply sandboxing to an app that should be explicitly included from the config.
-        if (info != null && info.alwaysSandboxDisplayApis()) {
+        if (info.alwaysSandboxDisplayApis(sConstrainDisplayApisConfig)) {
             return true;
         }
         // Max bounds should be sandboxed when an activity should have compatDisplayInsets, and it
@@ -9047,6 +9057,9 @@
         proto.write(PIP_AUTO_ENTER_ENABLED, pictureInPictureArgs.isAutoEnterEnabled());
         proto.write(IN_SIZE_COMPAT_MODE, inSizeCompatMode());
         proto.write(MIN_ASPECT_RATIO, getMinAspectRatio());
+        // Only record if max bounds sandboxing is applied, if the caller has the necessary
+        // permission to access the device configs.
+        proto.write(PROVIDES_MAX_BOUNDS, providesMaxBounds());
     }
 
     @Override
diff --git a/services/core/java/com/android/server/wm/ActivityStarter.java b/services/core/java/com/android/server/wm/ActivityStarter.java
index 2cf23c5..436a325 100644
--- a/services/core/java/com/android/server/wm/ActivityStarter.java
+++ b/services/core/java/com/android/server/wm/ActivityStarter.java
@@ -72,6 +72,8 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerService.ANIMATE;
+import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
+import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
 import static com.android.server.wm.ActivityTaskSupervisor.DEFER_RESUME;
 import static com.android.server.wm.ActivityTaskSupervisor.ON_TOP;
 import static com.android.server.wm.ActivityTaskSupervisor.PRESERVE_WINDOWS;
@@ -1275,7 +1277,7 @@
 
         // This is used to block background activity launch even if the app is still
         // visible to user after user clicking home button.
-        final boolean appSwitchAllowed = mService.getBalAppSwitchesAllowed();
+        final int appSwitchState = mService.getBalAppSwitchesState();
 
         // don't abort if the callingUid has a visible window or is a persistent system process
         final int callingUidProcState = mService.mActiveUids.getUidState(callingUid);
@@ -1288,7 +1290,9 @@
 
         // Normal apps with visible app window will be allowed to start activity if app switching
         // is allowed, or apps like live wallpaper with non app visible window will be allowed.
-        if (((appSwitchAllowed || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
+        final boolean appSwitchAllowedOrFg =
+                appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY;
+        if (((appSwitchAllowedOrFg || mService.mActiveUids.hasNonAppVisibleWindow(callingUid))
                 && callingUidHasAnyVisibleWindow)
                 || isCallingUidPersistentSystemProcess) {
             if (DEBUG_ACTIVITY_STARTS) {
@@ -1398,7 +1402,7 @@
         // don't abort if the callerApp or other processes of that uid are allowed in any way
         if (callerApp != null) {
             // first check the original calling process
-            if (callerApp.areBackgroundActivityStartsAllowed(appSwitchAllowed)) {
+            if (callerApp.areBackgroundActivityStartsAllowed(appSwitchState)) {
                 if (DEBUG_ACTIVITY_STARTS) {
                     Slog.d(TAG, "Background activity start allowed: callerApp process (pid = "
                             + callerApp.getPid() + ", uid = " + callerAppUid + ") is allowed");
@@ -1412,7 +1416,7 @@
                 for (int i = uidProcesses.size() - 1; i >= 0; i--) {
                     final WindowProcessController proc = uidProcesses.valueAt(i);
                     if (proc != callerApp
-                            && proc.areBackgroundActivityStartsAllowed(appSwitchAllowed)) {
+                            && proc.areBackgroundActivityStartsAllowed(appSwitchState)) {
                         if (DEBUG_ACTIVITY_STARTS) {
                             Slog.d(TAG,
                                     "Background activity start allowed: process " + proc.getPid()
@@ -1426,7 +1430,7 @@
         // anything that has fallen through would currently be aborted
         Slog.w(TAG, "Background activity start [callingPackage: " + callingPackage
                 + "; callingUid: " + callingUid
-                + "; appSwitchAllowed: " + appSwitchAllowed
+                + "; appSwitchState: " + appSwitchState
                 + "; isCallingUidForeground: " + isCallingUidForeground
                 + "; callingUidHasAnyVisibleWindow: " + callingUidHasAnyVisibleWindow
                 + "; callingUidProcState: " + DebugUtils.valueToString(ActivityManager.class,
diff --git a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
index 60a514e..c8227d9 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskManagerService.java
@@ -504,7 +504,27 @@
      * Whether normal application switches are allowed; a call to {@link #stopAppSwitches()
      * disables this.
      */
-    private volatile boolean mAppSwitchesAllowed = true;
+    private volatile int mAppSwitchesState = APP_SWITCH_ALLOW;
+
+    // The duration of resuming foreground app switch from disallow.
+    private static final long RESUME_FG_APP_SWITCH_MS = 500;
+
+    /** App switch is not allowed. */
+    static final int APP_SWITCH_DISALLOW = 0;
+
+    /** App switch is allowed only if the activity launch was requested by a foreground app. */
+    static final int APP_SWITCH_FG_ONLY = 1;
+
+    /** App switch is allowed. */
+    static final int APP_SWITCH_ALLOW = 2;
+
+    @IntDef({
+            APP_SWITCH_DISALLOW,
+            APP_SWITCH_FG_ONLY,
+            APP_SWITCH_ALLOW,
+    })
+    @Retention(RetentionPolicy.SOURCE)
+    @interface AppSwitchState {}
 
     /**
      * Last stop app switches time, apps finished before this time cannot start background activity
@@ -1247,7 +1267,7 @@
             if (topFocusedRootTask != null && topFocusedRootTask.getTopResumedActivity() != null
                     && topFocusedRootTask.getTopResumedActivity().info.applicationInfo.uid
                     == Binder.getCallingUid()) {
-                mAppSwitchesAllowed = true;
+                mAppSwitchesState = APP_SWITCH_ALLOW;
             }
         }
         return pir.sendInner(0, fillInIntent, resolvedType, allowlistToken, null, null,
@@ -2158,8 +2178,8 @@
     /**
      * Return true if app switching is allowed.
      */
-    boolean getBalAppSwitchesAllowed() {
-        return mAppSwitchesAllowed;
+    @AppSwitchState int getBalAppSwitchesState() {
+        return mAppSwitchesState;
     }
 
     /** Register an {@link AnrController} to control the ANR dialog behavior */
@@ -3680,8 +3700,10 @@
     public void stopAppSwitches() {
         mAmInternal.enforceCallingPermission(STOP_APP_SWITCHES, "stopAppSwitches");
         synchronized (mGlobalLock) {
-            mAppSwitchesAllowed = false;
+            mAppSwitchesState = APP_SWITCH_DISALLOW;
             mLastStopAppSwitchesTime = SystemClock.uptimeMillis();
+            mH.removeMessages(H.RESUME_FG_APP_SWITCH_MSG);
+            mH.sendEmptyMessageDelayed(H.RESUME_FG_APP_SWITCH_MSG, RESUME_FG_APP_SWITCH_MS);
         }
     }
 
@@ -3689,7 +3711,8 @@
     public void resumeAppSwitches() {
         mAmInternal.enforceCallingPermission(STOP_APP_SWITCHES, "resumeAppSwitches");
         synchronized (mGlobalLock) {
-            mAppSwitchesAllowed = true;
+            mAppSwitchesState = APP_SWITCH_ALLOW;
+            mH.removeMessages(H.RESUME_FG_APP_SWITCH_MSG);
         }
     }
 
@@ -5170,6 +5193,7 @@
         static final int REPORT_TIME_TRACKER_MSG = 1;
         static final int UPDATE_PROCESS_ANIMATING_STATE = 2;
         static final int END_POWER_MODE_UNKNOWN_VISIBILITY_MSG = 3;
+        static final int RESUME_FG_APP_SWITCH_MSG = 4;
 
         static final int FIRST_ACTIVITY_TASK_MSG = 100;
         static final int FIRST_SUPERVISOR_TASK_MSG = 200;
@@ -5207,6 +5231,14 @@
                     }
                 }
                 break;
+                case RESUME_FG_APP_SWITCH_MSG: {
+                    synchronized (mGlobalLock) {
+                        if (mAppSwitchesState == APP_SWITCH_DISALLOW) {
+                            mAppSwitchesState = APP_SWITCH_FG_ONLY;
+                        }
+                    }
+                }
+                break;
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
index 71a10df..0afd872 100644
--- a/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
+++ b/services/core/java/com/android/server/wm/BackgroundLaunchProcessController.java
@@ -20,6 +20,8 @@
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
 import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
 import static com.android.server.wm.ActivityTaskManagerService.ACTIVITY_BG_START_GRACE_PERIOD_MS;
+import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_ALLOW;
+import static com.android.server.wm.ActivityTaskManagerService.APP_SWITCH_FG_ONLY;
 
 import android.annotation.NonNull;
 import android.annotation.Nullable;
@@ -70,13 +72,13 @@
     }
 
     boolean areBackgroundActivityStartsAllowed(int pid, int uid, String packageName,
-            boolean appSwitchAllowed, boolean isCheckingForFgsStart,
+            int appSwitchState, boolean isCheckingForFgsStart,
             boolean hasActivityInVisibleTask, boolean hasBackgroundActivityStartPrivileges,
             long lastStopAppSwitchesTime, long lastActivityLaunchTime,
             long lastActivityFinishTime) {
         // If app switching is not allowed, we ignore all the start activity grace period
         // exception so apps cannot start itself in onPause() after pressing home button.
-        if (appSwitchAllowed) {
+        if (appSwitchState == APP_SWITCH_ALLOW) {
             // Allow if any activity in the caller has either started or finished very recently, and
             // it must be started or finished after last stop app switches time.
             final long now = SystemClock.uptimeMillis();
@@ -111,7 +113,8 @@
             return true;
         }
         // Allow if the caller has an activity in any foreground task.
-        if (appSwitchAllowed && hasActivityInVisibleTask) {
+        if (hasActivityInVisibleTask
+                && (appSwitchState == APP_SWITCH_ALLOW || appSwitchState == APP_SWITCH_FG_ONLY)) {
             if (DEBUG_ACTIVITY_STARTS) {
                 Slog.d(TAG, "[Process(" + pid
                         + ")] Activity start allowed: process has activity in foreground task");
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index f0a1554..c88dbf7 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -321,6 +321,11 @@
      */
     boolean mInResumeTopActivity = false;
 
+    /**
+     * Used to identify if the activity that is installed from device's system image.
+     */
+    boolean mIsEffectivelySystemApp;
+
     int mCurrentUser;
 
     String affinity;        // The affinity name for this task, or null; may change identity.
@@ -568,13 +573,24 @@
 
             if (r.finishing) return false;
 
-            // Set this as the candidate root since it isn't finishing.
-            mRoot = r;
+            if (mRoot == null || mRoot.finishing) {
+                // Set this as the candidate root since it isn't finishing.
+                mRoot = r;
+            }
 
-            // Only end search if we are ignore relinquishing identity or we are not relinquishing.
-            return ignoreRelinquishIdentity
-                    || mNeverRelinquishIdentity
-                    || (r.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
+            final int uid = mRoot == r ? effectiveUid : r.info.applicationInfo.uid;
+            if (ignoreRelinquishIdentity
+                    || (mRoot.info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0
+                    || (mRoot.info.applicationInfo.uid != Process.SYSTEM_UID
+                    && !mRoot.info.applicationInfo.isSystemApp()
+                    && mRoot.info.applicationInfo.uid != uid)) {
+                // No need to relinquish identity, end search.
+                return true;
+            }
+
+            // Relinquish to next activity
+            mRoot = r;
+            return false;
         }
     }
 
@@ -999,7 +1015,15 @@
      * @param info The activity info which could be different from {@code r.info} if set.
      */
     void setIntent(ActivityRecord r, @Nullable Intent intent, @Nullable ActivityInfo info) {
-        if (this.intent == null || !mNeverRelinquishIdentity) {
+        boolean updateIdentity = false;
+        if (this.intent == null) {
+            updateIdentity = true;
+        } else if (!mNeverRelinquishIdentity) {
+            final ActivityInfo activityInfo = info != null ? info : r.info;
+            updateIdentity = (effectiveUid == Process.SYSTEM_UID || mIsEffectivelySystemApp
+                    || effectiveUid == activityInfo.applicationInfo.uid);
+        }
+        if (updateIdentity) {
             mCallingUid = r.launchedFromUid;
             mCallingPackage = r.launchedFromPackage;
             mCallingFeatureId = r.launchedFromFeatureId;
@@ -1012,14 +1036,7 @@
     private void setIntent(Intent _intent, ActivityInfo info) {
         if (!isLeafTask()) return;
 
-        if (info.applicationInfo.uid == Process.SYSTEM_UID
-                || info.applicationInfo.isSystemApp()) {
-            // Only allow the apps that pre-installed on the system image to apply
-            // relinquishTaskIdentity
-            mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
-        } else {
-            mNeverRelinquishIdentity = true;
-        }
+        mNeverRelinquishIdentity = (info.flags & FLAG_RELINQUISH_TASK_IDENTITY) == 0;
         affinity = info.taskAffinity;
         if (intent == null) {
             // If this task already has an intent associated with it, don't set the root
@@ -1028,6 +1045,7 @@
             rootAffinity = affinity;
         }
         effectiveUid = info.applicationInfo.uid;
+        mIsEffectivelySystemApp = info.applicationInfo.isSystemApp();
         stringName = null;
 
         if (info.targetActivity == null) {
@@ -3141,14 +3159,6 @@
     }
 
     @Override
-    boolean fillsParent() {
-        // From the perspective of policy, we still want to report that this task fills parent
-        // in fullscreen windowing mode even it doesn't match parent bounds because there will be
-        // letterbox around its real content.
-        return getWindowingMode() == WINDOWING_MODE_FULLSCREEN || matchParentBounds();
-    }
-
-    @Override
     void forAllLeafTasks(Consumer<Task> callback, boolean traverseTopToBottom) {
         final int count = mChildren.size();
         boolean isLeafTask = true;
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 7bcf8a9f..ef143c2 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -2346,6 +2346,14 @@
         return true;
     }
 
+    @Override
+    boolean fillsParent() {
+        // From the perspective of policy, we still want to report that this task fills parent
+        // in fullscreen windowing mode even it doesn't match parent bounds because there will be
+        // letterbox around its real content.
+        return getWindowingMode() == WINDOWING_MODE_FULLSCREEN || matchParentBounds();
+    }
+
     boolean dump(String prefix, FileDescriptor fd, PrintWriter pw, boolean dumpAll,
             boolean dumpClient, String dumpPackage, final boolean needSep, Runnable header) {
         boolean printed = false;
diff --git a/services/core/java/com/android/server/wm/WindowContextListenerController.java b/services/core/java/com/android/server/wm/WindowContextListenerController.java
index cc52713..7956a11 100644
--- a/services/core/java/com/android/server/wm/WindowContextListenerController.java
+++ b/services/core/java/com/android/server/wm/WindowContextListenerController.java
@@ -173,7 +173,7 @@
 
     @VisibleForTesting
     class WindowContextListenerImpl implements WindowContainerListener {
-        @NonNull private final IBinder mClientToken;
+        @NonNull private final IWindowToken mClientToken;
         private final int mOwnerUid;
         @NonNull private WindowContainer<?> mContainer;
         /**
@@ -193,7 +193,7 @@
 
         private WindowContextListenerImpl(IBinder clientToken, WindowContainer<?> container,
                 int ownerUid, @WindowType int type, @Nullable Bundle options) {
-            mClientToken = clientToken;
+            mClientToken = IWindowToken.Stub.asInterface(clientToken);
             mContainer = Objects.requireNonNull(container);
             mOwnerUid = ownerUid;
             mType = type;
@@ -205,7 +205,7 @@
                 mDeathRecipient = deathRecipient;
             } catch (RemoteException e) {
                 ProtoLog.e(WM_ERROR, "Could not register window container listener token=%s, "
-                        + "container=%s", mClientToken, mContainer);
+                        + "container=%s", clientToken, mContainer);
             }
         }
 
@@ -228,17 +228,17 @@
         }
 
         private void register() {
+            final IBinder token = mClientToken.asBinder();
             if (mDeathRecipient == null) {
-                throw new IllegalStateException("Invalid client token: " + mClientToken);
+                throw new IllegalStateException("Invalid client token: " + token);
             }
-            mListeners.putIfAbsent(mClientToken, this);
+            mListeners.putIfAbsent(token, this);
             mContainer.registerWindowContainerListener(this);
-            reportConfigToWindowTokenClient();
         }
 
         private void unregister() {
             mContainer.unregisterWindowContainerListener(this);
-            mListeners.remove(mClientToken);
+            mListeners.remove(mClientToken.asBinder());
         }
 
         private void clear() {
@@ -258,19 +258,24 @@
 
         private void reportConfigToWindowTokenClient() {
             if (mDeathRecipient == null) {
-                throw new IllegalStateException("Invalid client token: " + mClientToken);
+                throw new IllegalStateException("Invalid client token: " + mClientToken.asBinder());
+            }
+            final DisplayContent dc = mContainer.getDisplayContent();
+            if (!dc.isReady()) {
+                // Do not report configuration when booting. The latest configuration will be sent
+                // when WindowManagerService#displayReady().
+                return;
             }
             // If the display of window context associated window container is suspended, don't
             // report the configuration update. Note that we still dispatch the configuration update
             // to WindowProviderService to make it compatible with Service#onConfigurationChanged.
             // Service always receives #onConfigurationChanged callback regardless of display state.
-            if (!isWindowProviderService(mOptions)
-                    && isSuspendedState(mContainer.getDisplayContent().getDisplayInfo().state)) {
+            if (!isWindowProviderService(mOptions) && isSuspendedState(dc.getDisplayInfo().state)) {
                 mHasPendingConfiguration = true;
                 return;
             }
             final Configuration config = mContainer.getConfiguration();
-            final int displayId = mContainer.getDisplayContent().getDisplayId();
+            final int displayId = dc.getDisplayId();
             if (mLastReportedConfig == null) {
                 mLastReportedConfig = new Configuration();
             }
@@ -282,9 +287,8 @@
             mLastReportedConfig.setTo(config);
             mLastReportedDisplay = displayId;
 
-            IWindowToken windowTokenClient = IWindowToken.Stub.asInterface(mClientToken);
             try {
-                windowTokenClient.onConfigurationChanged(config, displayId);
+                mClientToken.onConfigurationChanged(config, displayId);
             } catch (RemoteException e) {
                 ProtoLog.w(WM_ERROR, "Could not report config changes to the window token client.");
             }
@@ -294,7 +298,7 @@
         @Override
         public void onRemoved() {
             if (mDeathRecipient == null) {
-                throw new IllegalStateException("Invalid client token: " + mClientToken);
+                throw new IllegalStateException("Invalid client token: " + mClientToken.asBinder());
             }
             final WindowToken windowToken = mContainer.asWindowToken();
             if (windowToken != null && windowToken.isFromClient()) {
@@ -312,9 +316,8 @@
                 }
             }
             mDeathRecipient.unlinkToDeath();
-            IWindowToken windowTokenClient = IWindowToken.Stub.asInterface(mClientToken);
             try {
-                windowTokenClient.onWindowTokenRemoved();
+                mClientToken.onWindowTokenRemoved();
             } catch (RemoteException e) {
                 ProtoLog.w(WM_ERROR, "Could not report token removal to the window token client.");
             }
@@ -323,7 +326,7 @@
 
         @Override
         public String toString() {
-            return "WindowContextListenerImpl{clientToken=" + mClientToken + ", "
+            return "WindowContextListenerImpl{clientToken=" + mClientToken.asBinder() + ", "
                     + "container=" + mContainer + "}";
         }
 
@@ -337,11 +340,11 @@
             }
 
             void linkToDeath() throws RemoteException {
-                mClientToken.linkToDeath(this, 0);
+                mClientToken.asBinder().linkToDeath(this, 0);
             }
 
             void unlinkToDeath() {
-                mClientToken.unlinkToDeath(this, 0);
+                mClientToken.asBinder().unlinkToDeath(this, 0);
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index 1cfbe07..3ccb06c 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -512,19 +512,19 @@
      */
     @HotPath(caller = HotPath.START_SERVICE)
     public boolean areBackgroundFgsStartsAllowed() {
-        return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesAllowed(),
+        return areBackgroundActivityStartsAllowed(mAtm.getBalAppSwitchesState(),
                 true /* isCheckingForFgsStart */);
     }
 
-    boolean areBackgroundActivityStartsAllowed(boolean appSwitchAllowed) {
-        return areBackgroundActivityStartsAllowed(appSwitchAllowed,
+    boolean areBackgroundActivityStartsAllowed(int appSwitchState) {
+        return areBackgroundActivityStartsAllowed(appSwitchState,
                 false /* isCheckingForFgsStart */);
     }
 
-    private boolean areBackgroundActivityStartsAllowed(boolean appSwitchAllowed,
+    private boolean areBackgroundActivityStartsAllowed(int appSwitchState,
             boolean isCheckingForFgsStart) {
         return mBgLaunchController.areBackgroundActivityStartsAllowed(mPid, mUid, mInfo.packageName,
-                appSwitchAllowed, isCheckingForFgsStart, hasActivityInVisibleTask(),
+                appSwitchState, isCheckingForFgsStart, hasActivityInVisibleTask(),
                 mInstrumentingWithBackgroundActivityStartPrivileges,
                 mAtm.getLastStopAppSwitchesTime(),
                 mLastActivityLaunchTime, mLastActivityFinishTime);
diff --git a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
index 49d5e50..d3353cd 100644
--- a/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
+++ b/services/people/java/com/android/server/people/data/ConversationStatusExpirationBroadcastReceiver.java
@@ -31,6 +31,7 @@
 
 import com.android.server.LocalServices;
 import com.android.server.people.PeopleServiceInternal;
+import com.android.server.pm.PackageManagerService;
 
 /**
  * If a {@link ConversationStatus} is added to the system with an expiration time, remove that
@@ -50,6 +51,7 @@
             final PendingIntent pi = PendingIntent.getBroadcast(context,
                     REQUEST_CODE,
                     new Intent(ACTION)
+                            .setPackage(PackageManagerService.PLATFORM_PACKAGE_NAME)
                             .setData(new Uri.Builder().scheme(SCHEME)
                                     .appendPath(getKey(userId, pkg, conversationId, status))
                                     .build())
diff --git a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
index 18f1267..0dd4f5b 100644
--- a/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
+++ b/services/tests/mockingservicestests/src/com/android/server/am/MockingOomAdjusterTests.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static android.app.ActivityManager.PROCESS_CAPABILITY_ALL;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_FOREGROUND_SERVICE;
 import static android.app.ActivityManager.PROCESS_STATE_BOUND_TOP;
 import static android.app.ActivityManager.PROCESS_STATE_CACHED_ACTIVITY;
@@ -1854,6 +1855,36 @@
 
     @SuppressWarnings("GuardedBy")
     @Test
+    public void testUpdateOomAdj_DoAll_BoundByPersService_Cycle_Branch_Capability() {
+        ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
+                MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
+        ProcessRecord client = spy(makeDefaultProcessRecord(MOCKAPP2_PID, MOCKAPP2_UID,
+                MOCKAPP2_PROCESSNAME, MOCKAPP2_PACKAGENAME, false));
+        bindService(app, client, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        ProcessRecord client2 = spy(makeDefaultProcessRecord(MOCKAPP3_PID, MOCKAPP3_UID,
+                MOCKAPP3_PROCESSNAME, MOCKAPP3_PACKAGENAME, false));
+        bindService(client, client2, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        bindService(client2, app, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        ProcessRecord client3 = spy(makeDefaultProcessRecord(MOCKAPP4_PID, MOCKAPP4_UID,
+                MOCKAPP4_PROCESSNAME, MOCKAPP4_PACKAGENAME, false));
+        client3.mState.setMaxAdj(PERSISTENT_PROC_ADJ);
+        bindService(app, client3, null, Context.BIND_INCLUDE_CAPABILITIES, mock(IBinder.class));
+        ArrayList<ProcessRecord> lru = sService.mProcessList.getLruProcessesLOSP();
+        lru.clear();
+        lru.add(app);
+        lru.add(client);
+        lru.add(client2);
+        lru.add(client3);
+        sService.mWakefulness.set(PowerManagerInternal.WAKEFULNESS_AWAKE);
+        sService.mOomAdjuster.updateOomAdjLocked(OomAdjuster.OOM_ADJ_REASON_NONE);
+
+        assertEquals(PROCESS_CAPABILITY_ALL, client.mState.getSetCapability());
+        assertEquals(PROCESS_CAPABILITY_ALL, client2.mState.getSetCapability());
+        assertEquals(PROCESS_CAPABILITY_ALL, app.mState.getSetCapability());
+    }
+
+    @SuppressWarnings("GuardedBy")
+    @Test
     public void testUpdateOomAdj_DoAll_Provider_Cycle_Branch_2() {
         ProcessRecord app = spy(makeDefaultProcessRecord(MOCKAPP_PID, MOCKAPP_UID,
                 MOCKAPP_PROCESSNAME, MOCKAPP_PACKAGENAME, false));
diff --git a/services/tests/servicestests/AndroidTest.xml b/services/tests/servicestests/AndroidTest.xml
index 4c638d6..bb3eb81 100644
--- a/services/tests/servicestests/AndroidTest.xml
+++ b/services/tests/servicestests/AndroidTest.xml
@@ -16,6 +16,13 @@
 <configuration description="Runs Frameworks Services Tests.">
     <option name="test-suite-tag" value="apct" />
     <option name="test-suite-tag" value="apct-instrumentation" />
+
+    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+        <option name="cleanup" value="true" />
+        <option name="push-file" key="SimpleServiceTestApp3.apk"
+                value="/data/local/tmp/cts/content/SimpleServiceTestApp3.apk" />
+    </target_preparer>
+
     <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
         <option name="cleanup-apks" value="true" />
         <option name="install-arg" value="-t" />
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
index 8b6b7c2..1d6ed03 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/SystemActionPerformerTest.java
@@ -296,14 +296,6 @@
     }
 
     @Test
-    public void testToggleSplitScreen_legacy() {
-        setupWithRealContext();
-        mSystemActionPerformer.performSystemAction(
-                AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN);
-        verify(mMockStatusBarManagerInternal).toggleSplitScreen();
-    }
-
-    @Test
     public void testScreenshot_requestsFromScreenshotHelper_legacy() {
         setupWithMockContext();
         mSystemActionPerformer.performSystemAction(
diff --git a/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java b/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
index 10f4c05..e6a8dea 100644
--- a/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
+++ b/services/tests/servicestests/src/com/android/server/am/ServiceRestarterTest.java
@@ -16,6 +16,7 @@
 
 package com.android.server.am;
 
+import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
 
@@ -26,7 +27,9 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.ServiceConnection;
 import android.content.pm.ApplicationInfo;
+import android.os.IBinder;
 import android.os.SystemClock;
 import android.test.suitebuilder.annotation.LargeTest;
 import android.util.Log;
@@ -42,6 +45,8 @@
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * Build/Install/Run:
@@ -69,6 +74,12 @@
     private static final int ACTION_STOPPKG = 8;
     private static final int ACTION_ALL = ACTION_START | ACTION_KILL | ACTION_WAIT | ACTION_STOPPKG;
 
+    private static final String LOCAL_APK_BASE_PATH = "/data/local/tmp/cts/content/";
+    private static final String TEST_PACKAGE3_APK = "SimpleServiceTestApp3.apk";
+    private static final String ACTION_SERVICE_WITH_DEP_PKG =
+            "com.android.servicestests.apps.simpleservicetestapp.ACTION_SERVICE_WITH_DEP_PKG";
+    private static final String EXTRA_TARGET_PACKAGE = "target_package";
+
     private Context mContext;
     private Instrumentation mInstrumentation;
     private int mTestPackage1Uid;
@@ -199,6 +210,83 @@
         return res;
     }
 
+    @Test
+    public void testServiceWithDepPkgStopped() throws Exception {
+        final CountDownLatch[] latchHolder = new CountDownLatch[1];
+        final ServiceConnection conn = new ServiceConnection() {
+            @Override
+            public void onServiceConnected(ComponentName name, IBinder service) {
+                latchHolder[0].countDown();
+            }
+
+            @Override
+            public void onServiceDisconnected(ComponentName name) {
+                latchHolder[0].countDown();
+            }
+        };
+
+        final long timeout = 5_000;
+        final long shortTimeout = 2_000;
+        final Intent intent = new Intent(ACTION_SERVICE_WITH_DEP_PKG);
+        final String testPkg = TEST_PACKAGE2_NAME;
+        final String libPkg = TEST_PACKAGE3_NAME;
+        final String apkPath = LOCAL_APK_BASE_PATH + TEST_PACKAGE3_APK;
+        final ActivityManager am = mContext.getSystemService(ActivityManager.class);
+
+        intent.setComponent(ComponentName.unflattenFromString(testPkg + "/" + TEST_SERVICE_NAME));
+        intent.putExtra(EXTRA_TARGET_PACKAGE, libPkg);
+        try {
+            executeShellCmd("am service-restart-backoff disable " + testPkg);
+
+            latchHolder[0] = new CountDownLatch(1);
+            assertTrue("Unable to bind to test service in " + testPkg,
+                    mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE));
+            assertTrue("Timed out to bind service in " + testPkg,
+                    latchHolder[0].await(timeout, TimeUnit.MILLISECONDS));
+
+            Thread.sleep(shortTimeout);
+            assertTrue(libPkg + " should be a dependency package of " + testPkg,
+                    isPackageDependency(testPkg, libPkg));
+
+            // Force-stop lib package, the test service should be restarted.
+            latchHolder[0] = new CountDownLatch(2);
+            am.forceStopPackage(libPkg);
+            assertTrue("Test service in didn't restart in " + testPkg,
+                    latchHolder[0].await(timeout, TimeUnit.MILLISECONDS));
+
+            Thread.sleep(shortTimeout);
+
+            // Re-install the lib package, the test service should be restarted.
+            latchHolder[0] = new CountDownLatch(2);
+            assertTrue("Unable to install package " + apkPath, installPackage(apkPath));
+            assertTrue("Test service in didn't restart in " + testPkg,
+                    latchHolder[0].await(timeout, TimeUnit.MILLISECONDS));
+
+            Thread.sleep(shortTimeout);
+
+            // Force-stop the service package, the test service should not be restarted.
+            latchHolder[0] = new CountDownLatch(2);
+            am.forceStopPackage(testPkg);
+            assertFalse("Test service should not be restarted in " + testPkg,
+                    latchHolder[0].await(timeout * 2, TimeUnit.MILLISECONDS));
+        } finally {
+            executeShellCmd("am service-restart-backoff enable " + testPkg);
+            mContext.unbindService(conn);
+            am.forceStopPackage(testPkg);
+        }
+    }
+
+    private boolean isPackageDependency(String pkgName, String libPackage) throws Exception {
+        final String output = SystemUtil.runShellCommand("dumpsys activity processes " + pkgName);
+        final Matcher matcher = Pattern.compile("packageDependencies=\\{.*?\\b"
+                + libPackage + "\\b.*?\\}").matcher(output);
+        return matcher.find();
+    }
+
+    private boolean installPackage(String apkPath) throws Exception {
+        return executeShellCmd("pm install -t " + apkPath).equals("Success\n");
+    }
+
     private void startServiceAndWait(String pkgName, MyUidImportanceListener uidListener,
             long timeout) throws Exception {
         final Intent intent = new Intent();
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml b/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml
index 78afb7b..3cc105e 100644
--- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/AndroidManifest.xml
@@ -18,6 +18,7 @@
         package="com.android.servicestests.apps.simpleservicetestapp">
 
     <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
+    <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES" />
 
     <application>
         <service android:name=".SimpleService"
diff --git a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
index 4e981b2..b8654d7 100644
--- a/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
+++ b/services/tests/servicestests/test-apps/SimpleServiceTestApp/src/com/android/servicestests/apps/simpleservicetestapp/SimpleService.java
@@ -17,8 +17,10 @@
 
 import android.app.Service;
 import android.content.ComponentName;
+import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
+import android.content.pm.PackageManager;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.IRemoteCallback;
@@ -33,6 +35,9 @@
     private static final String TEST_CLASS =
             "com.android.servicestests.apps.simpleservicetestapp.SimpleService";
 
+    private static final String ACTION_SERVICE_WITH_DEP_PKG =
+            "com.android.servicestests.apps.simpleservicetestapp.ACTION_SERVICE_WITH_DEP_PKG";
+
     private static final String EXTRA_CALLBACK = "callback";
     private static final String EXTRA_COMMAND = "command";
     private static final String EXTRA_FLAGS = "flags";
@@ -118,6 +123,21 @@
 
     @Override
     public IBinder onBind(Intent intent) {
+        if (ACTION_SERVICE_WITH_DEP_PKG.equals(intent.getAction())) {
+            final String targetPkg = intent.getStringExtra(EXTRA_TARGET_PACKAGE);
+            Log.i(TAG, "SimpleService.onBind: " + ACTION_SERVICE_WITH_DEP_PKG + " " + targetPkg);
+            if (targetPkg != null) {
+                Context pkgContext = null;
+                try {
+                    pkgContext = createPackageContext(targetPkg,
+                            Context.CONTEXT_INCLUDE_CODE | Context.CONTEXT_IGNORE_SECURITY);
+                } catch (PackageManager.NameNotFoundException e) {
+                    Log.e(TAG, "Unable to create package context for " + pkgContext, e);
+                }
+                // This effectively loads the target package as a dependency.
+                pkgContext.getClassLoader();
+            }
+        }
         return mBinder;
     }
 }
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
index 0ad119d..c994b41 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -61,10 +61,6 @@
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEGATIVE;
 import static android.service.notification.NotificationListenerService.Ranking.USER_SENTIMENT_NEUTRAL;
 
-import static com.android.server.notification.NotificationManagerService.ACTION_DISABLE_NAS;
-import static com.android.server.notification.NotificationManagerService.ACTION_ENABLE_NAS;
-import static com.android.server.notification.NotificationManagerService.ACTION_LEARNMORE_NAS;
-
 import static com.google.common.truth.Truth.assertThat;
 
 import static junit.framework.Assert.assertEquals;
@@ -325,7 +321,6 @@
     @Mock
     MultiRateLimiter mToastRateLimiter;
     BroadcastReceiver mPackageIntentReceiver;
-    BroadcastReceiver mNASIntentReceiver;
     NotificationRecordLoggerFake mNotificationRecordLogger = new NotificationRecordLoggerFake();
     private InstanceIdSequence mNotificationInstanceIdSequence = new InstanceIdSequenceFake(
             1 << 30);
@@ -553,14 +548,9 @@
                     && filter.hasAction(Intent.ACTION_PACKAGES_UNSUSPENDED)
                     && filter.hasAction(Intent.ACTION_PACKAGES_SUSPENDED)) {
                 mPackageIntentReceiver = broadcastReceivers.get(i);
-            } else if (filter.hasAction(ACTION_ENABLE_NAS)
-                    && filter.hasAction(ACTION_DISABLE_NAS)
-                    && filter.hasAction(ACTION_LEARNMORE_NAS)) {
-                mNASIntentReceiver = broadcastReceivers.get(i);
             }
         }
         assertNotNull("package intent receiver should exist", mPackageIntentReceiver);
-        assertNotNull("nas intent receiver should exist", mNASIntentReceiver);
 
         // Pretend the shortcut exists
         List<ShortcutInfo> shortcutInfos = new ArrayList<>();
@@ -655,16 +645,6 @@
         mPackageIntentReceiver.onReceive(getContext(), intent);
     }
 
-    private void simulateNASUpgradeBroadcast(String action, int uid) {
-        final Bundle extras = new Bundle();
-        extras.putInt(Intent.EXTRA_USER_ID, uid);
-
-        final Intent intent = new Intent(action);
-        intent.putExtras(extras);
-
-        mNASIntentReceiver.onReceive(getContext(), intent);
-    }
-
     private ArrayMap<Boolean, ArrayList<ComponentName>> generateResetComponentValues() {
         ArrayMap<Boolean, ArrayList<ComponentName>> changed = new ArrayMap<>();
         changed.put(true, new ArrayList<>());
@@ -6042,7 +6022,7 @@
     }
 
     @Test
-    public void testNASSettingUpgrade_userSetNull_noOnBoarding() throws RemoteException {
+    public void testNASSettingUpgrade_userSetNull() throws RemoteException {
         ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component1");
         TestableNotificationManagerService service = spy(mService);
         int userId = 11;
@@ -6055,14 +6035,13 @@
                 .thenReturn(new ArrayList<>());
         when(mAssistants.hasUserSet(userId)).thenReturn(true);
 
-        service.migrateDefaultNASShowNotificationIfNecessary();
+        service.migrateDefaultNAS();
         assertTrue(service.isNASMigrationDone(userId));
-        verify(service, times(0)).createNASUpgradeNotification(eq(userId));
         verify(mAssistants, times(1)).clearDefaults();
     }
 
     @Test
-    public void testNASSettingUpgrade_userSetSameDefault_noOnBoarding() throws RemoteException {
+    public void testNASSettingUpgrade_userSet() throws RemoteException {
         ComponentName defaultComponent = ComponentName.unflattenFromString("package/Component1");
         TestableNotificationManagerService service = spy(mService);
         int userId = 11;
@@ -6075,55 +6054,10 @@
                 .thenReturn(new ArrayList(Arrays.asList(defaultComponent)));
         when(mAssistants.hasUserSet(userId)).thenReturn(true);
 
-        service.migrateDefaultNASShowNotificationIfNecessary();
-        assertTrue(service.isNASMigrationDone(userId));
-        verify(service, times(0)).createNASUpgradeNotification(eq(userId));
-        verify(mAssistants, times(1)).resetDefaultFromConfig();
-    }
-
-    @Test
-    public void testNASSettingUpgrade_userSetDifferentDefault_showOnboarding()
-            throws RemoteException {
-        ComponentName oldDefaultComponent = ComponentName.unflattenFromString("package/Component1");
-        ComponentName newDefaultComponent = ComponentName.unflattenFromString("package/Component2");
-        TestableNotificationManagerService service = spy(mService);
-        int userId = 11;
-        setUsers(new int[]{userId});
-        setNASMigrationDone(false, userId);
-        when(mAssistants.getDefaultComponents())
-                .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
-        when(mAssistants.getDefaultFromConfig())
-                .thenReturn(newDefaultComponent);
-        when(mAssistants.getAllowedComponents(anyInt()))
-                .thenReturn(Arrays.asList(oldDefaultComponent));
-        when(mAssistants.hasUserSet(userId)).thenReturn(true);
-
-        service.migrateDefaultNASShowNotificationIfNecessary();
-        assertFalse(service.isNASMigrationDone(userId));
-        //TODO(b/192450820)
-        //verify(service, times(1)).createNASUpgradeNotification(eq(userId));
-        verify(mAssistants, times(0)).resetDefaultFromConfig();
-
-        //Test user clear data before enable/disable from onboarding notification
-        ArrayMap<Boolean, ArrayList<ComponentName>> changedListeners =
-                generateResetComponentValues();
-        when(mListeners.resetComponents(anyString(), anyInt())).thenReturn(changedListeners);
-        ArrayMap<Boolean, ArrayList<ComponentName>> changes = new ArrayMap<>();
-        changes.put(true, new ArrayList(Arrays.asList(newDefaultComponent)));
-        changes.put(false, new ArrayList());
-        when(mAssistants.resetComponents(anyString(), anyInt())).thenReturn(changes);
-
-        //Clear data
-        service.getBinderService().clearData("package", userId, false);
-        //Test migrate flow again
-        service.migrateDefaultNASShowNotificationIfNecessary();
-
-        //The notification should be still there
-        assertFalse(service.isNASMigrationDone(userId));
-        //TODO(b/192450820)
-        //verify(service, times(2)).createNASUpgradeNotification(eq(userId));
-        verify(mAssistants, times(0)).resetDefaultFromConfig();
-        assertEquals(oldDefaultComponent, service.getApprovedAssistant(userId));
+        service.migrateDefaultNAS();
+        verify(mAssistants, times(1)).setUserSet(userId, false);
+        //resetDefaultAssistantsIfNecessary should invoke from readPolicyXml() and migration
+        verify(mAssistants, times(2)).resetDefaultAssistantsIfNecessary();
     }
 
     @Test
@@ -6143,24 +6077,22 @@
                 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
         when(mAssistants.getDefaultFromConfig())
                 .thenReturn(newDefaultComponent);
-        //User1: need onboarding
+        //User1: set different NAS
         when(mAssistants.getAllowedComponents(userId1))
                 .thenReturn(Arrays.asList(oldDefaultComponent));
-        //User2: no onboarding
+        //User2: set to none
         when(mAssistants.getAllowedComponents(userId2))
-                .thenReturn(Arrays.asList(newDefaultComponent));
+                .thenReturn(new ArrayList<>());
 
         when(mAssistants.hasUserSet(userId1)).thenReturn(true);
         when(mAssistants.hasUserSet(userId2)).thenReturn(true);
 
-        service.migrateDefaultNASShowNotificationIfNecessary();
-        assertFalse(service.isNASMigrationDone(userId1));
+        service.migrateDefaultNAS();
+        // user1's setting get reset
+        verify(mAssistants, times(1)).setUserSet(userId1, false);
+        verify(mAssistants, times(0)).setUserSet(eq(userId2), anyBoolean());
         assertTrue(service.isNASMigrationDone(userId2));
 
-        //TODO(b/192450820)
-        //verify(service, times(1)).createNASUpgradeNotification(any(Integer.class));
-        // only user2's default get updated
-        verify(mAssistants, times(1)).resetDefaultFromConfig();
     }
 
     @Test
@@ -6180,7 +6112,7 @@
                 .thenReturn(new ArraySet<>(Arrays.asList(oldDefaultComponent)));
         when(mAssistants.getDefaultFromConfig())
                 .thenReturn(newDefaultComponent);
-        //Both profiles: need onboarding
+        //Both profiles: set different NAS
         when(mAssistants.getAllowedComponents(userId1))
                 .thenReturn(Arrays.asList(oldDefaultComponent));
         when(mAssistants.getAllowedComponents(userId2))
@@ -6189,13 +6121,9 @@
         when(mAssistants.hasUserSet(userId1)).thenReturn(true);
         when(mAssistants.hasUserSet(userId2)).thenReturn(true);
 
-        service.migrateDefaultNASShowNotificationIfNecessary();
+        service.migrateDefaultNAS();
         assertFalse(service.isNASMigrationDone(userId1));
         assertFalse(service.isNASMigrationDone(userId2));
-
-        // TODO(b/192450820): only user1 get notification
-        //verify(service, times(1)).createNASUpgradeNotification(eq(userId1));
-        //verify(service, times(0)).createNASUpgradeNotification(eq(userId2));
     }
 
 
@@ -6223,79 +6151,16 @@
         //Clear data
         service.getBinderService().clearData("package", userId, false);
         //Test migrate flow again
-        service.migrateDefaultNASShowNotificationIfNecessary();
+        service.migrateDefaultNAS();
 
-        //TODO(b/192450820): The notification should not appear again
-        //verify(service, times(0)).createNASUpgradeNotification(eq(userId));
-        verify(mAssistants, times(0)).resetDefaultFromConfig();
+        //Migration should not happen again
+        verify(mAssistants, times(0)).setUserSet(userId, false);
+        verify(mAssistants, times(0)).clearDefaults();
+        //resetDefaultAssistantsIfNecessary should only invoke once from readPolicyXml()
+        verify(mAssistants, times(1)).resetDefaultAssistantsIfNecessary();
+
     }
 
-    @Test
-    public void testNASUpgradeNotificationDisableBroadcast_multiProfile() {
-        int userId1 = 11;
-        int userId2 = 12;
-        setUsers(new int[]{userId1, userId2});
-        when(mUm.isManagedProfile(userId2)).thenReturn(true);
-        when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1, userId2});
-
-        TestableNotificationManagerService service = spy(mService);
-        setNASMigrationDone(false, userId1);
-        setNASMigrationDone(false, userId2);
-
-        simulateNASUpgradeBroadcast(ACTION_DISABLE_NAS, userId1);
-
-        assertTrue(service.isNASMigrationDone(userId1));
-        assertTrue(service.isNASMigrationDone(userId2));
-        // User disabled the NAS from notification, the default stored in xml should be null
-        // rather than the new default
-        verify(mAssistants, times(1)).clearDefaults();
-        verify(mAssistants, times(0)).resetDefaultFromConfig();
-
-        //TODO(b/192450820):No more notification after disabled
-        //service.migrateDefaultNASShowNotificationIfNecessary();
-        //verify(service, times(0)).createNASUpgradeNotification(anyInt());
-    }
-
-    @Test
-    public void testNASUpgradeNotificationEnableBroadcast_multiUser() {
-        int userId1 = 11;
-        int userId2 = 12;
-        setUsers(new int[]{userId1, userId2});
-        when(mUm.getProfileIds(userId1, false)).thenReturn(new int[]{userId1});
-
-        TestableNotificationManagerService service = spy(mService);
-        setNASMigrationDone(false, userId1);
-        setNASMigrationDone(false, userId2);
-
-        simulateNASUpgradeBroadcast(ACTION_ENABLE_NAS, userId1);
-
-        assertTrue(service.isNASMigrationDone(userId1));
-        assertFalse(service.isNASMigrationDone(userId2));
-        verify(mAssistants, times(1)).resetDefaultFromConfig();
-
-        //TODO(b/192450820)
-        //service.migrateDefaultNASShowNotificationIfNecessary();
-        //verify(service, times(0)).createNASUpgradeNotification(eq(userId1));
-    }
-
-    @Test
-    public void testNASUpgradeNotificationLearnMoreBroadcast() {
-        int userId = 11;
-        setUsers(new int[]{userId});
-        TestableNotificationManagerService service = spy(mService);
-        setNASMigrationDone(false, userId);
-        doNothing().when(mContext).startActivity(any());
-
-        simulateNASUpgradeBroadcast(ACTION_LEARNMORE_NAS, userId);
-
-        verify(mContext, times(1)).startActivity(any(Intent.class));
-        assertFalse(service.isNASMigrationDone(userId));
-        //TODO(b/192450820)
-        //verify(service, times(0)).createNASUpgradeNotification(eq(userId));
-        verify(mAssistants, times(0)).resetDefaultFromConfig();
-    }
-
-
     private void setNASMigrationDone(boolean done, int userId) {
         Settings.Secure.putIntForUser(mContext.getContentResolver(),
                 Settings.Secure.NAS_SETTINGS_UPDATED, done ? 1 : 0, userId);
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
index 8c1045d..bfaa815 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskTests.java
@@ -899,22 +899,21 @@
 
     /**
      * Test that root activity index is reported correctly when looking for the 'effective root' in
-     * case when bottom activity is finishing. Ignore the relinquishing task identity if it's not a
-     * system activity even with the FLAG_RELINQUISH_TASK_IDENTITY.
+     * case when bottom activities are relinquishing task identity or finishing.
      */
     @Test
     public void testFindRootIndex_effectiveRoot_finishingAndRelinquishing() {
-        final Task task = getTestTask();
+        final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final Task task = activity0.getTask();
         // Add extra two activities. Mark the one on the bottom with "relinquishTaskIdentity" and
         // one above as finishing.
-        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
         activity1.finishing = true;
         new ActivityBuilder(mAtm).setTask(task).build();
 
         assertEquals("The first non-finishing activity and non-relinquishing task identity "
-                + "must be reported.", task.getChildAt(0), task.getRootActivity(
+                + "must be reported.", task.getChildAt(2), task.getRootActivity(
                 false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
@@ -934,21 +933,21 @@
     }
 
     /**
-     * Test that the root activity index is reported correctly when looking for the
-     * 'effective root' for the case when all non-system activities have relinquishTaskIdentity set.
+     * Test that the topmost activity index is reported correctly when looking for the
+     * 'effective root' for the case when all activities have relinquishTaskIdentity set.
      */
     @Test
     public void testFindRootIndex_effectiveRoot_relinquishingMultipleActivities() {
-        final Task task = getTestTask();
+        final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final Task task = activity0.getTask();
         // Set relinquishTaskIdentity for all activities in the task
-        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
         activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
 
-        assertEquals("The topmost activity in the task must be reported.", task.getChildAt(0),
-                task.getRootActivity(false /*ignoreRelinquishIdentity*/,
-                        true /*setToBottomIfNone*/));
+        assertEquals("The topmost activity in the task must be reported.",
+                task.getChildAt(task.getChildCount() - 1), task.getRootActivity(
+                        false /*ignoreRelinquishIdentity*/, true /*setToBottomIfNone*/));
     }
 
     /** Test that bottom-most activity is reported in {@link Task#getRootActivity()}. */
@@ -1086,14 +1085,14 @@
     }
 
     /**
-     * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with non-system
-     * activity that relinquishes task identity.
+     * Test {@link ActivityRecord#getTaskForActivityLocked(IBinder, boolean)} with activity that
+     * relinquishes task identity.
      */
     @Test
     public void testGetTaskForActivity_onlyRoot_relinquishTaskIdentity() {
-        final Task task = getTestTask();
+        final ActivityRecord activity0 = new ActivityBuilder(mAtm).setCreateTask(true).build();
+        final Task task = activity0.getTask();
         // Make the current root activity relinquish task identity
-        final ActivityRecord activity0 = task.getBottomMostActivity();
         activity0.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
         // Add an extra activity on top - this will be the new root
         final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
@@ -1102,7 +1101,7 @@
 
         assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity0.appToken, true /* onlyRoot */));
-        assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
+        assertEquals(task.mTaskId,
                 ActivityRecord.getTaskForActivityLocked(activity1.appToken, true /* onlyRoot */));
         assertEquals("No task must be reported for activity that is above root", INVALID_TASK_ID,
                 ActivityRecord.getTaskForActivityLocked(activity2.appToken, true /* onlyRoot */));
@@ -1189,6 +1188,46 @@
         verify(task).setIntent(eq(activity0));
     }
 
+    /**
+     * Test {@link Task#updateEffectiveIntent()} when activity with relinquishTaskIdentity but
+     * another with different uid. This should make the task use the root activity when updating the
+     * intent.
+     */
+    @Test
+    public void testUpdateEffectiveIntent_relinquishingWithDifferentUid() {
+        final ActivityRecord activity0 = new ActivityBuilder(mAtm)
+                .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build();
+        final Task task = activity0.getTask();
+
+        // Add an extra activity on top
+        new ActivityBuilder(mAtm).setUid(11).setTask(task).build();
+
+        spyOn(task);
+        task.updateEffectiveIntent();
+        verify(task).setIntent(eq(activity0));
+    }
+
+    /**
+     * Test {@link Task#updateEffectiveIntent()} with activities set as relinquishTaskIdentity.
+     * This should make the task use the topmost activity when updating the intent.
+     */
+    @Test
+    public void testUpdateEffectiveIntent_relinquishingMultipleActivities() {
+        final ActivityRecord activity0 = new ActivityBuilder(mAtm)
+                .setActivityFlags(FLAG_RELINQUISH_TASK_IDENTITY).setCreateTask(true).build();
+        final Task task = activity0.getTask();
+        // Add an extra activity on top
+        final ActivityRecord activity1 = new ActivityBuilder(mAtm).setTask(task).build();
+        activity1.info.flags |= FLAG_RELINQUISH_TASK_IDENTITY;
+
+        // Add an extra activity on top
+        final ActivityRecord activity2 = new ActivityBuilder(mAtm).setTask(task).build();
+
+        spyOn(task);
+        task.updateEffectiveIntent();
+        verify(task).setIntent(eq(activity2));
+    }
+
     @Test
     public void testSaveLaunchingStateWhenConfigurationChanged() {
         LaunchParamsPersister persister = mAtm.mTaskSupervisor.mLaunchParamsPersister;