Merge "Don't set ImageWallpaper to home only the first time" into udc-dev
diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java
index 785470f..79b68c1 100644
--- a/core/java/android/app/NotificationManager.java
+++ b/core/java/android/app/NotificationManager.java
@@ -571,6 +571,12 @@
      */
     public static final int BUBBLE_PREFERENCE_SELECTED = 2;
 
+    /**
+     * Maximum length of the component name of a registered NotificationListenerService.
+     * @hide
+     */
+    public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500;
+
     @UnsupportedAppUsage
     private static INotificationManager sService;
 
diff --git a/core/java/android/content/pm/PackageInstaller.java b/core/java/android/content/pm/PackageInstaller.java
index 105b38a..4b883cd 100644
--- a/core/java/android/content/pm/PackageInstaller.java
+++ b/core/java/android/content/pm/PackageInstaller.java
@@ -3045,10 +3045,6 @@
          * The update ownership enforcement can only be enabled on initial installation. Set
          * this to {@code true} on package update is a no-op.
          *
-         * Apps may opt themselves out of update ownership by setting the
-         * <a href="https://developer.android.com/guide/topics/manifest/manifest-element.html#allowupdateownership">android:alllowUpdateOwnership</a>
-         * attribute in their manifest to <code>false</code>.
-         *
          * Note: To enable the update ownership enforcement, the installer must have the
          * {@link android.Manifest.permission#ENFORCE_UPDATE_OWNERSHIP ENFORCE_UPDATE_OWNERSHIP}
          * permission.
diff --git a/core/java/android/view/inputmethod/InputMethodManager.java b/core/java/android/view/inputmethod/InputMethodManager.java
index 41ef44e..3cac1e5 100644
--- a/core/java/android/view/inputmethod/InputMethodManager.java
+++ b/core/java/android/view/inputmethod/InputMethodManager.java
@@ -2657,17 +2657,6 @@
             }
         }
 
-        if (windowGainingFocus == null) {
-            windowGainingFocus = view.getWindowToken();
-            if (windowGainingFocus == null) {
-                Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
-                return false;
-            }
-            startInputFlags = getStartInputFlags(view, startInputFlags);
-            softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
-            windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
-        }
-
         // Now we need to get an input connection from the served view.
         // This is complicated in a couple ways: we can't be holding our lock
         // when calling out to the view, and we need to make sure we call into
@@ -2690,6 +2679,17 @@
             return false;
         }
 
+        if (windowGainingFocus == null) {
+            windowGainingFocus = view.getWindowToken();
+            if (windowGainingFocus == null) {
+                Log.e(TAG, "ABORT input: ServedView must be attached to a Window");
+                return false;
+            }
+            startInputFlags = getStartInputFlags(view, startInputFlags);
+            softInputMode = view.getViewRootImpl().mWindowAttributes.softInputMode;
+            windowFlags = view.getViewRootImpl().mWindowAttributes.flags;
+        }
+
         // Okay we are now ready to call into the served view and have it
         // do its stuff.
         // Life is good: let's hook everything up!
diff --git a/core/java/com/android/internal/app/IntentForwarderActivity.java b/core/java/com/android/internal/app/IntentForwarderActivity.java
index 7452daa..65b5979 100644
--- a/core/java/com/android/internal/app/IntentForwarderActivity.java
+++ b/core/java/com/android/internal/app/IntentForwarderActivity.java
@@ -56,6 +56,7 @@
 import android.os.UserManager;
 import android.provider.Settings;
 import android.telecom.TelecomManager;
+import android.util.Log;
 import android.util.Slog;
 import android.view.View;
 import android.widget.Button;
@@ -124,16 +125,19 @@
         String className = intentReceived.getComponent().getClassName();
         final int targetUserId;
         final String userMessage;
+        final UserInfo managedProfile;
         if (className.equals(FORWARD_INTENT_TO_PARENT)) {
             userMessage = getForwardToPersonalMessage();
             targetUserId = getProfileParent();
+            managedProfile = null;
 
             getMetricsLogger().write(
                     new LogMaker(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE)
                     .setSubtype(MetricsEvent.PARENT_PROFILE));
         } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
             userMessage = getForwardToWorkMessage();
-            targetUserId = getManagedProfile();
+            managedProfile = getManagedProfile();
+            targetUserId = managedProfile == null ? UserHandle.USER_NULL : managedProfile.id;
 
             getMetricsLogger().write(
                     new LogMaker(MetricsEvent.ACTION_SWITCH_SHARE_PROFILE)
@@ -142,6 +146,7 @@
             Slog.wtf(TAG, IntentForwarderActivity.class.getName() + " cannot be called directly");
             userMessage = null;
             targetUserId = UserHandle.USER_NULL;
+            managedProfile = null;
         }
         if (targetUserId == UserHandle.USER_NULL) {
             // This covers the case where there is no parent / managed profile.
@@ -185,27 +190,49 @@
                         finish();
                     // When switching to the work profile, ask the user for consent before launching
                     } else if (className.equals(FORWARD_INTENT_TO_MANAGED_PROFILE)) {
-                        maybeShowUserConsentMiniResolver(result, newIntent, targetUserId);
+                        maybeShowUserConsentMiniResolver(result, newIntent, managedProfile);
                     }
                 }, getApplicationContext().getMainExecutor());
     }
 
     private void maybeShowUserConsentMiniResolver(
-            ResolveInfo target, Intent launchIntent, int targetUserId) {
+            ResolveInfo target, Intent launchIntent, UserInfo managedProfile) {
         if (target == null || isIntentForwarderResolveInfo(target) || !isDeviceProvisioned()) {
             finish();
             return;
         }
 
-        if (launchIntent.getBooleanExtra(EXTRA_SKIP_USER_CONFIRMATION, /* defaultValue= */ false)
-                && getCallingPackage() != null
-                && PERMISSION_GRANTED == getPackageManager().checkPermission(
-                        INTERACT_ACROSS_USERS, getCallingPackage())) {
+        int targetUserId = managedProfile == null ? UserHandle.USER_NULL : managedProfile.id;
+        String callingPackage = getCallingPackage();
+        boolean privilegedCallerAskedToSkipUserConsent =
+                launchIntent.getBooleanExtra(
+                        EXTRA_SKIP_USER_CONFIRMATION, /* defaultValue= */ false)
+                        && callingPackage != null
+                        && PERMISSION_GRANTED == getPackageManager().checkPermission(
+                              INTERACT_ACROSS_USERS, callingPackage);
+
+        DevicePolicyManager devicePolicyManager =
+                getSystemService(DevicePolicyManager.class);
+        ComponentName profileOwnerName = devicePolicyManager.getProfileOwnerAsUser(targetUserId);
+        boolean intentToLaunchProfileOwner = profileOwnerName != null
+                && profileOwnerName.getPackageName().equals(target.getComponentInfo().packageName);
+
+        if (privilegedCallerAskedToSkipUserConsent || intentToLaunchProfileOwner) {
+            Log.i("IntentForwarderActivity", String.format(
+                    "Skipping user consent for redirection into the managed profile for intent [%s]"
+                            + ", privilegedCallerAskedToSkipUserConsent=[%s]"
+                            + ", intentToLaunchProfileOwner=[%s]",
+                    launchIntent, privilegedCallerAskedToSkipUserConsent,
+                    intentToLaunchProfileOwner));
             startActivityAsCaller(launchIntent, targetUserId);
             finish();
             return;
         }
 
+        Log.i("IntentForwarderActivity", String.format(
+                "Showing user consent for redirection into the managed profile for intent [%s] and "
+                        + " calling package [%s]",
+                launchIntent, callingPackage));
         int layoutId = R.layout.miniresolver;
         setContentView(layoutId);
 
@@ -245,8 +272,7 @@
 
 
         View telephonyInfo = findViewById(R.id.miniresolver_info_section);
-        DevicePolicyManager devicePolicyManager =
-                getSystemService(DevicePolicyManager.class);
+
         // Additional information section is work telephony specific. Therefore, it is only shown
         // for telephony related intents, when all sim subscriptions are in the work profile.
         if ((isDialerIntent(launchIntent) || isTextMessageIntent(launchIntent))
@@ -507,20 +533,18 @@
     }
 
     /**
-     * Returns the userId of the managed profile for this device or UserHandle.USER_NULL if there is
-     * no managed profile.
+     * Returns the managed profile for this device or null if there is no managed profile.
      *
-     * TODO: Remove the assumption that there is only one managed profile
-     * on the device.
+     * TODO: Remove the assumption that there is only one managed profile on the device.
      */
-    private int getManagedProfile() {
+    @Nullable private UserInfo getManagedProfile() {
         List<UserInfo> relatedUsers = mInjector.getUserManager().getProfiles(UserHandle.myUserId());
         for (UserInfo userInfo : relatedUsers) {
-            if (userInfo.isManagedProfile()) return userInfo.id;
+            if (userInfo.isManagedProfile()) return userInfo;
         }
         Slog.wtf(TAG, FORWARD_INTENT_TO_MANAGED_PROFILE
                 + " has been called, but there is no managed profile");
-        return UserHandle.USER_NULL;
+        return null;
     }
 
     /**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
index 24aaa9b..73eb62a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip/PipTransition.java
@@ -339,19 +339,36 @@
         }
         // This means an expand happened before enter-pip finished and we are now "merging" a
         // no-op transition that happens to match our exit-pip.
+        // Or that the keyguard is up and preventing the transition from applying, in which case we
+        // want to manually reset pip. (b/283783868)
         boolean cancelled = false;
         if (mPipAnimationController.getCurrentAnimator() != null) {
             mPipAnimationController.getCurrentAnimator().cancel();
+            mPipAnimationController.resetAnimatorState();
             cancelled = true;
         }
+
         // Unset exitTransition AFTER cancel so that finishResize knows we are merging.
         mExitTransition = null;
-        if (!cancelled || aborted) return;
+        if (!cancelled) return;
         final ActivityManager.RunningTaskInfo taskInfo = mPipOrganizer.getTaskInfo();
         if (taskInfo != null) {
-            startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
-                    mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
-                    new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */);
+            if (aborted) {
+                // keyguard case - the transition got aborted, so we want to reset state and
+                // windowing mode before reapplying the resize transaction
+                sendOnPipTransitionFinished(TRANSITION_DIRECTION_LEAVE_PIP);
+                mPipOrganizer.onExitPipFinished(taskInfo);
+
+                WindowContainerTransaction wct = new WindowContainerTransaction();
+                mPipOrganizer.applyWindowingModeChangeOnExit(wct, TRANSITION_DIRECTION_LEAVE_PIP);
+                wct.setBounds(taskInfo.token, null);
+                mPipOrganizer.applyFinishBoundsResize(wct, TRANSITION_DIRECTION_LEAVE_PIP, false);
+            } else {
+                // merge case
+                startExpandAnimation(taskInfo, mPipOrganizer.getSurfaceControl(),
+                        mPipBoundsState.getBounds(), mPipBoundsState.getBounds(),
+                        new Rect(mExitDestinationBounds), Surface.ROTATION_0, null /* startT */);
+            }
         }
         mExitDestinationBounds.setEmpty();
         mCurrentPipTaskToken = null;
@@ -567,7 +584,16 @@
                 mPipBoundsState.getDisplayBounds());
         mFinishCallback = (wct, wctCB) -> {
             mPipOrganizer.onExitPipFinished(taskInfo);
-            if (!Transitions.SHELL_TRANSITIONS_ROTATION && toFullscreen) {
+
+            // TODO(b/286346098): remove the OPEN app flicker completely
+            // not checking if we go to fullscreen helps avoid getting pip into an inconsistent
+            // state after the flicker occurs. This is a temp solution until flicker is removed.
+            if (!Transitions.SHELL_TRANSITIONS_ROTATION) {
+                // will help to debug the case when we are not exiting to fullscreen
+                if (!toFullscreen) {
+                    ProtoLog.d(ShellProtoLogGroup.WM_SHELL_PICTURE_IN_PICTURE,
+                            "%s: startExitAnimation() not exiting to fullscreen", TAG);
+                }
                 wct = wct != null ? wct : new WindowContainerTransaction();
                 wct.setBounds(pipTaskToken, null);
                 mPipOrganizer.applyWindowingModeChangeOnExit(wct, TRANSITION_DIRECTION_LEAVE_PIP);
@@ -831,7 +857,7 @@
         }
 
         final Rect destinationBounds = mPipBoundsAlgorithm.getEntryDestinationBounds();
-        final Rect currentBounds = taskInfo.configuration.windowConfiguration.getBounds();
+        final Rect currentBounds = pipChange.getStartAbsBounds();
         int rotationDelta = deltaRotation(startRotation, endRotation);
         Rect sourceHintRect = PipBoundsAlgorithm.getValidSourceHintRect(
                 taskInfo.pictureInPictureParams, currentBounds, destinationBounds);
@@ -1050,7 +1076,7 @@
         // When the PIP window is visible and being a part of the transition, such as display
         // rotation, we need to update its bounds and rounded corner.
         final SurfaceControl leash = pipChange.getLeash();
-        final Rect destBounds = mPipBoundsState.getBounds();
+        final Rect destBounds = mPipOrganizer.getCurrentOrAnimatingBounds();
         final boolean isInPip = mPipTransitionState.isInPip();
         mSurfaceTransactionHelper
                 .crop(startTransaction, leash, destBounds)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
index 8468aac..64f7598 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/splitscreen/StageCoordinator.java
@@ -2841,18 +2841,24 @@
             }
         }
 
+        final ArrayMap<Integer, SurfaceControl> dismissingTasks = new ArrayMap<>();
+        for (int i = info.getChanges().size() - 1; i >= 0; --i) {
+            final TransitionInfo.Change change = info.getChanges().get(i);
+            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
+            if (taskInfo == null) continue;
+            if (getStageOfTask(taskInfo) != null
+                    || getSplitItemPosition(change.getLastParent()) != SPLIT_POSITION_UNDEFINED) {
+                dismissingTasks.put(taskInfo.taskId, change.getLeash());
+            }
+        }
+
+
         if (shouldBreakPairedTaskInRecents(dismissReason)) {
             // Notify recents if we are exiting in a way that breaks the pair, and disable further
             // updates to splits in the recents until we enter split again
             mRecentTasks.ifPresent(recentTasks -> {
-                for (int i = info.getChanges().size() - 1; i >= 0; --i) {
-                    final TransitionInfo.Change change = info.getChanges().get(i);
-                    final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
-                    if (taskInfo != null && (getStageOfTask(taskInfo) != null
-                            || getSplitItemPosition(change.getLastParent())
-                            != SPLIT_POSITION_UNDEFINED)) {
-                        recentTasks.removeSplitPair(taskInfo.taskId);
-                    }
+                for (int i = dismissingTasks.keySet().size() - 1; i >= 0; --i) {
+                    recentTasks.removeSplitPair(dismissingTasks.keyAt(i));
                 }
             });
         }
@@ -2870,6 +2876,10 @@
             t.hide(toStage == STAGE_TYPE_MAIN ? mSideStage.mRootLeash : mMainStage.mRootLeash);
             t.setPosition(toStage == STAGE_TYPE_MAIN
                     ? mMainStage.mRootLeash : mSideStage.mRootLeash, 0, 0);
+        } else {
+            for (int i = dismissingTasks.keySet().size() - 1; i >= 0; --i) {
+                finishT.hide(dismissingTasks.valueAt(i));
+            }
         }
 
         if (toStage == STAGE_TYPE_UNDEFINED) {
@@ -2879,7 +2889,7 @@
         }
 
         // Hide divider and dim layer on transition finished.
-        setDividerVisibility(false, finishT);
+        setDividerVisibility(false, t);
         finishT.hide(mMainStage.mDimLayer);
         finishT.hide(mSideStage.mDimLayer);
     }
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
index c964df1..c2f15f6 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/startingsurface/TaskSnapshotWindow.java
@@ -16,6 +16,7 @@
 
 package com.android.wm.shell.startingsurface;
 
+import static android.app.WindowConfiguration.WINDOWING_MODE_PINNED;
 import static android.graphics.Color.WHITE;
 import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -77,6 +78,13 @@
             @NonNull Runnable clearWindowHandler) {
         final ActivityManager.RunningTaskInfo runningTaskInfo = info.taskInfo;
         final int taskId = runningTaskInfo.taskId;
+
+        // if we're in PIP we don't want to create the snapshot
+        if (runningTaskInfo.getWindowingMode() == WINDOWING_MODE_PINNED) {
+            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
+                    "did not create taskSnapshot due to being in PIP");
+            return null;
+        }
         ProtoLog.v(ShellProtoLogGroup.WM_SHELL_STARTING_WINDOW,
                 "create taskSnapshot surface for task: %d", taskId);
 
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
index 49185d1..d0a361a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/DefaultMixedHandler.java
@@ -25,6 +25,7 @@
 
 import static com.android.wm.shell.common.split.SplitScreenConstants.FLAG_IS_DIVIDER_BAR;
 import static com.android.wm.shell.common.split.SplitScreenConstants.SPLIT_POSITION_UNDEFINED;
+import static com.android.wm.shell.pip.PipAnimationController.ANIM_TYPE_ALPHA;
 import static com.android.wm.shell.splitscreen.SplitScreen.STAGE_TYPE_UNDEFINED;
 import static com.android.wm.shell.splitscreen.SplitScreenController.EXIT_REASON_CHILD_TASK_ENTER_PIP;
 import static com.android.wm.shell.util.TransitionUtil.isOpeningType;
@@ -477,6 +478,7 @@
                 }
             }
 
+            mPipHandler.setEnterAnimationType(ANIM_TYPE_ALPHA);
             mPipHandler.startEnterAnimation(pipChange, startTransaction, finishTransaction,
                     finishCB);
             // Dispatch the rest of the transition normally. This will most-likely be taken by
diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
index b5e4fa3..af06d73 100644
--- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
+++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java
@@ -243,7 +243,9 @@
         return mHelper != null ? mHelper.packageName : null;
     }
 
-    public void updateState(@NonNull String packageName, int uid, boolean isEnabled) {
+    /** Updates enabled state based on associated package. */
+    public void updateState(
+            @NonNull String packageName, int uid, boolean isEnableAllowed, boolean isEnabled) {
         mHelper.updatePackageDetails(packageName, uid);
         if (mAppOpsManager == null) {
             mAppOpsManager = getContext().getSystemService(AppOpsManager.class);
@@ -254,7 +256,9 @@
         final boolean ecmEnabled = getContext().getResources().getBoolean(
                 com.android.internal.R.bool.config_enhancedConfirmationModeEnabled);
         final boolean appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED;
-        if (isEnabled) {
+        if (!isEnableAllowed && !isEnabled) {
+            setEnabled(false);
+        } else if (isEnabled) {
             setEnabled(true);
         } else if (appOpsAllowed && isDisabledByAppOps()) {
             setEnabled(true);
diff --git a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
index 1811c02..64c0f99 100644
--- a/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
+++ b/packages/SystemUI/plugin/bcsmartspace/src/com/android/systemui/plugins/BcSmartspaceDataPlugin.java
@@ -128,6 +128,16 @@
         void setDozeAmount(float amount);
 
         /**
+         * Set if dozing is true or false
+         */
+        default void setDozing(boolean dozing) {}
+
+        /**
+         * Set if split shade enabled
+         */
+        default void setSplitShadeEnabled(boolean enabled) {}
+
+        /**
          * Set the current keyguard bypass enabled status.
          */
         default void setKeyguardBypassEnabled(boolean enabled) {}
diff --git a/packages/SystemUI/res-product/values/strings.xml b/packages/SystemUI/res-product/values/strings.xml
index 13f72af0..42733a2 100644
--- a/packages/SystemUI/res-product/values/strings.xml
+++ b/packages/SystemUI/res-product/values/strings.xml
@@ -122,6 +122,44 @@
        Try again in <xliff:g id="number">%3$d</xliff:g> seconds.
     </string>
 
+    <!-- Title for notification & dialog that the user's phone last shut down because it got too hot. [CHAR LIMIT=40] -->
+    <string name="thermal_shutdown_title" product="default">Phone turned off due to heat</string>
+    <!-- Title for notification & dialog that the user's device last shut down because it got too hot. [CHAR LIMIT=40] -->
+    <string name="thermal_shutdown_title" product="device">Device turned off due to heat</string>
+    <!-- Title for notification & dialog that the user's tablet last shut down because it got too hot. [CHAR LIMIT=40] -->
+    <string name="thermal_shutdown_title" product="tablet">Tablet turned off due to heat</string>
+    <!-- Message body for notification that user's phone last shut down because it got too hot. [CHAR LIMIT=120] -->
+    <string name="thermal_shutdown_message" product="default">Your phone is now running normally.\nTap for more info</string>
+    <!-- Message body for notification that user's device last shut down because it got too hot. [CHAR LIMIT=120] -->
+    <string name="thermal_shutdown_message" product="device">Your device is now running normally.\nTap for more info</string>
+    <!-- Message body for notification that user's tablet last shut down because it got too hot. [CHAR LIMIT=120] -->
+    <string name="thermal_shutdown_message" product="tablet">Your tablet is now running normally.\nTap for more info</string>
+    <!-- Text body for dialog alerting user that their phone last shut down because it got too hot. [CHAR LIMIT=500] -->
+    <string name="thermal_shutdown_dialog_message" product="default">Your phone was too hot, so it turned off to cool down. Your phone is now running normally.\n\nYour phone may get too hot if you:\n\t&#8226; Use resource-intensive apps (such as gaming, video, or navigation apps)\n\t&#8226; Download or upload large files\n\t&#8226; Use your phone in high temperatures</string>
+    <!-- Text body for dialog alerting user that their device last shut down because it got too hot. [CHAR LIMIT=500] -->
+    <string name="thermal_shutdown_dialog_message" product="device">Your device was too hot, so it turned off to cool down. Your device is now running normally.\n\nYour device may get too hot if you:\n\t&#8226; Use resource-intensive apps (such as gaming, video, or navigation apps)\n\t&#8226; Download or upload large files\n\t&#8226; Use your device in high temperatures</string>
+    <!-- Text body for dialog alerting user that their tablet last shut down because it got too hot. [CHAR LIMIT=500] -->
+    <string name="thermal_shutdown_dialog_message" product="tablet">Your tablet was too hot, so it turned off to cool down. Your tablet is now running normally.\n\nYour tablet may get too hot if you:\n\t&#8226; Use resource-intensive apps (such as gaming, video, or navigation apps)\n\t&#8226; Download or upload large files\n\t&#8226; Use your tablet in high temperatures</string>
+
+    <!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
+    <string name="high_temp_title" product="default">Phone is getting warm</string>
+    <!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
+    <string name="high_temp_title" product="device">Device is getting warm</string>
+    <!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
+    <string name="high_temp_title" product="tablet">Tablet is getting warm</string>
+    <!-- Message body for notification that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=120] -->
+    <string name="high_temp_notif_message" product="default">Some features limited while phone cools down.\nTap for more info</string>
+    <!-- Message body for notification that user's device has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=120] -->
+    <string name="high_temp_notif_message" product="device">Some features limited while device cools down.\nTap for more info</string>
+    <!-- Message body for notification that user's tablet has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=120] -->
+    <string name="high_temp_notif_message" product="tablet">Some features limited while tablet cools down.\nTap for more info</string>
+    <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=350] -->
+    <string name="high_temp_dialog_message" product="default">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
+    <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=350] -->
+    <string name="high_temp_dialog_message" product="device">Your device will automatically try to cool down. You can still use your device, but it may run slower.\n\nOnce your device has cooled down, it will run normally.</string>
+    <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=350] -->
+    <string name="high_temp_dialog_message" product="tablet">Your tablet will automatically try to cool down. You can still use your tablet, but it may run slower.\n\nOnce your tablet has cooled down, it will run normally.</string>
+
     <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (tablet) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
     <string name="security_settings_sfps_enroll_find_sensor_message" product="tablet">The fingerprint sensor is on the power button. It’s the flat button next to the raised volume button on the edge of the tablet.</string>
     <!-- Content description of the fingerprint icon when the system-provided fingerprint dialog is showing, to locate the sensor (device) for accessibility (not shown on the screen). [CHAR LIMIT=NONE]-->
diff --git a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
index 7105721..21e0d2c 100644
--- a/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
+++ b/packages/SystemUI/res/layout/media_output_list_item_advanced.xml
@@ -164,7 +164,6 @@
             />
         <ImageView
             android:id="@+id/media_output_item_end_click_icon"
-            android:src="@drawable/media_output_status_edit_session"
             android:layout_width="24dp"
             android:layout_height="24dp"
             android:focusable="false"
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 663efea..070748c 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -2089,23 +2089,11 @@
     <!-- Tuner string -->
     <!-- Tuner string -->
 
-    <!-- Title for notification & dialog that the user's phone last shut down because it got too hot. [CHAR LIMIT=40] -->
-    <string name="thermal_shutdown_title">Phone turned off due to heat</string>
-    <!-- Message body for notification that user's phone last shut down because it got too hot. [CHAR LIMIT=120] -->
-    <string name="thermal_shutdown_message">Your phone is now running normally.\nTap for more info</string>
-    <!-- Text body for dialog alerting user that their phone last shut down because it got too hot. [CHAR LIMIT=500] -->
-    <string name="thermal_shutdown_dialog_message">Your phone was too hot, so it turned off to cool down. Your phone is now running normally.\n\nYour phone may get too hot if you:\n\t&#8226; Use resource-intensive apps (such as gaming, video, or navigation apps)\n\t&#8226; Download or upload large files\n\t&#8226; Use your phone in high temperatures</string>
     <!-- Text help link for care instructions for overheating devices [CHAR LIMIT=40] -->
     <string name="thermal_shutdown_dialog_help_text">See care steps</string>
     <!-- URL for care instructions for overheating devices -->
     <string name="thermal_shutdown_dialog_help_url" translatable="false"></string>
 
-    <!-- Title for notification (and dialog) that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=30] -->
-    <string name="high_temp_title">Phone is getting warm</string>
-    <!-- Message body for notification that user's phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=120] -->
-    <string name="high_temp_notif_message">Some features limited while phone cools down.\nTap for more info</string>
-    <!-- Text body for dialog alerting user that their phone has reached a certain temperature and may start to slow down in order to cool down. [CHAR LIMIT=350] -->
-    <string name="high_temp_dialog_message">Your phone will automatically try to cool down. You can still use your phone, but it may run slower.\n\nOnce your phone has cooled down, it will run normally.</string>
     <!-- Text help link for care instructions for overheating devices [CHAR LIMIT=40] -->
     <string name="high_temp_dialog_help_text">See care steps</string>
     <!-- URL for care instructions for overheating devices -->
diff --git a/packages/SystemUI/res/xml/large_screen_shade_header.xml b/packages/SystemUI/res/xml/large_screen_shade_header.xml
index bf576dc..3881e8c 100644
--- a/packages/SystemUI/res/xml/large_screen_shade_header.xml
+++ b/packages/SystemUI/res/xml/large_screen_shade_header.xml
@@ -60,7 +60,7 @@
             app:layout_constraintBottom_toBottomOf="parent"
             app:layout_constraintEnd_toStartOf="@id/batteryRemainingIcon"
             app:layout_constraintTop_toTopOf="parent"
-            app:layout_constraintEnd_toEndOf="@id/carrier_group"/>
+            app:layout_constraintStart_toEndOf="@id/carrier_group"/>
         <PropertySet android:alpha="1" />
     </Constraint>
 
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
index 41c1eda..a026130 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardClockSwitchController.java
@@ -352,6 +352,13 @@
     }
 
     /**
+     * Set if the split shade is enabled
+     */
+    public void setSplitShadeEnabled(boolean splitShadeEnabled) {
+        mSmartspaceController.setSplitShadeEnabled(splitShadeEnabled);
+    }
+
+    /**
      * Set which clock should be displayed on the keyguard. The other one will be automatically
      * hidden.
      */
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
index 00500d6..6854c97 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardStatusViewController.java
@@ -323,6 +323,13 @@
     }
 
     /**
+     * Set if the split shade is enabled
+     */
+    public void setSplitShadeEnabled(boolean enabled) {
+        mKeyguardClockSwitchController.setSplitShadeEnabled(enabled);
+    }
+
+    /**
      * Updates the alignment of the KeyguardStatusView and animates the transition if requested.
      */
     public void updateAlignment(
@@ -350,6 +357,9 @@
         }
 
         mInteractionJankMonitor.begin(mView, CUJ_LOCKSCREEN_CLOCK_MOVE_ANIMATION);
+        /* This transition blocks any layout changes while running. For that reason
+        * special logic with setting visibility was added to {@link BcSmartspaceView#setDozing}
+        * for split shade to avoid jump of the media object. */
         ChangeBounds transition = new ChangeBounds();
         if (splitShadeEnabled) {
             // Excluding media from the transition on split-shade, as it doesn't transition
diff --git a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
index ae061c0..de24024 100644
--- a/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
+++ b/packages/SystemUI/src/com/android/keyguard/KeyguardUpdateMonitor.java
@@ -296,6 +296,11 @@
     private static final ComponentName FALLBACK_HOME_COMPONENT = new ComponentName(
             "com.android.settings", "com.android.settings.FallbackHome");
 
+    private static final List<Integer> ABSENT_SIM_STATE_LIST = Arrays.asList(
+            TelephonyManager.SIM_STATE_ABSENT,
+            TelephonyManager.SIM_STATE_UNKNOWN,
+            TelephonyManager.SIM_STATE_NOT_READY);
+
     private final Context mContext;
     private final UserTracker mUserTracker;
     private final KeyguardUpdateMonitorLogger mLogger;
@@ -3698,8 +3703,7 @@
         mLogger.logSimState(subId, slotId, state);
 
         boolean becameAbsent = false;
-        if (!SubscriptionManager.isValidSubscriptionId(subId)
-                && state != TelephonyManager.SIM_STATE_UNKNOWN) {
+        if (!SubscriptionManager.isValidSubscriptionId(subId)) {
             mLogger.w("invalid subId in handleSimStateChange()");
             /* Only handle No SIM(ABSENT) and Card Error(CARD_IO_ERROR) due to
              * handleServiceStateChange() handle other case */
@@ -3717,11 +3721,11 @@
                 }
             } else if (state == TelephonyManager.SIM_STATE_CARD_IO_ERROR) {
                 updateTelephonyCapable(true);
-            } else {
-                return;
             }
         }
 
+        becameAbsent |= ABSENT_SIM_STATE_LIST.contains(state);
+
         SimData data = mSimDatas.get(subId);
         final boolean changed;
         if (data == null) {
@@ -3734,7 +3738,7 @@
             data.subId = subId;
             data.slotId = slotId;
         }
-        if ((changed || becameAbsent) || state == TelephonyManager.SIM_STATE_UNKNOWN) {
+        if ((changed || becameAbsent)) {
             for (int i = 0; i < mCallbacks.size(); i++) {
                 KeyguardUpdateMonitorCallback cb = mCallbacks.get(i).get();
                 if (cb != null) {
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index bc41ab31..2d82c50 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -139,6 +139,7 @@
 import com.android.systemui.flags.Flags;
 import com.android.systemui.flags.SystemPropertiesHelper;
 import com.android.systemui.keyguard.dagger.KeyguardModule;
+import com.android.systemui.keyguard.shared.model.TransitionStep;
 import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
 import com.android.systemui.log.SessionTracker;
 import com.android.systemui.navigationbar.NavigationModeController;
@@ -538,6 +539,8 @@
 
     private CentralSurfaces mCentralSurfaces;
 
+    private IRemoteAnimationFinishedCallback mUnoccludeFromDreamFinishedCallback;
+
     private final DeviceConfig.OnPropertiesChangedListener mOnPropertiesChangedListener =
             new DeviceConfig.OnPropertiesChangedListener() {
             @Override
@@ -642,6 +645,8 @@
             switch (simState) {
                 case TelephonyManager.SIM_STATE_NOT_READY:
                 case TelephonyManager.SIM_STATE_ABSENT:
+                case TelephonyManager.SIM_STATE_UNKNOWN:
+                    mPendingPinLock = false;
                     // only force lock screen in case of missing sim if user hasn't
                     // gone through setup wizard
                     synchronized (KeyguardViewMediator.this) {
@@ -706,9 +711,6 @@
                         }
                     }
                     break;
-                case TelephonyManager.SIM_STATE_UNKNOWN:
-                    mPendingPinLock = false;
-                    break;
                 default:
                     if (DEBUG_SIM_STATES) Log.v(TAG, "Unspecific state: " + simState);
                     break;
@@ -1165,6 +1167,7 @@
                             getRemoteSurfaceAlphaApplier().accept(0.0f);
                             mDreamingToLockscreenTransitionViewModel.get()
                                     .startTransition();
+                            mUnoccludeFromDreamFinishedCallback = finishedCallback;
                             return;
                         }
 
@@ -1244,6 +1247,19 @@
         };
     }
 
+    private Consumer<TransitionStep> getFinishedCallbackConsumer() {
+        return (TransitionStep step) -> {
+            if (mUnoccludeFromDreamFinishedCallback == null) return;
+            try {
+                mUnoccludeFromDreamFinishedCallback.onAnimationFinished();
+                mUnoccludeFromDreamFinishedCallback = null;
+            } catch (RemoteException e) {
+                Log.e(TAG, "Wasn't able to callback", e);
+            }
+            mInteractionJankMonitor.end(CUJ_LOCKSCREEN_OCCLUSION);
+        };
+    }
+
     private DeviceConfigProxy mDeviceConfig;
     private DozeParameters mDozeParameters;
 
@@ -1503,6 +1519,9 @@
                 collectFlow(viewRootImpl.getView(),
                         mDreamingToLockscreenTransitionViewModel.get().getDreamOverlayAlpha(),
                         getRemoteSurfaceAlphaApplier(), mMainDispatcher);
+                collectFlow(viewRootImpl.getView(),
+                        mDreamingToLockscreenTransitionViewModel.get().getTransitionEnded(),
+                        getFinishedCallbackConsumer(), mMainDispatcher);
             }
         }
         // Most services aren't available until the system reaches the ready state, so we
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
index 42f12f8..41a81a8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractor.kt
@@ -49,11 +49,15 @@
 ) {
     /** (any)->GONE transition information */
     val anyStateToGoneTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == KeyguardState.GONE }
+        repository.transitions.filter { step -> step.to == GONE }
 
     /** (any)->AOD transition information */
     val anyStateToAodTransition: Flow<TransitionStep> =
-        repository.transitions.filter { step -> step.to == KeyguardState.AOD }
+        repository.transitions.filter { step -> step.to == AOD }
+
+    /** DREAMING->(any) transition information. */
+    val fromDreamingTransition: Flow<TransitionStep> =
+        repository.transitions.filter { step -> step.from == DREAMING }
 
     /** AOD->LOCKSCREEN transition information. */
     val aodToLockscreenTransition: Flow<TransitionStep> = repository.transition(AOD, LOCKSCREEN)
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
index 9ca4bd6..e24d326 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModel.kt
@@ -48,7 +48,7 @@
         )
 
     val transitionEnded =
-        keyguardTransitionInteractor.dreamingToLockscreenTransition.filter { step ->
+        keyguardTransitionInteractor.fromDreamingTransition.filter { step ->
             step.transitionState == TransitionState.FINISHED ||
                 step.transitionState == TransitionState.CANCELED
         }
diff --git a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
index 318cd99..26a7d04 100644
--- a/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
+++ b/packages/SystemUI/src/com/android/systemui/media/dialog/MediaOutputAdapter.java
@@ -20,6 +20,7 @@
 import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_NONE;
 import static com.android.settingslib.media.MediaDevice.SelectionBehavior.SELECTION_BEHAVIOR_TRANSFER;
 
+import android.annotation.DrawableRes;
 import android.content.Context;
 import android.content.res.ColorStateList;
 import android.graphics.drawable.AnimatedVectorDrawable;
@@ -181,27 +182,23 @@
                                     mController.getSelectedMediaDevice(), device)));
                     boolean isHost = device.isHostForOngoingSession()
                             && isActiveWithOngoingSession;
-                    if (isHost) {
+                    if (isActiveWithOngoingSession) {
                         mCurrentActivePosition = position;
                         updateTitleIcon(R.drawable.media_output_icon_volume,
                                 mController.getColorItemContent());
                         mSubTitleText.setText(device.getSubtextString());
                         updateTwoLineLayoutContentAlpha(DEVICE_CONNECTED_ALPHA);
-                        updateEndClickAreaAsSessionEditing(device);
+                        updateEndClickAreaAsSessionEditing(device,
+                                isHost ? R.drawable.media_output_status_edit_session
+                                        : R.drawable.ic_sound_bars_anim);
                         setTwoLineLayout(device, null /* title */, true /* bFocused */,
                                 true /* showSeekBar */, false /* showProgressBar */,
                                 true /* showSubtitle */, false /* showStatus */,
                                 true /* showEndTouchArea */, false /* isFakeActive */);
                         initSeekbar(device, isCurrentSeekbarInvisible);
                     } else {
-                        if (isActiveWithOngoingSession) {
-                            //Selected device which has ongoing session, disable seekbar since we
-                            //only allow volume control on Host
+                        if (currentlyConnected) {
                             mCurrentActivePosition = position;
-                        }
-                        boolean showSeekbar =
-                                (!device.hasOngoingSession() && currentlyConnected);
-                        if (showSeekbar) {
                             updateTitleIcon(R.drawable.media_output_icon_volume,
                                     mController.getColorItemContent());
                             initSeekbar(device, isCurrentSeekbarInvisible);
@@ -222,10 +219,10 @@
                                 updateClickActionBasedOnSelectionBehavior(device)
                                         ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
                         setTwoLineLayout(device, currentlyConnected /* bFocused */,
-                                showSeekbar  /* showSeekBar */,
+                                currentlyConnected  /* showSeekBar */,
                                 false /* showProgressBar */, true /* showSubtitle */,
                                 deviceStatusIcon != null /* showStatus */,
-                                isActiveWithOngoingSession /* isFakeActive */);
+                                false /* isFakeActive */);
                     }
                 } else if (device.getState() == MediaDeviceState.STATE_CONNECTING_FAILED) {
                     setUpDeviceIcon(device);
@@ -267,25 +264,16 @@
                         setSingleLineLayout(getItemTitle(device));
                     } else if (device.hasOngoingSession()) {
                         mCurrentActivePosition = position;
-                        if (device.isHostForOngoingSession()) {
-                            updateTitleIcon(R.drawable.media_output_icon_volume,
-                                    mController.getColorItemContent());
-                            updateEndClickAreaAsSessionEditing(device);
-                            mEndClickIcon.setVisibility(View.VISIBLE);
-                            setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
-                                    false /* showProgressBar */, false /* showCheckBox */,
-                                    true /* showEndTouchArea */);
-                            initSeekbar(device, isCurrentSeekbarInvisible);
-                        } else {
-                            updateDeviceStatusIcon(mContext.getDrawable(
-                                    R.drawable.ic_sound_bars_anim));
-                            mStatusIcon.setVisibility(View.VISIBLE);
-                            updateSingleLineLayoutContentAlpha(
-                                    updateClickActionBasedOnSelectionBehavior(device)
-                                            ? DEVICE_CONNECTED_ALPHA : DEVICE_DISCONNECTED_ALPHA);
-                            setSingleLineLayout(getItemTitle(device));
-                            initFakeActiveDevice();
-                        }
+                        updateTitleIcon(R.drawable.media_output_icon_volume,
+                                mController.getColorItemContent());
+                        updateEndClickAreaAsSessionEditing(device, device.isHostForOngoingSession()
+                                ? R.drawable.media_output_status_edit_session
+                                : R.drawable.ic_sound_bars_anim);
+                        mEndClickIcon.setVisibility(View.VISIBLE);
+                        setSingleLineLayout(getItemTitle(device), true /* showSeekBar */,
+                                false /* showProgressBar */, false /* showCheckBox */,
+                                true /* showEndTouchArea */);
+                        initSeekbar(device, isCurrentSeekbarInvisible);
                     } else if (mController.isCurrentConnectedDeviceRemote()
                             && !mController.getSelectableMediaDevice().isEmpty()) {
                         //If device is connected and there's other selectable devices, layout as
@@ -362,7 +350,7 @@
             mStatusIcon.setAlpha(alphaValue);
         }
 
-        private void updateEndClickAreaAsSessionEditing(MediaDevice device) {
+        private void updateEndClickAreaAsSessionEditing(MediaDevice device, @DrawableRes int id) {
             mEndClickIcon.setOnClickListener(null);
             mEndTouchArea.setOnClickListener(null);
             updateEndClickAreaColor(mController.getColorSeekbarProgress());
@@ -371,6 +359,11 @@
             mEndClickIcon.setOnClickListener(
                     v -> mController.tryToLaunchInAppRoutingIntent(device.getId(), v));
             mEndTouchArea.setOnClickListener(v -> mEndClickIcon.performClick());
+            Drawable drawable = mContext.getDrawable(id);
+            mEndClickIcon.setImageDrawable(drawable);
+            if (drawable instanceof AnimatedVectorDrawable) {
+                ((AnimatedVectorDrawable) drawable).start();
+            }
         }
 
         public void updateEndClickAreaColor(int color) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 8123627..3acfe6c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -1172,6 +1172,7 @@
                 mKeyguardStatusViewComponentFactory.build(keyguardStatusView);
         mKeyguardStatusViewController = statusViewComponent.getKeyguardStatusViewController();
         mKeyguardStatusViewController.init();
+        mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
         updateClockAppearance();
 
         if (mKeyguardUserSwitcherController != null) {
@@ -1224,6 +1225,7 @@
 
     private void onSplitShadeEnabledChanged() {
         mShadeLog.logSplitShadeChanged(mSplitShadeEnabled);
+        mKeyguardStatusViewController.setSplitShadeEnabled(mSplitShadeEnabled);
         // Reset any left over overscroll state. It is a rare corner case but can happen.
         mQsController.setOverScrollAmount(0);
         mScrimController.setNotificationsOverScrollAmount(0);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
index 518825c..6c1dc8c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/lockscreen/LockscreenSmartspaceController.kt
@@ -124,6 +124,7 @@
     private var showSensitiveContentForCurrentUser = false
     private var showSensitiveContentForManagedUser = false
     private var managedUserHandle: UserHandle? = null
+    private var mSplitShadeEnabled = false
 
     // TODO(b/202758428): refactor so that we can test color updates via region samping, similar to
     //  how we test color updates when theme changes (See testThemeChangeUpdatesTextColor).
@@ -131,6 +132,7 @@
     // TODO: Move logic into SmartspaceView
     var stateChangeListener = object : View.OnAttachStateChangeListener {
         override fun onViewAttachedToWindow(v: View) {
+            (v as SmartspaceView).setSplitShadeEnabled(mSplitShadeEnabled)
             smartspaceViews.add(v as SmartspaceView)
 
             connectSession()
@@ -216,6 +218,11 @@
             execution.assertIsMainThread()
             smartspaceViews.forEach { it.setDozeAmount(eased) }
         }
+
+        override fun onDozingChanged(isDozing: Boolean) {
+            execution.assertIsMainThread()
+            smartspaceViews.forEach { it.setDozing(isDozing) }
+        }
     }
 
     private val deviceProvisionedListener =
@@ -421,6 +428,11 @@
         reloadSmartspace()
     }
 
+    fun setSplitShadeEnabled(enabled: Boolean) {
+        mSplitShadeEnabled = enabled
+        smartspaceViews.forEach { it.setSplitShadeEnabled(enabled) }
+    }
+
     /**
      * Requests the smartspace session for an update.
      */
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
index 9272c37..11ba753 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutController.java
@@ -411,7 +411,8 @@
         }
     };
 
-    private final NotificationSwipeHelper.NotificationCallback mNotificationCallback =
+    @VisibleForTesting
+    final NotificationSwipeHelper.NotificationCallback mNotificationCallback =
             new NotificationSwipeHelper.NotificationCallback() {
 
                 @Override
@@ -470,10 +471,11 @@
                  */
 
                 public void handleChildViewDismissed(View view) {
+                    // The View needs to clean up the Swipe states, e.g. roundness.
+                    mView.onSwipeEnd();
                     if (mView.getClearAllInProgress()) {
                         return;
                     }
-                    mView.onSwipeEnd();
                     if (view instanceof ExpandableNotificationRow) {
                         ExpandableNotificationRow row = (ExpandableNotificationRow) view;
                         if (row.isHeadsUp()) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
index bcf3b0c..4a9921e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/window/StatusBarWindowController.java
@@ -240,8 +240,10 @@
                     Insets.of(0, safeTouchRegionHeight, 0, 0));
         }
         lp.providedInsets = new InsetsFrameProvider[] {
-                new InsetsFrameProvider(mInsetsSourceOwner, 0, statusBars()),
-                new InsetsFrameProvider(mInsetsSourceOwner, 0, tappableElement()),
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, statusBars())
+                        .setInsetsSize(Insets.of(0, height, 0, 0)),
+                new InsetsFrameProvider(mInsetsSourceOwner, 0, tappableElement())
+                        .setInsetsSize(Insets.of(0, height, 0, 0)),
                 gestureInsetsProvider
         };
         return lp;
diff --git a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
index 7456d34..9362220 100644
--- a/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/volume/VolumeDialogImpl.java
@@ -476,7 +476,8 @@
         mWindow.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
         mWindow.clearFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND
                 | WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR);
-        mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
+        mWindow.addFlags(WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                | WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
                 | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                 | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH
                 | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED);
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
index b21cc6d..9e561ed 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardClockSwitchControllerTest.java
@@ -408,4 +408,18 @@
                 any(ClockRegistry.ClockChangeListener.class));
         verify(mClockEventController, times).registerListeners(mView);
     }
+
+    @Test
+    public void testSplitShadeEnabledSetToSmartspaceController() {
+        mController.setSplitShadeEnabled(true);
+        verify(mSmartspaceController, times(1)).setSplitShadeEnabled(true);
+        verify(mSmartspaceController, times(0)).setSplitShadeEnabled(false);
+    }
+
+    @Test
+    public void testSplitShadeDisabledSetToSmartspaceController() {
+        mController.setSplitShadeEnabled(false);
+        verify(mSmartspaceController, times(1)).setSplitShadeEnabled(false);
+        verify(mSmartspaceController, times(0)).setSplitShadeEnabled(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
index a2c6329..512e5dc 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardStatusViewControllerTest.java
@@ -17,6 +17,7 @@
 package com.android.keyguard;
 
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -155,4 +156,18 @@
         verify(mControllerMock).setProperty(AnimatableProperty.SCALE_X, 20f, true);
         verify(mControllerMock).setProperty(AnimatableProperty.SCALE_Y, 20f, true);
     }
+
+    @Test
+    public void splitShadeEnabledPassedToClockSwitchController() {
+        mController.setSplitShadeEnabled(true);
+        verify(mKeyguardClockSwitchController, times(1)).setSplitShadeEnabled(true);
+        verify(mKeyguardClockSwitchController, times(0)).setSplitShadeEnabled(false);
+    }
+
+    @Test
+    public void splitShadeDisabledPassedToClockSwitchController() {
+        mController.setSplitShadeEnabled(false);
+        verify(mKeyguardClockSwitchController, times(1)).setSplitShadeEnabled(false);
+        verify(mKeyguardClockSwitchController, times(0)).setSplitShadeEnabled(true);
+    }
 }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
index 1e675f8..3cb4c0c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/KeyguardUpdateMonitorTest.java
@@ -2935,6 +2935,16 @@
                 TelephonyManager.SIM_STATE_UNKNOWN);
     }
 
+    @Test
+    public void testOnSimStateChanged_HandleSimStateNotReady() {
+        KeyguardUpdateMonitorCallback keyguardUpdateMonitorCallback = spy(
+                KeyguardUpdateMonitorCallback.class);
+        mKeyguardUpdateMonitor.registerCallback(keyguardUpdateMonitorCallback);
+        mKeyguardUpdateMonitor.handleSimStateChange(-1, 0, TelephonyManager.SIM_STATE_NOT_READY);
+        verify(keyguardUpdateMonitorCallback).onSimStateChanged(-1, 0,
+                TelephonyManager.SIM_STATE_NOT_READY);
+    }
+
     private void verifyFingerprintAuthenticateNeverCalled() {
         verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), any());
         verify(mFingerprintManager, never()).authenticate(any(), any(), any(), any(), anyInt(),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
index c280538..7a501a8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/KeyguardViewMediatorTest.java
@@ -186,6 +186,8 @@
         when(mStatusBarKeyguardViewManager.getViewRootImpl()).thenReturn(testViewRoot);
         when(mDreamingToLockscreenTransitionViewModel.getDreamOverlayAlpha())
                 .thenReturn(mock(Flow.class));
+        when(mDreamingToLockscreenTransitionViewModel.getTransitionEnded())
+                .thenReturn(mock(Flow.class));
         mNotificationShadeWindowController = new NotificationShadeWindowControllerImpl(mContext,
                 mWindowManager, mActivityManager, mDozeParameters, mStatusBarStateController,
                 mConfigurationController, mViewMediator, mKeyguardBypassController,
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
index a341346..ab994b7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/DreamingToLockscreenTransitionViewModelTest.kt
@@ -22,8 +22,16 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
-import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
+import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
+import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
+import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
+import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
 import com.android.systemui.keyguard.shared.model.TransitionState
+import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
+import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
+import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
+import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
 import com.android.systemui.keyguard.shared.model.TransitionStep
 import com.android.systemui.util.mockito.mock
 import com.google.common.collect.Range
@@ -60,7 +68,7 @@
             val job =
                 underTest.dreamOverlayTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0f, STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
@@ -82,7 +90,7 @@
             val job = underTest.dreamOverlayAlpha.onEach { values.add(it) }.launchIn(this)
 
             // Should start running here...
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0f, STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
             repository.sendTransitionStep(step(0.5f))
@@ -104,7 +112,7 @@
 
             val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
 
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0f, STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.1f))
             repository.sendTransitionStep(step(0.2f))
@@ -126,7 +134,7 @@
             val job =
                 underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
 
-            repository.sendTransitionStep(step(0f, TransitionState.STARTED))
+            repository.sendTransitionStep(step(0f, STARTED))
             repository.sendTransitionStep(step(0f))
             repository.sendTransitionStep(step(0.3f))
             repository.sendTransitionStep(step(0.5f))
@@ -138,13 +146,44 @@
             job.cancel()
         }
 
-    private fun step(
-        value: Float,
-        state: TransitionState = TransitionState.RUNNING
-    ): TransitionStep {
+    @Test
+    fun transitionEnded() =
+        runTest(UnconfinedTestDispatcher()) {
+            val values = mutableListOf<TransitionStep>()
+
+            val job = underTest.transitionEnded.onEach { values.add(it) }.launchIn(this)
+
+            repository.sendTransitionStep(TransitionStep(DOZING, DREAMING, 0.0f, STARTED))
+            repository.sendTransitionStep(TransitionStep(DOZING, DREAMING, 1.0f, FINISHED))
+
+            repository.sendTransitionStep(TransitionStep(DREAMING, LOCKSCREEN, 0.0f, STARTED))
+            repository.sendTransitionStep(TransitionStep(DREAMING, LOCKSCREEN, 0.1f, RUNNING))
+            repository.sendTransitionStep(TransitionStep(DREAMING, LOCKSCREEN, 1.0f, FINISHED))
+
+            repository.sendTransitionStep(TransitionStep(LOCKSCREEN, DREAMING, 0.0f, STARTED))
+            repository.sendTransitionStep(TransitionStep(LOCKSCREEN, DREAMING, 0.5f, RUNNING))
+            repository.sendTransitionStep(TransitionStep(LOCKSCREEN, DREAMING, 1.0f, FINISHED))
+
+            repository.sendTransitionStep(TransitionStep(DREAMING, GONE, 0.0f, STARTED))
+            repository.sendTransitionStep(TransitionStep(DREAMING, GONE, 0.5f, RUNNING))
+            repository.sendTransitionStep(TransitionStep(DREAMING, GONE, 1.0f, CANCELED))
+
+            repository.sendTransitionStep(TransitionStep(DREAMING, AOD, 0.0f, STARTED))
+            repository.sendTransitionStep(TransitionStep(DREAMING, AOD, 1.0f, FINISHED))
+
+            assertThat(values.size).isEqualTo(3)
+            values.forEach {
+                assertThat(it.transitionState == FINISHED || it.transitionState == CANCELED)
+                    .isTrue()
+            }
+
+            job.cancel()
+        }
+
+    private fun step(value: Float, state: TransitionState = RUNNING): TransitionStep {
         return TransitionStep(
-            from = KeyguardState.DREAMING,
-            to = KeyguardState.LOCKSCREEN,
+            from = DREAMING,
+            to = LOCKSCREEN,
             value = value,
             transitionState = state,
             ownerName = "DreamingToLockscreenTransitionViewModelTest"
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
index 7df54d4..e4f89a2 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/dialog/MediaOutputAdapterTest.java
@@ -291,13 +291,13 @@
 
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mTitleText.getText().toString()).isEqualTo(TEST_DEVICE_NAME_1);
-        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mTwoLineLayout.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mEndTouchArea.getVisibility()).isEqualTo(View.VISIBLE);
     }
 
     @Test
@@ -525,16 +525,16 @@
         mMediaOutputAdapter.onBindViewHolder(mViewHolder, 0);
 
         assertThat(mViewHolder.mTitleText.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.GONE);
+        assertThat(mViewHolder.mSeekBar.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mProgressBar.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mCheckBox.getVisibility()).isEqualTo(View.GONE);
-        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.VISIBLE);
+        assertThat(mViewHolder.mStatusIcon.getVisibility()).isEqualTo(View.GONE);
         assertThat(mViewHolder.mSubTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mTwoLineTitleText.getVisibility()).isEqualTo(View.VISIBLE);
         assertThat(mViewHolder.mSubTitleText.getText().toString()).isEqualTo(TEST_CUSTOM_SUBTEXT);
         assertThat(mViewHolder.mTwoLineTitleText.getText().toString()).isEqualTo(
                 TEST_DEVICE_NAME_1);
-        assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isTrue();
+        assertThat(mViewHolder.mContainerLayout.hasOnClickListeners()).isFalse();
     }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
index 02666e4..cd0550e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayoutControllerTest.java
@@ -74,6 +74,7 @@
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.row.NotificationGutsManager;
 import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController.NotificationPanelEvent;
+import com.android.systemui.statusbar.notification.stack.NotificationSwipeHelper.NotificationCallback;
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationListViewModel;
 import com.android.systemui.statusbar.phone.CentralSurfaces;
 import com.android.systemui.statusbar.phone.HeadsUpManagerPhone;
@@ -339,6 +340,36 @@
     }
 
     @Test
+    public void callSwipeCallbacksDuringClearAll() {
+        initController(/* viewIsAttached= */ true);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        NotificationCallback notificationCallback = mController.mNotificationCallback;
+
+        when(mNotificationStackScrollLayout.getClearAllInProgress()).thenReturn(true);
+
+        notificationCallback.onBeginDrag(row);
+        verify(mNotificationStackScrollLayout).onSwipeBegin(row);
+
+        notificationCallback.handleChildViewDismissed(row);
+        verify(mNotificationStackScrollLayout).onSwipeEnd();
+    }
+
+    @Test
+    public void callSwipeCallbacksDuringClearNotification() {
+        initController(/* viewIsAttached= */ true);
+        ExpandableNotificationRow row = mock(ExpandableNotificationRow.class);
+        NotificationCallback notificationCallback = mController.mNotificationCallback;
+
+        when(mNotificationStackScrollLayout.getClearAllInProgress()).thenReturn(false);
+
+        notificationCallback.onBeginDrag(row);
+        verify(mNotificationStackScrollLayout).onSwipeBegin(row);
+
+        notificationCallback.handleChildViewDismissed(row);
+        verify(mNotificationStackScrollLayout).onSwipeEnd();
+    }
+
+    @Test
     public void testOnMenuClickedLogging() {
         ExpandableNotificationRow row = mock(ExpandableNotificationRow.class, RETURNS_DEEP_STUBS);
         when(row.getEntry().getSbn().getLogMaker()).thenReturn(new LogMaker(
diff --git a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
index eb7fa10..add94b1 100644
--- a/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
+++ b/services/core/java/com/android/server/devicestate/DeviceStateManagerService.java
@@ -172,6 +172,7 @@
     private DeviceState mRearDisplayState;
 
     // TODO(259328837) Generalize for all pending feature requests in the future
+    @GuardedBy("mLock")
     @Nullable
     private OverrideRequest mRearDisplayPendingOverrideRequest;
 
@@ -779,7 +780,7 @@
      * {@link StatusBarManagerInternal} to notify SystemUI to display the educational dialog.
      */
     @GuardedBy("mLock")
-    private void showRearDisplayEducationalOverlayLocked(OverrideRequest request) {
+    private void showRearDisplayEducationalOverlayLocked(@NonNull OverrideRequest request) {
         mRearDisplayPendingOverrideRequest = request;
 
         StatusBarManagerInternal statusBar =
@@ -844,8 +845,8 @@
      * request if it was dismissed in a way that should cancel the feature.
      */
     private void onStateRequestOverlayDismissedInternal(boolean shouldCancelRequest) {
-        if (mRearDisplayPendingOverrideRequest != null) {
-            synchronized (mLock) {
+        synchronized (mLock) {
+            if (mRearDisplayPendingOverrideRequest != null) {
                 if (shouldCancelRequest) {
                     ProcessRecord processRecord = mProcessRecords.get(
                             mRearDisplayPendingOverrideRequest.getPid());
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 488745c..4bd66f2 100644
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5594,6 +5594,11 @@
                 boolean granted, boolean userSet) {
             Objects.requireNonNull(listener);
             checkNotificationListenerAccess();
+            if (granted && listener.flattenToString().length()
+                    > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) {
+                throw new IllegalArgumentException(
+                        "Component name too long: " + listener.flattenToString());
+            }
             if (!userSet && isNotificationListenerAccessUserSet(listener)) {
                 // Don't override user's choice
                 return;
diff --git a/services/core/java/com/android/server/policy/PhoneWindowManager.java b/services/core/java/com/android/server/policy/PhoneWindowManager.java
index 3132c5d..cbded89 100644
--- a/services/core/java/com/android/server/policy/PhoneWindowManager.java
+++ b/services/core/java/com/android/server/policy/PhoneWindowManager.java
@@ -3570,19 +3570,17 @@
     }
 
     @Override
-    public void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition) {
-        if (mKeyguardDelegate != null && waitAppTransition) {
+    public void onKeyguardOccludedChangedLw(boolean occluded) {
+        if (mKeyguardDelegate != null) {
             mPendingKeyguardOccluded = occluded;
             mKeyguardOccludedChanged = true;
-        } else {
-            setKeyguardOccludedLw(occluded);
         }
     }
 
     @Override
     public int applyKeyguardOcclusionChange() {
         if (DEBUG_KEYGUARD) Slog.d(TAG, "transition/occluded commit occluded="
-                + mPendingKeyguardOccluded);
+                + mPendingKeyguardOccluded + " changed=" + mKeyguardOccludedChanged);
 
         // TODO(b/276433230): Explicitly save before/after for occlude state in each
         // Transition so we don't need to update SysUI every time.
diff --git a/services/core/java/com/android/server/policy/WindowManagerPolicy.java b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
index 887f946..03a7bd3 100644
--- a/services/core/java/com/android/server/policy/WindowManagerPolicy.java
+++ b/services/core/java/com/android/server/policy/WindowManagerPolicy.java
@@ -169,7 +169,7 @@
      *
      * @param occluded Whether Keyguard is currently occluded or not.
      */
-    void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition);
+    void onKeyguardOccludedChangedLw(boolean occluded);
 
     /**
      * Commit any queued changes to keyguard occlude status that had been deferred during the
diff --git a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
index 4a57592a..27329e2 100644
--- a/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
+++ b/services/core/java/com/android/server/power/stats/BatteryStatsImpl.java
@@ -14613,17 +14613,13 @@
 
     // Inform StatsLog of setBatteryState changes.
     private void reportChangesToStatsLog(final int status, final int plugType, final int level) {
-        if (!mHaveBatteryLevel) {
-            return;
-        }
-
-        if (mBatteryStatus != status) {
+        if (!mHaveBatteryLevel || mBatteryStatus != status) {
             FrameworkStatsLog.write(FrameworkStatsLog.CHARGING_STATE_CHANGED, status);
         }
-        if (mBatteryPlugType != plugType) {
+        if (!mHaveBatteryLevel || mBatteryPlugType != plugType) {
             FrameworkStatsLog.write(FrameworkStatsLog.PLUGGED_STATE_CHANGED, plugType);
         }
-        if (mBatteryLevel != level) {
+        if (!mHaveBatteryLevel || mBatteryLevel != level) {
             FrameworkStatsLog.write(FrameworkStatsLog.BATTERY_LEVEL_CHANGED, level);
         }
     }
diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java
index b296ef2..1ff01a6 100644
--- a/services/core/java/com/android/server/vr/VrManagerService.java
+++ b/services/core/java/com/android/server/vr/VrManagerService.java
@@ -1049,7 +1049,11 @@
 
         for (ComponentName c : possibleServices) {
             if (Objects.equals(c.getPackageName(), pkg)) {
-                nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
+                try {
+                    nm.setNotificationListenerAccessGrantedForUser(c, userId, true);
+                } catch (Exception e) {
+                    Slog.w(TAG, "Could not grant NLS access to package " + pkg, e);
+                }
             }
         }
     }
diff --git a/services/core/java/com/android/server/wm/KeyguardController.java b/services/core/java/com/android/server/wm/KeyguardController.java
index ad9c3b2..83fd725 100644
--- a/services/core/java/com/android/server/wm/KeyguardController.java
+++ b/services/core/java/com/android/server/wm/KeyguardController.java
@@ -418,13 +418,17 @@
             return;
         }
 
-        final boolean waitAppTransition = isKeyguardLocked(displayId);
-        mWindowManager.mPolicy.onKeyguardOccludedChangedLw(isDisplayOccluded(DEFAULT_DISPLAY),
-                waitAppTransition);
-        if (waitAppTransition) {
-            mService.deferWindowLayout();
-            try {
-                if (isDisplayOccluded(DEFAULT_DISPLAY)) {
+        final TransitionController tc = mRootWindowContainer.mTransitionController;
+
+        final boolean occluded = isDisplayOccluded(displayId);
+        final boolean performTransition = isKeyguardLocked(displayId);
+        final boolean executeTransition = performTransition && !tc.isCollecting();
+
+        mWindowManager.mPolicy.onKeyguardOccludedChangedLw(occluded);
+        mService.deferWindowLayout();
+        try {
+            if (isKeyguardLocked(displayId)) {
+                if (occluded) {
                     mRootWindowContainer.getDefaultDisplay().requestTransitionAndLegacyPrepare(
                             TRANSIT_KEYGUARD_OCCLUDE,
                             TRANSIT_FLAG_KEYGUARD_OCCLUDING,
@@ -434,11 +438,19 @@
                             TRANSIT_KEYGUARD_UNOCCLUDE,
                             TRANSIT_FLAG_KEYGUARD_UNOCCLUDING);
                 }
-                updateKeyguardSleepToken(DEFAULT_DISPLAY);
-                mWindowManager.executeAppTransition();
-            } finally {
-                mService.continueWindowLayout();
+            } else {
+                if (tc.inTransition()) {
+                    tc.mStateValidators.add(mWindowManager.mPolicy::applyKeyguardOcclusionChange);
+                } else {
+                    mWindowManager.mPolicy.applyKeyguardOcclusionChange();
+                }
             }
+            updateKeyguardSleepToken(displayId);
+            if (performTransition && executeTransition) {
+                mWindowManager.executeAppTransition();
+            }
+        } finally {
+            mService.continueWindowLayout();
         }
     }
 
@@ -485,6 +497,9 @@
         }
     }
 
+    /**
+     * @return true if Keyguard is occluded or the device is dreaming.
+     */
     boolean isDisplayOccluded(int displayId) {
         return getDisplayState(displayId).mOccluded;
     }
diff --git a/services/core/java/com/android/server/wm/SafeActivityOptions.java b/services/core/java/com/android/server/wm/SafeActivityOptions.java
index 5860776..c914fa1 100644
--- a/services/core/java/com/android/server/wm/SafeActivityOptions.java
+++ b/services/core/java/com/android/server/wm/SafeActivityOptions.java
@@ -48,6 +48,7 @@
 import android.os.UserHandle;
 import android.util.Slog;
 import android.view.RemoteAnimationAdapter;
+import android.window.RemoteTransition;
 import android.window.WindowContainerToken;
 
 import com.android.internal.annotations.VisibleForTesting;
@@ -385,6 +386,18 @@
             throw new SecurityException(msg);
         }
 
+        // Check permission for remote transitions
+        final RemoteTransition transition = options.getRemoteTransition();
+        if (transition != null && supervisor.mService.checkPermission(
+                CONTROL_REMOTE_APP_TRANSITION_ANIMATIONS, callingPid, callingUid)
+                != PERMISSION_GRANTED) {
+            final String msg = "Permission Denial: starting " + getIntentString(intent)
+                    + " from " + callerApp + " (pid=" + callingPid
+                    + ", uid=" + callingUid + ") with remoteTransition";
+            Slog.w(TAG, msg);
+            throw new SecurityException(msg);
+        }
+
         // If launched from bubble is specified, then ensure that the caller is system or sysui.
         if (options.getLaunchedFromBubble() && !isSystemOrSystemUI(callingPid, callingUid)) {
             final String msg = "Permission Denial: starting " + getIntentString(intent)
diff --git a/services/core/java/com/android/server/wm/Transition.java b/services/core/java/com/android/server/wm/Transition.java
index b7ef5bb..2c582c1 100644
--- a/services/core/java/com/android/server/wm/Transition.java
+++ b/services/core/java/com/android/server/wm/Transition.java
@@ -27,6 +27,7 @@
 import static android.view.Display.DEFAULT_DISPLAY;
 import static android.view.Display.INVALID_DISPLAY;
 import static android.view.WindowManager.INPUT_CONSUMER_RECENTS_ANIMATION;
+import static android.view.WindowManager.KEYGUARD_VISIBILITY_TRANSIT_FLAGS;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_SEAMLESS;
 import static android.view.WindowManager.LayoutParams.ROTATION_ANIMATION_UNSPECIFIED;
 import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
@@ -1093,6 +1094,16 @@
                 final Task task = ar.getTask();
                 if (task == null) continue;
                 boolean visibleAtTransitionEnd = mVisibleAtTransitionEndTokens.contains(ar);
+                // visibleAtTransitionEnd is used to guard against pre-maturely committing
+                // invisible on a window which is actually hidden by a later transition and not this
+                // one. However, for a transient launch, we can't use this mechanism because the
+                // visibility is determined at finish. Instead, use a different heuristic: don't
+                // commit invisible if the window is already in a later transition. That later
+                // transition will then handle the commit.
+                if (isTransientLaunch(ar) && !ar.isVisibleRequested()
+                        && mController.inCollectingTransition(ar)) {
+                    visibleAtTransitionEnd = true;
+                }
                 // We need both the expected visibility AND current requested-visibility to be
                 // false. If it is expected-visible but not currently visible, it means that
                 // another animation is queued-up to animate this to invisibility, so we can't
@@ -2649,7 +2660,7 @@
     }
 
     private void validateKeyguardOcclusion() {
-        if ((mFlags & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0) {
+        if ((mFlags & KEYGUARD_VISIBILITY_TRANSIT_FLAGS) != 0) {
             mController.mStateValidators.add(
                 mController.mAtm.mWindowManager.mPolicy::applyKeyguardOcclusionChange);
         }
diff --git a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
index 46c90b4..bafa4a5 100644
--- a/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
+++ b/services/credentials/java/com/android/server/credentials/ProviderRegistryGetSession.java
@@ -126,6 +126,7 @@
         mElementKeys = new HashSet<>(requestOption
                 .getCredentialRetrievalData()
                 .getStringArrayList(CredentialOption.SUPPORTED_ELEMENT_KEYS));
+        mStatus = Status.PENDING;
     }
 
     protected ProviderRegistryGetSession(@NonNull Context context,
@@ -143,6 +144,7 @@
         mElementKeys = new HashSet<>(requestOption
                 .getCredentialRetrievalData()
                 .getStringArrayList(CredentialOption.SUPPORTED_ELEMENT_KEYS));
+        mStatus = Status.PENDING;
     }
 
     private List<Entry> prepareUiCredentialEntries(
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 cebc540..4347dd6 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -4148,6 +4148,30 @@
     }
 
     @Test
+    public void testSetListenerAccessForUser_grantWithNameTooLong_throws() {
+        UserHandle user = UserHandle.of(mContext.getUserId() + 10);
+        ComponentName c = new ComponentName("com.example.package",
+                com.google.common.base.Strings.repeat("Blah", 150));
+
+        assertThrows(IllegalArgumentException.class,
+                () -> mBinderService.setNotificationListenerAccessGrantedForUser(
+                        c, user.getIdentifier(), /* enabled= */ true, true));
+    }
+
+    @Test
+    public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception {
+        UserHandle user = UserHandle.of(mContext.getUserId() + 10);
+        ComponentName c = new ComponentName("com.example.package",
+                com.google.common.base.Strings.repeat("Blah", 150));
+
+        mBinderService.setNotificationListenerAccessGrantedForUser(
+                c, user.getIdentifier(), /* enabled= */ false, true);
+
+        verify(mListeners).setPackageOrComponentEnabled(
+                c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true);
+    }
+
+    @Test
     public void testSetAssistantAccessForUser() throws Exception {
         UserInfo ui = new UserInfo();
         ui.id = mContext.getUserId() + 10;
diff --git a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
index adf3f39..bd111ad 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TestWindowManagerPolicy.java
@@ -233,7 +233,7 @@
     }
 
     @Override
-    public void onKeyguardOccludedChangedLw(boolean occluded, boolean waitAppTransition) {
+    public void onKeyguardOccludedChangedLw(boolean occluded) {
     }
 
     public void setSafeMode(boolean safeMode) {
diff --git a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java
index db36975..346622f 100644
--- a/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java
+++ b/tests/BinaryTransparencyHostTest/src/android/transparency/test/BinaryTransparencyHostTest.java
@@ -61,8 +61,11 @@
         options.setTestMethodName("testCollectAllApexInfo");
 
         // Collect APEX package names from /apex, then pass them as expectation to be verified.
+        // The package names are collected from the find name with deduplication (NB: we used to
+        // deduplicate by dropping directory names with '@', but there's a DCLA case where it only
+        // has one directory with '@'. So we have to keep it and deduplicate the current way).
         CommandResult result = getDevice().executeShellV2Command(
-                "ls -d /apex/*/ |grep -v @ |grep -v /apex/sharedlibs |cut -d/ -f3");
+                "ls -d /apex/*/ |grep -v /apex/sharedlibs |cut -d/ -f3 |cut -d@ -f1 |sort |uniq");
         assertTrue(result.getStatus() == CommandStatus.SUCCESS);
         String[] packageNames = result.getStdout().split("\n");
         for (var i = 0; i < packageNames.length; i++) {