diff --git a/core/java/android/app/DownloadManager.java b/core/java/android/app/DownloadManager.java
index 35509237827953f06bf87054650cad6984da9cac..fd13174a6a39b8ba13da9b78292521e6ba8c0428 100644
--- a/core/java/android/app/DownloadManager.java
+++ b/core/java/android/app/DownloadManager.java
@@ -575,8 +575,9 @@ public class DownloadManager {
                     extras.putString(Downloads.DIR_TYPE, dirType);
                     client.call(Downloads.CALL_CREATE_EXTERNAL_PUBLIC_DIR, null, extras);
                 } catch (RemoteException e) {
-                    throw new IllegalStateException("Unable to create directory: "
-                            + file.getAbsolutePath());
+                    throw new IllegalStateException(
+                        "Unable to create directory: " + file.getAbsolutePath(),
+                        e);
                 }
             } else {
                 if (file.exists()) {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
index 33c084e424f6c5712ff927fd10275aff661b2164..39287674be0e056f180d38c7c4bdddae10179df6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/BouncerScene.kt
@@ -78,7 +78,10 @@ import androidx.compose.ui.unit.dp
 import androidx.compose.ui.unit.times
 import com.android.compose.PlatformButton
 import com.android.compose.animation.scene.ElementKey
+import com.android.compose.animation.scene.SceneKey as SceneTransitionLayoutSceneKey
 import com.android.compose.animation.scene.SceneScope
+import com.android.compose.animation.scene.SceneTransitionLayout
+import com.android.compose.animation.scene.transitions
 import com.android.compose.modifiers.thenIf
 import com.android.compose.windowsizeclass.LocalWindowSizeClass
 import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel
@@ -90,6 +93,8 @@ import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
 import com.android.systemui.common.shared.model.Text.Companion.loadText
 import com.android.systemui.common.ui.compose.Icon
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.fold.ui.composable.FoldPosture
+import com.android.systemui.fold.ui.composable.foldPosture
 import com.android.systemui.res.R
 import com.android.systemui.scene.shared.model.Direction
 import com.android.systemui.scene.shared.model.SceneKey
@@ -159,28 +164,27 @@ private fun SceneScope.BouncerScene(
 
         when (layout) {
             Layout.STANDARD ->
-                Bouncer(
+                StandardLayout(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
-                    userInputAreaVisibility = UserInputAreaVisibility.FULL,
                     modifier = childModifier,
                 )
             Layout.SIDE_BY_SIDE ->
-                SideBySide(
+                SideBySideLayout(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
                     isUserSwitcherVisible = isFullScreenUserSwitcherEnabled,
                     modifier = childModifier,
                 )
             Layout.STACKED ->
-                Stacked(
+                StackedLayout(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
                     isUserSwitcherVisible = isFullScreenUserSwitcherEnabled,
                     modifier = childModifier,
                 )
             Layout.SPLIT ->
-                Split(
+                SplitLayout(
                     viewModel = viewModel,
                     dialogFactory = dialogFactory,
                     modifier = childModifier,
@@ -194,59 +198,150 @@ private fun SceneScope.BouncerScene(
  * authentication attempt, including all messaging UI (directives, reasoning, errors, etc.).
  */
 @Composable
-private fun Bouncer(
+private fun StandardLayout(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
-    userInputAreaVisibility: UserInputAreaVisibility,
     modifier: Modifier = Modifier,
+    outputOnly: Boolean = false,
 ) {
-    val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
-    val dialogMessage: String? by viewModel.throttlingDialogMessage.collectAsState()
-    var dialog: Dialog? by remember { mutableStateOf(null) }
-    val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState()
+    val foldPosture: FoldPosture by foldPosture()
+    val isSplitAroundTheFoldRequired by viewModel.isFoldSplitRequired.collectAsState()
+    val isSplitAroundTheFold =
+        foldPosture == FoldPosture.Tabletop && !outputOnly && isSplitAroundTheFoldRequired
+    val currentSceneKey by
+        remember(isSplitAroundTheFold) {
+            mutableStateOf(
+                if (isSplitAroundTheFold) SceneKeys.SplitSceneKey else SceneKeys.ContiguousSceneKey
+            )
+        }
 
-    Column(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        modifier = modifier.padding(start = 32.dp, top = 92.dp, end = 32.dp, bottom = 0.dp)
+    SceneTransitionLayout(
+        currentScene = currentSceneKey,
+        onChangeScene = {},
+        transitions = SceneTransitions,
+        modifier = modifier,
     ) {
-        Crossfade(
-            targetState = message,
-            label = "Bouncer message",
-            animationSpec = if (message.isUpdateAnimated) tween() else snap(),
-        ) { message ->
-            Text(
-                text = message.text,
-                color = MaterialTheme.colorScheme.onSurface,
-                style = MaterialTheme.typography.bodyLarge,
+        scene(SceneKeys.ContiguousSceneKey) {
+            FoldSplittable(
+                viewModel = viewModel,
+                dialogFactory = dialogFactory,
+                outputOnly = outputOnly,
+                isSplit = false,
             )
         }
 
-        Spacer(Modifier.heightIn(min = 21.dp, max = 48.dp))
-
-        Box(Modifier.weight(1f)) {
-            UserInputArea(
+        scene(SceneKeys.SplitSceneKey) {
+            FoldSplittable(
                 viewModel = viewModel,
-                visibility = userInputAreaVisibility,
-                modifier = Modifier.align(Alignment.Center),
+                dialogFactory = dialogFactory,
+                outputOnly = outputOnly,
+                isSplit = true,
             )
         }
+    }
+}
 
-        Spacer(Modifier.heightIn(min = 21.dp, max = 48.dp))
+/**
+ * Renders the "standard" layout of the bouncer, where the bouncer is rendered on its own (no user
+ * switcher UI) and laid out vertically, centered horizontally.
+ *
+ * If [isSplit] is `true`, the top and bottom parts of the bouncer are split such that they don't
+ * render across the location of the fold hardware when the device is fully or part-way unfolded
+ * with the fold hinge in a horizontal position.
+ *
+ * If [outputOnly] is `true`, only the "output" part of the UI is shown (where the entered PIN
+ * "shapes" appear), if `false`, the entire UI is shown, including the area where the user can enter
+ * their PIN or pattern.
+ */
+@Composable
+private fun SceneScope.FoldSplittable(
+    viewModel: BouncerViewModel,
+    dialogFactory: BouncerSceneDialogFactory,
+    outputOnly: Boolean,
+    isSplit: Boolean,
+    modifier: Modifier = Modifier,
+) {
+    val message: BouncerViewModel.MessageViewModel by viewModel.message.collectAsState()
+    val dialogMessage: String? by viewModel.throttlingDialogMessage.collectAsState()
+    var dialog: Dialog? by remember { mutableStateOf(null) }
+    val actionButton: BouncerActionButtonModel? by viewModel.actionButton.collectAsState()
+    val splitRatio =
+        LocalContext.current.resources.getFloat(
+            R.dimen.motion_layout_half_fold_bouncer_height_ratio
+        )
+
+    Column(modifier = modifier.padding(horizontal = 32.dp)) {
+        // Content above the fold, when split on a foldable device in a "table top" posture:
+        Box(
+            modifier =
+                Modifier.element(SceneElements.AboveFold).fillMaxWidth().thenIf(isSplit) {
+                    Modifier.weight(splitRatio)
+                },
+        ) {
+            Column(
+                horizontalAlignment = Alignment.CenterHorizontally,
+                modifier = Modifier.fillMaxWidth().padding(top = 92.dp),
+            ) {
+                Crossfade(
+                    targetState = message,
+                    label = "Bouncer message",
+                    animationSpec = if (message.isUpdateAnimated) tween() else snap(),
+                ) { message ->
+                    Text(
+                        text = message.text,
+                        color = MaterialTheme.colorScheme.onSurface,
+                        style = MaterialTheme.typography.bodyLarge,
+                    )
+                }
 
-        val actionButtonModifier = Modifier.height(56.dp)
+                Spacer(Modifier.heightIn(min = 21.dp, max = 48.dp))
 
-        actionButton.let { actionButtonViewModel ->
-            if (actionButtonViewModel != null) {
-                BouncerActionButton(
-                    viewModel = actionButtonViewModel,
-                    modifier = actionButtonModifier,
+                UserInputArea(
+                    viewModel = viewModel,
+                    visibility = UserInputAreaVisibility.OUTPUT_ONLY,
                 )
-            } else {
-                Spacer(modifier = actionButtonModifier)
             }
         }
 
-        Spacer(Modifier.height(48.dp))
+        // Content below the fold, when split on a foldable device in a "table top" posture:
+        Box(
+            modifier =
+                Modifier.element(SceneElements.BelowFold).fillMaxWidth().thenIf(isSplit) {
+                    Modifier.weight(1 - splitRatio)
+                },
+        ) {
+            Column(
+                horizontalAlignment = Alignment.CenterHorizontally,
+                modifier = Modifier.fillMaxWidth(),
+            ) {
+                if (!outputOnly) {
+                    Box(Modifier.weight(1f)) {
+                        UserInputArea(
+                            viewModel = viewModel,
+                            visibility = UserInputAreaVisibility.INPUT_ONLY,
+                            modifier = Modifier.align(Alignment.Center),
+                        )
+                    }
+                }
+
+                Spacer(Modifier.heightIn(min = 21.dp, max = 48.dp))
+
+                val actionButtonModifier = Modifier.height(56.dp)
+
+                actionButton.let { actionButtonViewModel ->
+                    if (actionButtonViewModel != null) {
+                        BouncerActionButton(
+                            viewModel = actionButtonViewModel,
+                            modifier = actionButtonModifier,
+                        )
+                    } else {
+                        Spacer(modifier = actionButtonModifier)
+                    }
+                }
+
+                Spacer(Modifier.height(48.dp))
+            }
+        }
 
         if (dialogMessage != null) {
             if (dialog == null) {
@@ -288,8 +383,8 @@ private fun UserInputArea(
     when (val nonNullViewModel = authMethodViewModel) {
         is PinBouncerViewModel ->
             when (visibility) {
-                UserInputAreaVisibility.FULL ->
-                    PinBouncer(
+                UserInputAreaVisibility.OUTPUT_ONLY ->
+                    PinInputDisplay(
                         viewModel = nonNullViewModel,
                         modifier = modifier,
                     )
@@ -298,34 +393,21 @@ private fun UserInputArea(
                         viewModel = nonNullViewModel,
                         modifier = modifier,
                     )
-                UserInputAreaVisibility.OUTPUT_ONLY ->
-                    PinInputDisplay(
-                        viewModel = nonNullViewModel,
-                        modifier = modifier,
-                    )
-                UserInputAreaVisibility.NONE -> {}
             }
         is PasswordBouncerViewModel ->
-            when (visibility) {
-                UserInputAreaVisibility.FULL,
-                UserInputAreaVisibility.INPUT_ONLY ->
-                    PasswordBouncer(
-                        viewModel = nonNullViewModel,
-                        modifier = modifier,
-                    )
-                else -> {}
+            if (visibility == UserInputAreaVisibility.INPUT_ONLY) {
+                PasswordBouncer(
+                    viewModel = nonNullViewModel,
+                    modifier = modifier,
+                )
             }
         is PatternBouncerViewModel ->
-            when (visibility) {
-                UserInputAreaVisibility.FULL,
-                UserInputAreaVisibility.INPUT_ONLY ->
-                    PatternBouncer(
-                        viewModel = nonNullViewModel,
-                        modifier =
-                            Modifier.aspectRatio(1f, matchHeightConstraintsFirst = false)
-                                .then(modifier)
-                    )
-                else -> {}
+            if (visibility == UserInputAreaVisibility.INPUT_ONLY) {
+                PatternBouncer(
+                    viewModel = nonNullViewModel,
+                    modifier =
+                        Modifier.aspectRatio(1f, matchHeightConstraintsFirst = false).then(modifier)
+                )
             }
         else -> Unit
     }
@@ -492,17 +574,17 @@ private fun UserSwitcherDropdownMenu(
  * by double-tapping on the side.
  */
 @Composable
-private fun Split(
+private fun SplitLayout(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
     modifier: Modifier = Modifier,
 ) {
     SwappableLayout(
         startContent = { startContentModifier ->
-            Bouncer(
+            StandardLayout(
                 viewModel = viewModel,
                 dialogFactory = dialogFactory,
-                userInputAreaVisibility = UserInputAreaVisibility.OUTPUT_ONLY,
+                outputOnly = true,
                 modifier = startContentModifier,
             )
         },
@@ -595,7 +677,7 @@ private fun SwappableLayout(
  * rendering of the bouncer will be used instead of the side-by-side layout.
  */
 @Composable
-private fun SideBySide(
+private fun SideBySideLayout(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
     isUserSwitcherVisible: Boolean,
@@ -615,10 +697,9 @@ private fun SideBySide(
             }
         },
         endContent = { endContentModifier ->
-            Bouncer(
+            StandardLayout(
                 viewModel = viewModel,
                 dialogFactory = dialogFactory,
-                userInputAreaVisibility = UserInputAreaVisibility.FULL,
                 modifier = endContentModifier,
             )
         },
@@ -628,7 +709,7 @@ private fun SideBySide(
 
 /** Arranges the bouncer contents and user switcher contents one on top of the other, vertically. */
 @Composable
-private fun Stacked(
+private fun StackedLayout(
     viewModel: BouncerViewModel,
     dialogFactory: BouncerSceneDialogFactory,
     isUserSwitcherVisible: Boolean,
@@ -644,10 +725,9 @@ private fun Stacked(
             )
         }
 
-        Bouncer(
+        StandardLayout(
             viewModel = viewModel,
             dialogFactory = dialogFactory,
-            userInputAreaVisibility = UserInputAreaVisibility.FULL,
             modifier = Modifier.fillMaxWidth().weight(1f),
         )
     }
@@ -707,11 +787,6 @@ private enum class Layout {
 
 /** Enumerates all supported user-input area visibilities. */
 private enum class UserInputAreaVisibility {
-    /**
-     * The entire user input area is shown, including where the user enters input and where it's
-     * reflected to the user.
-     */
-    FULL,
     /**
      * Only the area where the user enters the input is shown; the area where the input is reflected
      * back to the user is not shown.
@@ -722,8 +797,6 @@ private enum class UserInputAreaVisibility {
      * input is entered by the user is not shown.
      */
     OUTPUT_ONLY,
-    /** The entire user input area is hidden. */
-    NONE,
 }
 
 /**
@@ -758,3 +831,17 @@ private fun animatedAlpha(
 private val SelectedUserImageSize = 190.dp
 private val UserSwitcherDropdownWidth = SelectedUserImageSize + 2 * 29.dp
 private val UserSwitcherDropdownHeight = 60.dp
+
+private object SceneKeys {
+    val ContiguousSceneKey = SceneTransitionLayoutSceneKey("default")
+    val SplitSceneKey = SceneTransitionLayoutSceneKey("split")
+}
+
+private object SceneElements {
+    val AboveFold = ElementKey("above_fold")
+    val BelowFold = ElementKey("below_fold")
+}
+
+private val SceneTransitions = transitions {
+    from(SceneKeys.ContiguousSceneKey, to = SceneKeys.SplitSceneKey) { spec = tween() }
+}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
index 5b9ad4de8c8433030998ece904c9d4c75086af16..fb50f69f7d9b530c2a55f758615ea8260c27365c 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/bouncer/ui/composable/PinBouncer.kt
@@ -24,14 +24,10 @@ import androidx.compose.animation.core.AnimationVector1D
 import androidx.compose.animation.core.animateDpAsState
 import androidx.compose.animation.core.animateFloatAsState
 import androidx.compose.animation.core.tween
-import androidx.compose.foundation.gestures.awaitEachGesture
-import androidx.compose.foundation.gestures.awaitFirstDown
 import androidx.compose.foundation.gestures.detectTapGestures
 import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Spacer
-import androidx.compose.foundation.layout.heightIn
-import androidx.compose.foundation.layout.size
+import androidx.compose.foundation.layout.aspectRatio
+import androidx.compose.foundation.layout.sizeIn
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
@@ -69,34 +65,13 @@ import kotlinx.coroutines.delay
 import kotlinx.coroutines.launch
 
 @Composable
-internal fun PinBouncer(
+fun PinPad(
     viewModel: PinBouncerViewModel,
     modifier: Modifier = Modifier,
 ) {
     // Report that the UI is shown to let the view-model run some logic.
     LaunchedEffect(Unit) { viewModel.onShown() }
 
-    Column(
-        horizontalAlignment = Alignment.CenterHorizontally,
-        modifier =
-            modifier.pointerInput(Unit) {
-                awaitEachGesture {
-                    awaitFirstDown()
-                    viewModel.onDown()
-                }
-            }
-    ) {
-        PinInputDisplay(viewModel)
-        Spacer(Modifier.heightIn(min = 34.dp, max = 48.dp))
-        PinPad(viewModel)
-    }
-}
-
-@Composable
-fun PinPad(
-    viewModel: PinBouncerViewModel,
-    modifier: Modifier = Modifier,
-) {
     val isInputEnabled: Boolean by viewModel.isInputEnabled.collectAsState()
     val backspaceButtonAppearance by viewModel.backspaceButtonAppearance.collectAsState()
     val confirmButtonAppearance by viewModel.confirmButtonAppearance.collectAsState()
@@ -298,7 +273,8 @@ private fun PinPadButton(
         contentAlignment = Alignment.Center,
         modifier =
             modifier
-                .size(pinButtonSize)
+                .sizeIn(maxWidth = pinButtonSize, maxHeight = pinButtonSize)
+                .aspectRatio(1f)
                 .drawBehind {
                     drawRoundRect(
                         color = containerColor,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/FoldPosture.kt b/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/FoldPosture.kt
new file mode 100644
index 0000000000000000000000000000000000000000..1c993cf6206c5b46a8fee125d10ba4d70bc01d45
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/fold/ui/composable/FoldPosture.kt
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.fold.ui.composable
+
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.State
+import androidx.compose.runtime.collectAsState
+import androidx.compose.runtime.getValue
+import androidx.compose.runtime.produceState
+import androidx.compose.runtime.remember
+import androidx.compose.ui.platform.LocalContext
+import androidx.window.layout.FoldingFeature
+import androidx.window.layout.WindowInfoTracker
+
+sealed interface FoldPosture {
+    /** A foldable device that's fully closed/folded or a device that doesn't support folding. */
+    data object Folded : FoldPosture
+    /** A foldable that's halfway open with the hinge held vertically. */
+    data object Book : FoldPosture
+    /** A foldable that's halfway open with the hinge held horizontally. */
+    data object Tabletop : FoldPosture
+    /** A foldable that's fully unfolded / flat. */
+    data object FullyUnfolded : FoldPosture
+}
+
+/** Returns the [FoldPosture] of the device currently. */
+@Composable
+fun foldPosture(): State<FoldPosture> {
+    val context = LocalContext.current
+    val infoTracker = remember(context) { WindowInfoTracker.getOrCreate(context) }
+    val layoutInfo by infoTracker.windowLayoutInfo(context).collectAsState(initial = null)
+
+    return produceState<FoldPosture>(
+        initialValue = FoldPosture.Folded,
+        key1 = layoutInfo,
+    ) {
+        value =
+            layoutInfo
+                ?.displayFeatures
+                ?.firstNotNullOfOrNull { it as? FoldingFeature }
+                .let { foldingFeature ->
+                    when (foldingFeature?.state) {
+                        null -> FoldPosture.Folded
+                        FoldingFeature.State.HALF_OPENED ->
+                            foldingFeature.orientation.toHalfwayPosture()
+                        FoldingFeature.State.FLAT ->
+                            if (foldingFeature.isSeparating) {
+                                // Dual screen device.
+                                foldingFeature.orientation.toHalfwayPosture()
+                            } else {
+                                FoldPosture.FullyUnfolded
+                            }
+                        else -> error("Unsupported state \"${foldingFeature.state}\"")
+                    }
+                }
+    }
+}
+
+private fun FoldingFeature.Orientation.toHalfwayPosture(): FoldPosture {
+    return when (this) {
+        FoldingFeature.Orientation.HORIZONTAL -> FoldPosture.Tabletop
+        FoldingFeature.Orientation.VERTICAL -> FoldPosture.Book
+        else -> error("Unsupported orientation \"$this\"")
+    }
+}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
index 15d4d2002b2bd0b90ee621992411222ff98fa85a..67ce86b4e137f9457c2550cc57b5664be942402d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/bouncer/domain/interactor/BouncerActionButtonInteractorTest.kt
@@ -25,7 +25,7 @@ import com.android.internal.logging.nano.MetricsProto
 import com.android.internal.logging.testing.FakeMetricsLogger
 import com.android.internal.util.EmergencyAffordanceManager
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags.REFACTOR_GETCURRENTUSER
 import com.android.systemui.log.table.TableLogBuffer
diff --git a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
index f0915583f0210713be357dcce3440c080be6b9c9..07359d1b446cbb1f962fb3f72f9106b2edcad3ea 100644
--- a/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
+++ b/packages/SystemUI/src/com/android/keyguard/LockIconViewController.java
@@ -60,10 +60,10 @@ import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.biometrics.AuthRippleController;
 import com.android.systemui.biometrics.UdfpsController;
 import com.android.systemui.biometrics.shared.model.UdfpsOverlayParams;
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
 import com.android.systemui.dagger.SysUISingleton;
 import com.android.systemui.dagger.qualifiers.Main;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FeatureFlags;
 import com.android.systemui.flags.Flags;
@@ -127,7 +127,7 @@ public class LockIconViewController implements Dumpable {
     @NonNull private final KeyguardTransitionInteractor mTransitionInteractor;
     @NonNull private final KeyguardInteractor mKeyguardInteractor;
     @NonNull private final View.AccessibilityDelegate mAccessibilityDelegate;
-    @NonNull private final Lazy<BouncerInteractor> mBouncerInteractor;
+    @NonNull private final Lazy<DeviceEntryInteractor> mDeviceEntryInteractor;
     @NonNull private final SceneContainerFlags mSceneContainerFlags;
 
     // Tracks the velocity of a touch to help filter out the touches that move too fast.
@@ -205,7 +205,7 @@ public class LockIconViewController implements Dumpable {
             @NonNull FeatureFlags featureFlags,
             PrimaryBouncerInteractor primaryBouncerInteractor,
             Context context,
-            Lazy<BouncerInteractor> bouncerInteractor,
+            Lazy<DeviceEntryInteractor> deviceEntryInteractor,
             SceneContainerFlags sceneContainerFlags
     ) {
         mStatusBarStateController = statusBarStateController;
@@ -232,7 +232,7 @@ public class LockIconViewController implements Dumpable {
         dumpManager.registerDumpable(TAG, this);
         mResources = resources;
         mContext = context;
-        mBouncerInteractor = bouncerInteractor;
+        mDeviceEntryInteractor = deviceEntryInteractor;
         mSceneContainerFlags = sceneContainerFlags;
 
         mAccessibilityDelegate = new View.AccessibilityDelegate() {
@@ -747,7 +747,7 @@ public class LockIconViewController implements Dumpable {
         vibrateOnLongPress();
 
         if (mSceneContainerFlags.isEnabled()) {
-            mBouncerInteractor.get().showOrUnlockDevice(null);
+            mDeviceEntryInteractor.get().attemptDeviceEntry();
         } else {
             mKeyguardViewController.showPrimaryBouncer(/* scrim */ true);
         }
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
index e8b16db10da5ca3d1c74d5ebb0501c0b680b146c..ee3a55f51679b4f1c175fb2ea23b97099a1a7c36 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/data/repository/AuthenticationRepository.kt
@@ -25,7 +25,7 @@ import com.android.internal.widget.LockPatternChecker
 import com.android.internal.widget.LockPatternUtils
 import com.android.internal.widget.LockscreenCredential
 import com.android.keyguard.KeyguardSecurityModel
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationResultModel
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.broadcast.BroadcastDispatcher
@@ -45,7 +45,9 @@ import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.combine
@@ -67,6 +69,12 @@ interface AuthenticationRepository {
      */
     val isAutoConfirmFeatureEnabled: StateFlow<Boolean>
 
+    /**
+     * Emits the result whenever a PIN/Pattern/Password security challenge is attempted by the user
+     * in order to unlock the device.
+     */
+    val authenticationChallengeResult: SharedFlow<Boolean>
+
     /**
      * The exact length a PIN should be for us to enable PIN length hinting.
      *
@@ -164,6 +172,7 @@ constructor(
             initialValue = false,
             getFreshValue = lockPatternUtils::isAutoPinConfirmEnabled,
         )
+    override val authenticationChallengeResult = MutableSharedFlow<Boolean>()
 
     override val hintedPinLength: Int = 6
 
@@ -224,6 +233,7 @@ constructor(
             } else {
                 lockPatternUtils.reportFailedPasswordAttempt(selectedUserId)
             }
+            authenticationChallengeResult.emit(isSuccessful)
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
index 22b44d56fe9be270620cd5d23addbb91a02dadbf..1ede5301e751ecbad7ddb112dc2e1a672a6f0c14 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractor.kt
@@ -16,19 +16,16 @@
 
 package com.android.systemui.authentication.domain.interactor
 
-import com.android.app.tracing.TraceUtils.Companion.async
 import com.android.app.tracing.TraceUtils.Companion.withContext
 import com.android.internal.widget.LockPatternView
 import com.android.internal.widget.LockscreenCredential
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.AuthenticationRepository
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.dagger.qualifiers.Background
-import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
 import com.android.systemui.user.data.repository.UserRepository
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
@@ -40,6 +37,7 @@ import kotlinx.coroutines.Job
 import kotlinx.coroutines.async
 import kotlinx.coroutines.delay
 import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
@@ -47,7 +45,6 @@ import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.launch
-import kotlinx.coroutines.withContext
 
 /**
  * Hosts application business logic related to user authentication.
@@ -64,7 +61,6 @@ constructor(
     private val repository: AuthenticationRepository,
     @Background private val backgroundDispatcher: CoroutineDispatcher,
     private val userRepository: UserRepository,
-    private val deviceEntryRepository: DeviceEntryRepository,
     private val clock: SystemClock,
 ) {
     /**
@@ -85,8 +81,7 @@ constructor(
      * `true` even when the lockscreen is showing and still needs to be dismissed by the user to
      * proceed.
      */
-    val authenticationMethod: Flow<DomainLayerAuthenticationMethodModel> =
-        repository.authenticationMethod.map { rawModel -> rawModel.toDomainLayer() }
+    val authenticationMethod: Flow<AuthenticationMethodModel> = repository.authenticationMethod
 
     /** The current authentication throttling state, only meaningful if [isThrottled] is `true`. */
     val throttling: StateFlow<AuthenticationThrottlingModel> = repository.throttling
@@ -143,6 +138,13 @@ constructor(
     /** Whether the pattern should be visible for the currently-selected user. */
     val isPatternVisible: StateFlow<Boolean> = repository.isPatternVisible
 
+    /**
+     * Emits the outcome (successful or unsuccessful) whenever a PIN/Pattern/Password security
+     * challenge is attempted by the user in order to unlock the device.
+     */
+    val authenticationChallengeResult: SharedFlow<Boolean> =
+        repository.authenticationChallengeResult
+
     private var throttlingCountdownJob: Job? = null
 
     init {
@@ -165,17 +167,8 @@ constructor(
      * The flow should be used for code that wishes to stay up-to-date its logic as the
      * authentication changes over time and this method should be used for simple code that only
      * needs to check the current value.
-     *
-     * Note: this layer adds the synthetic authentication method of "swipe" which is special. When
-     * the current authentication method is "swipe", the user does not need to complete any
-     * authentication challenge to unlock the device; they just need to dismiss the lockscreen to
-     * get past it. This also means that the value of `DeviceEntryInteractor#isUnlocked` remains
-     * `true` even when the lockscreen is showing and still needs to be dismissed by the user to
-     * proceed.
      */
-    suspend fun getAuthenticationMethod(): DomainLayerAuthenticationMethodModel {
-        return repository.getAuthenticationMethod().toDomainLayer()
-    }
+    suspend fun getAuthenticationMethod() = repository.getAuthenticationMethod()
 
     /**
      * Attempts to authenticate the user and unlock the device.
@@ -205,13 +198,13 @@ constructor(
                 // attempt.
                 isThrottled.value -> true
                 // The pattern is too short; skip the attempt.
-                authMethod == DomainLayerAuthenticationMethodModel.Pattern &&
+                authMethod == AuthenticationMethodModel.Pattern &&
                     input.size < repository.minPatternLength -> true
                 // Auto-confirm attempt when the feature is not enabled; skip the attempt.
                 tryAutoConfirm && !isAutoConfirmEnabled.value -> true
                 // Auto-confirm should skip the attempt if the pin entered is too short.
                 tryAutoConfirm &&
-                    authMethod == DomainLayerAuthenticationMethodModel.Pin &&
+                    authMethod == AuthenticationMethodModel.Pin &&
                     input.size < repository.getPinLength() -> true
                 else -> false
             }
@@ -297,15 +290,15 @@ constructor(
         }
     }
 
-    private fun DomainLayerAuthenticationMethodModel.createCredential(
+    private fun AuthenticationMethodModel.createCredential(
         input: List<Any>
     ): LockscreenCredential? {
         return when (this) {
-            is DomainLayerAuthenticationMethodModel.Pin ->
+            is AuthenticationMethodModel.Pin ->
                 LockscreenCredential.createPin(input.joinToString(""))
-            is DomainLayerAuthenticationMethodModel.Password ->
+            is AuthenticationMethodModel.Password ->
                 LockscreenCredential.createPassword(input.joinToString(""))
-            is DomainLayerAuthenticationMethodModel.Pattern ->
+            is AuthenticationMethodModel.Pattern ->
                 LockscreenCredential.createPattern(
                     input
                         .map { it as AuthenticationPatternCoordinate }
@@ -315,23 +308,6 @@ constructor(
         }
     }
 
-    private suspend fun DataLayerAuthenticationMethodModel.toDomainLayer():
-        DomainLayerAuthenticationMethodModel {
-        return when (this) {
-            is DataLayerAuthenticationMethodModel.None ->
-                if (deviceEntryRepository.isInsecureLockscreenEnabled()) {
-                    DomainLayerAuthenticationMethodModel.Swipe
-                } else {
-                    DomainLayerAuthenticationMethodModel.None
-                }
-            is DataLayerAuthenticationMethodModel.Pin -> DomainLayerAuthenticationMethodModel.Pin
-            is DataLayerAuthenticationMethodModel.Password ->
-                DomainLayerAuthenticationMethodModel.Password
-            is DataLayerAuthenticationMethodModel.Pattern ->
-                DomainLayerAuthenticationMethodModel.Pattern
-        }
-    }
-
     companion object {
         const val TAG = "AuthenticationInteractor"
     }
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/domain/model/AuthenticationMethodModel.kt b/packages/SystemUI/src/com/android/systemui/authentication/domain/model/AuthenticationMethodModel.kt
deleted file mode 100644
index d7e6099a890824c574154ca5a25906df9955e83d..0000000000000000000000000000000000000000
--- a/packages/SystemUI/src/com/android/systemui/authentication/domain/model/AuthenticationMethodModel.kt
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2023 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.systemui.authentication.domain.model
-
-/** Enumerates all known authentication methods. */
-sealed class AuthenticationMethodModel(
-    /**
-     * Whether the authentication method is considered to be "secure".
-     *
-     * "Secure" authentication methods require authentication to unlock the device. Non-secure auth
-     * methods simply require user dismissal.
-     */
-    open val isSecure: Boolean,
-) {
-    /** There is no authentication method on the device. We shouldn't even show the lock screen. */
-    object None : AuthenticationMethodModel(isSecure = false)
-
-    /** The most basic authentication method. The lock screen can be swiped away when displayed. */
-    object Swipe : AuthenticationMethodModel(isSecure = false)
-
-    object Pin : AuthenticationMethodModel(isSecure = true)
-
-    object Password : AuthenticationMethodModel(isSecure = true)
-
-    object Pattern : AuthenticationMethodModel(isSecure = true)
-}
diff --git a/packages/SystemUI/src/com/android/systemui/authentication/data/model/AuthenticationMethodModel.kt b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt
similarity index 81%
rename from packages/SystemUI/src/com/android/systemui/authentication/data/model/AuthenticationMethodModel.kt
rename to packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt
index 6d23b11e5d66265c06ad8398fe8efc5c9a15fe1f..bb5b81d4d2f738a140170ba8916edf211007841a 100644
--- a/packages/SystemUI/src/com/android/systemui/authentication/data/model/AuthenticationMethodModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/authentication/shared/model/AuthenticationMethodModel.kt
@@ -1,5 +1,5 @@
 /*
- * Copyright 2023 The Android Open Source Project
+ * Copyright (C) 2023 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package com.android.systemui.authentication.data.model
+package com.android.systemui.authentication.shared.model
 
 /** Enumerates all known authentication methods. */
 sealed class AuthenticationMethodModel(
@@ -26,7 +26,10 @@ sealed class AuthenticationMethodModel(
      */
     open val isSecure: Boolean,
 ) {
-    /** There is no authentication method on the device. We shouldn't even show the lock screen. */
+    /**
+     * Device doesn't use a secure authentication method. Either there is no lockscreen or the lock
+     * screen can be swiped away when displayed.
+     */
     object None : AuthenticationMethodModel(isSecure = false)
 
     object Pin : AuthenticationMethodModel(isSecure = true)
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
index b9a913ea866fe02dfc215e385abb3aedca70e99b..4e1cddc63530802a52f0ef491699e9c939537592 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractor.kt
@@ -19,24 +19,22 @@ package com.android.systemui.bouncer.domain.interactor
 import android.content.Context
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
 import com.android.systemui.authentication.domain.interactor.AuthenticationResult
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.bouncer.data.repository.BouncerRepository
 import com.android.systemui.classifier.FalsingClassifier
 import com.android.systemui.classifier.domain.interactor.FalsingInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.res.R
-import com.android.systemui.scene.domain.interactor.SceneInteractor
 import com.android.systemui.scene.shared.flag.SceneContainerFlags
-import com.android.systemui.scene.shared.model.SceneKey
-import com.android.systemui.scene.shared.model.SceneModel
 import com.android.systemui.util.kotlin.pairwise
 import javax.inject.Inject
 import kotlin.time.Duration.Companion.milliseconds
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.async
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.SharedFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
@@ -51,9 +49,7 @@ constructor(
     @Application private val applicationScope: CoroutineScope,
     @Application private val applicationContext: Context,
     private val repository: BouncerRepository,
-    private val deviceEntryInteractor: DeviceEntryInteractor,
     private val authenticationInteractor: AuthenticationInteractor,
-    private val sceneInteractor: SceneInteractor,
     flags: SceneContainerFlags,
     private val falsingInteractor: FalsingInteractor,
 ) {
@@ -100,6 +96,10 @@ constructor(
     val isUserSwitcherVisible: Boolean
         get() = repository.isUserSwitcherVisible
 
+    private val _onImeHidden = MutableSharedFlow<Unit>()
+    /** Provide the onImeHidden events from the bouncer */
+    val onImeHidden: SharedFlow<Unit> = _onImeHidden
+
     init {
         if (flags.isEnabled()) {
             // Clear the message if moved from throttling to no-longer throttling.
@@ -141,32 +141,6 @@ constructor(
         )
     }
 
-    /**
-     * Either shows the bouncer or unlocks the device, if the bouncer doesn't need to be shown.
-     *
-     * @param message An optional message to show to the user in the bouncer.
-     */
-    fun showOrUnlockDevice(
-        message: String? = null,
-    ) {
-        applicationScope.launch {
-            if (deviceEntryInteractor.isAuthenticationRequired()) {
-                repository.setMessage(
-                    message ?: promptMessage(authenticationInteractor.getAuthenticationMethod())
-                )
-                sceneInteractor.changeScene(
-                    scene = SceneModel(SceneKey.Bouncer),
-                    loggingReason = "request to unlock device while authentication required",
-                )
-            } else {
-                sceneInteractor.changeScene(
-                    scene = SceneModel(SceneKey.Gone),
-                    loggingReason = "request to unlock device while authentication isn't required",
-                )
-            }
-        }
-    }
-
     /**
      * Resets the user-facing message back to the default according to the current authentication
      * method.
@@ -212,17 +186,11 @@ constructor(
         return applicationScope
             .async {
                 val authResult = authenticationInteractor.authenticate(input, tryAutoConfirm)
-                when (authResult) {
-                    // Authentication succeeded.
-                    AuthenticationResult.SUCCEEDED ->
-                        sceneInteractor.changeScene(
-                            scene = SceneModel(SceneKey.Gone),
-                            loggingReason = "successful authentication",
-                        )
-                    // Authentication failed.
-                    AuthenticationResult.FAILED -> showErrorMessage()
-                    // Authentication skipped.
-                    AuthenticationResult.SKIPPED -> if (!tryAutoConfirm) showErrorMessage()
+                if (
+                    authResult == AuthenticationResult.FAILED ||
+                        (authResult == AuthenticationResult.SKIPPED && !tryAutoConfirm)
+                ) {
+                    showErrorMessage()
                 }
                 authResult
             }
@@ -242,16 +210,8 @@ constructor(
     }
 
     /** Notifies the interactor that the input method editor has been hidden. */
-    fun onImeHidden() {
-        // If the bouncer is showing, hide it and return to the lockscreen scene.
-        if (sceneInteractor.desiredScene.value.key != SceneKey.Bouncer) {
-            return
-        }
-
-        sceneInteractor.changeScene(
-            scene = SceneModel(SceneKey.Lockscreen),
-            loggingReason = "IME hidden",
-        )
+    suspend fun onImeHidden() {
+        _onImeHidden.emit(Unit)
     }
 
     private fun promptMessage(authMethod: AuthenticationMethodModel): String {
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
index 55bc653fc737415b664c90b2c91eab7669093b0e..f46574ca5bbeeaeabbbe1825c7b7243c8ce174b3 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModel.kt
@@ -18,7 +18,7 @@ package com.android.systemui.bouncer.ui.viewmodel
 
 import android.annotation.StringRes
 import com.android.systemui.authentication.domain.interactor.AuthenticationResult
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -75,7 +75,7 @@ sealed class AuthMethodBouncerViewModel(
      * Notifies that the input method editor (for example, the software keyboard) has been shown or
      * hidden.
      */
-    fun onImeVisibilityChanged(isVisible: Boolean) {
+    suspend fun onImeVisibilityChanged(isVisible: Boolean) {
         if (isImeVisible && !isVisible) {
             interactor.onImeHidden()
         }
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
index 73d15f0f369bc325a585dd38c7d7c4a1e568dc57..09c94c81581bda8d85dc99924ab6d531140cc9e6 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModel.kt
@@ -20,7 +20,7 @@ import android.content.Context
 import android.graphics.Bitmap
 import androidx.core.graphics.drawable.toBitmap
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.bouncer.shared.model.BouncerActionButtonModel
@@ -180,6 +180,19 @@ class BouncerViewModel(
                 initialValue = isSideBySideSupported(authMethodViewModel.value),
             )
 
+    /**
+     * Whether the splitting the UI around the fold seam (where the hinge is on a foldable device)
+     * is required.
+     */
+    val isFoldSplitRequired: StateFlow<Boolean> =
+        authMethodViewModel
+            .map { authMethod -> isFoldSplitRequired(authMethod) }
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue = isFoldSplitRequired(authMethodViewModel.value),
+            )
+
     init {
         if (flags.isEnabled()) {
             applicationScope.launch {
@@ -212,6 +225,10 @@ class BouncerViewModel(
         return isUserSwitcherVisible || authMethod !is PasswordBouncerViewModel
     }
 
+    private fun isFoldSplitRequired(authMethod: AuthMethodBouncerViewModel?): Boolean {
+        return authMethod !is PasswordBouncerViewModel
+    }
+
     private fun toMessageViewModel(
         message: String?,
         isThrottled: Boolean,
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
index fe7741930d3317ae79c3c0309c861ee8f5e451cd..a15698e1f90c09c7d7eb81cdc40bdb68aaebc1fb 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModel.kt
@@ -16,7 +16,7 @@
 
 package com.android.systemui.bouncer.ui.viewmodel
 
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.res.R
 import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt
index d301085e823d6e8313d1b8d65592096576c225ad..ed6a48f93d679362787d3b85750a4770636dfceb 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModel.kt
@@ -18,7 +18,7 @@ package com.android.systemui.bouncer.ui.viewmodel
 
 import android.content.Context
 import android.util.TypedValue
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.res.R
diff --git a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
index b90e255267261c652f404a4b7043ac0e44e35d91..2ed0d5d2f6c1fdab9ce5533eac6796dc6c2b74e2 100644
--- a/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModel.kt
@@ -18,7 +18,7 @@ package com.android.systemui.bouncer.ui.viewmodel
 
 import android.content.Context
 import com.android.keyguard.PinShapeAdapter
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.res.R
 import kotlinx.coroutines.CoroutineScope
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
index 1e29e1fa31970d13882a8ecc32cf7f3c6c4fd646..f27bbe6c76242746a26a90bd8dd6b910fe41d9db 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepository.kt
@@ -1,5 +1,6 @@
 package com.android.systemui.deviceentry.data.repository
 
+import android.util.Log
 import com.android.internal.widget.LockPatternUtils
 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
@@ -15,9 +16,12 @@ import javax.inject.Inject
 import kotlinx.coroutines.CoroutineDispatcher
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.channels.awaitClose
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.asStateFlow
 import kotlinx.coroutines.flow.distinctUntilChanged
+import kotlinx.coroutines.flow.onEach
 import kotlinx.coroutines.flow.stateIn
 import kotlinx.coroutines.withContext
 
@@ -35,10 +39,14 @@ interface DeviceEntryRepository {
     val isUnlocked: StateFlow<Boolean>
 
     /**
-     * Whether the lockscreen should be shown when the authentication method is not secure (e.g.
-     * `None` or `Swipe`).
+     * Whether the lockscreen is enabled for the current user. This is `true` whenever the user has
+     * chosen any secure authentication method and even if they set the lockscreen to be dismissed
+     * when the user swipes on it.
      */
-    suspend fun isInsecureLockscreenEnabled(): Boolean
+    suspend fun isLockscreenEnabled(): Boolean
+
+    /** Report successful authentication for device entry. */
+    fun reportSuccessfulAuthentication()
 
     /**
      * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
@@ -67,7 +75,9 @@ constructor(
     keyguardStateController: KeyguardStateController,
 ) : DeviceEntryRepository {
 
-    override val isUnlocked =
+    private val _isUnlocked = MutableStateFlow(false)
+
+    private val isUnlockedReportedByLegacyKeyguard =
         conflatedCallbackFlow {
                 val callback =
                     object : KeyguardStateController.Callback {
@@ -99,19 +109,27 @@ constructor(
                 awaitClose { keyguardStateController.removeCallback(callback) }
             }
             .distinctUntilChanged()
+            .onEach { _isUnlocked.value = it }
             .stateIn(
                 applicationScope,
                 SharingStarted.Eagerly,
                 initialValue = false,
             )
 
-    override suspend fun isInsecureLockscreenEnabled(): Boolean {
+    override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow()
+
+    override suspend fun isLockscreenEnabled(): Boolean {
         return withContext(backgroundDispatcher) {
             val selectedUserId = userRepository.getSelectedUserInfo().id
             !lockPatternUtils.isLockScreenDisabled(selectedUserId)
         }
     }
 
+    override fun reportSuccessfulAuthentication() {
+        Log.d(TAG, "Successful authentication reported.")
+        _isUnlocked.value = true
+    }
+
     override val isBypassEnabled: StateFlow<Boolean> =
         conflatedCallbackFlow {
                 val listener =
diff --git a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
index e872d13bd913f7cea276d3de6b2c1de2ca9bcf52..c3f352932675ca22576f7c76214c0cef47ae45c9 100644
--- a/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt
@@ -17,23 +17,28 @@
 package com.android.systemui.deviceentry.domain.interactor
 
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.data.repository.DeviceEntryRepository
 import com.android.systemui.keyguard.data.repository.DeviceEntryFaceAuthRepository
 import com.android.systemui.keyguard.data.repository.TrustRepository
 import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.flag.SceneContainerFlags
 import com.android.systemui.scene.shared.model.SceneKey
+import com.android.systemui.scene.shared.model.SceneModel
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.combine
 import kotlinx.coroutines.flow.filter
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.merge
+import kotlinx.coroutines.flow.onStart
 import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.launch
 
 /**
  * Hosts application business logic related to device entry.
@@ -48,9 +53,10 @@ constructor(
     @Application private val applicationScope: CoroutineScope,
     repository: DeviceEntryRepository,
     private val authenticationInteractor: AuthenticationInteractor,
-    sceneInteractor: SceneInteractor,
+    private val sceneInteractor: SceneInteractor,
     deviceEntryFaceAuthRepository: DeviceEntryFaceAuthRepository,
     trustRepository: TrustRepository,
+    flags: SceneContainerFlags,
 ) {
     /**
      * Whether the device is unlocked.
@@ -90,28 +96,33 @@ constructor(
             .map { it == SceneKey.Gone }
             .stateIn(
                 scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
+                started = SharingStarted.Eagerly,
                 initialValue = false,
             )
 
     // Authenticated by a TrustAgent like trusted device, location, etc or by face auth.
     private val passivelyAuthenticated =
         merge(
-            trustRepository.isCurrentUserTrusted,
-            deviceEntryFaceAuthRepository.isAuthenticated,
-        )
+                trustRepository.isCurrentUserTrusted,
+                deviceEntryFaceAuthRepository.isAuthenticated,
+            )
+            .onStart { emit(false) }
 
     /**
      * Whether it's currently possible to swipe up to enter the device without requiring
-     * authentication. This returns `false` whenever the lockscreen has been dismissed.
+     * authentication or when the device is already authenticated using a passive authentication
+     * mechanism like face or trust manager. This returns `false` whenever the lockscreen has been
+     * dismissed.
      *
      * Note: `true` doesn't mean the lockscreen is visible. It may be occluded or covered by other
      * UI.
      */
     val canSwipeToEnter =
         combine(
+                // This is true when the user has chosen to show the lockscreen but has not made it
+                // secure.
                 authenticationInteractor.authenticationMethod.map {
-                    it == AuthenticationMethodModel.Swipe
+                    it == AuthenticationMethodModel.None && repository.isLockscreenEnabled()
                 },
                 passivelyAuthenticated,
                 isDeviceEntered
@@ -120,10 +131,36 @@ constructor(
             }
             .stateIn(
                 scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
+                started = SharingStarted.Eagerly,
                 initialValue = false,
             )
 
+    /**
+     * Attempt to enter the device and dismiss the lockscreen. If authentication is required to
+     * unlock the device it will transition to bouncer.
+     */
+    fun attemptDeviceEntry() {
+        // TODO (b/307768356),
+        //       1. Check if the device is already authenticated by trust agent/passive biometrics
+        //       2. show SPFS/UDFPS bouncer if it is available AlternateBouncerInteractor.show
+        //       3. For face auth only setups trigger face auth, delay transitioning to bouncer for
+        //          a small amount of time.
+        //       4. Transition to bouncer scene
+        applicationScope.launch {
+            if (isAuthenticationRequired()) {
+                sceneInteractor.changeScene(
+                    scene = SceneModel(SceneKey.Bouncer),
+                    loggingReason = "request to unlock device while authentication required",
+                )
+            } else {
+                sceneInteractor.changeScene(
+                    scene = SceneModel(SceneKey.Gone),
+                    loggingReason = "request to unlock device while authentication isn't required",
+                )
+            }
+        }
+    }
+
     /**
      * Returns `true` if the device currently requires authentication before entry is granted;
      * `false` if the device can be entered without authenticating first.
@@ -133,10 +170,22 @@ constructor(
     }
 
     /**
-     * Whether lock screen bypass is enabled. When enabled, the lock screen will be automatically
+     * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically
      * dismissed once the authentication challenge is completed. For example, completing a biometric
      * authentication challenge via face unlock or fingerprint sensor can automatically bypass the
-     * lock screen.
+     * lockscreen.
      */
     val isBypassEnabled: StateFlow<Boolean> = repository.isBypassEnabled
+
+    init {
+        if (flags.isEnabled()) {
+            applicationScope.launch {
+                authenticationInteractor.authenticationChallengeResult.collectLatest { successful ->
+                    if (successful) {
+                        repository.reportSuccessfulAuthentication()
+                    }
+                }
+            }
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
index 9edd2c6cf92765bf2fabaf4a71a19f107fd0e126..5993cf10431880ce63d0f10ed095c115c2495a2e 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt
@@ -16,8 +16,8 @@
 
 package com.android.systemui.qs.ui.viewmodel
 
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
 import javax.inject.Inject
 
@@ -26,11 +26,9 @@ import javax.inject.Inject
 class QuickSettingsSceneViewModel
 @Inject
 constructor(
-    private val bouncerInteractor: BouncerInteractor,
+    private val deviceEntryInteractor: DeviceEntryInteractor,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
 ) {
     /** Notifies that some content in quick settings was clicked. */
-    fun onContentClicked() {
-        bouncerInteractor.showOrUnlockDevice()
-    }
+    fun onContentClicked() = deviceEntryInteractor.attemptDeviceEntry()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
index 91b4d1778e1c34b21499abbe2c8931481fbfc137..ca2828b99d95da68b75786a45a7471c16af2981f 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/startable/SceneContainerStartable.kt
@@ -19,8 +19,7 @@
 package com.android.systemui.scene.domain.startable
 
 import com.android.systemui.CoreStartable
-import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.classifier.FalsingCollectorActual
 import com.android.systemui.dagger.SysUISingleton
@@ -45,6 +44,7 @@ import com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_STATUS_B
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.collectLatest
 import kotlinx.coroutines.flow.distinctUntilChanged
 import kotlinx.coroutines.flow.distinctUntilChangedBy
 import kotlinx.coroutines.flow.emptyFlow
@@ -64,7 +64,7 @@ constructor(
     @Application private val applicationScope: CoroutineScope,
     private val sceneInteractor: SceneInteractor,
     private val deviceEntryInteractor: DeviceEntryInteractor,
-    private val authenticationInteractor: AuthenticationInteractor,
+    private val bouncerInteractor: BouncerInteractor,
     private val keyguardInteractor: KeyguardInteractor,
     private val flags: SceneContainerFlags,
     private val sysUiState: SysUiState,
@@ -120,6 +120,17 @@ constructor(
 
     /** Switches between scenes based on ever-changing application state. */
     private fun automaticallySwitchScenes() {
+        applicationScope.launch {
+            // TODO (b/308001302): Move this to a bouncer specific interactor.
+            bouncerInteractor.onImeHidden.collectLatest {
+                if (sceneInteractor.desiredScene.value.key == SceneKey.Bouncer) {
+                    sceneInteractor.changeScene(
+                        scene = SceneModel(SceneKey.Lockscreen),
+                        loggingReason = "IME hidden",
+                    )
+                }
+            }
+        }
         applicationScope.launch {
             deviceEntryInteractor.isUnlocked
                 .mapNotNull { isUnlocked ->
@@ -132,41 +143,41 @@ constructor(
                                     transitionState.toScene,
                                 )
                         }
-                    when {
-                        isUnlocked ->
-                            when {
-                                // When the device becomes unlocked in Bouncer, go to Gone.
-                                renderedScenes.contains(SceneKey.Bouncer) ->
-                                    SceneKey.Gone to "device unlocked in Bouncer scene"
-
-                                // When the device becomes unlocked in Lockscreen, go to Gone if
-                                // bypass is enabled.
-                                renderedScenes.contains(SceneKey.Lockscreen) ->
-                                    if (deviceEntryInteractor.isBypassEnabled.value) {
-                                        SceneKey.Gone to
-                                            "device unlocked in Lockscreen scene with bypass"
-                                    } else {
-                                        null
-                                    }
-
-                                // We got unlocked while on a scene that's not Lockscreen or
-                                // Bouncer, no need to change scenes.
-                                else -> null
-                            }
-
-                        // When the device becomes locked, to Lockscreen.
-                        !isUnlocked ->
-                            when {
-                                // Already on lockscreen or bouncer, no need to change scenes.
-                                renderedScenes.contains(SceneKey.Lockscreen) ||
-                                    renderedScenes.contains(SceneKey.Bouncer) -> null
+                    val isOnLockscreen = renderedScenes.contains(SceneKey.Lockscreen)
+                    val isOnBouncer = renderedScenes.contains(SceneKey.Bouncer)
+                    if (!isUnlocked) {
+                        return@mapNotNull if (isOnLockscreen || isOnBouncer) {
+                            // Already on lockscreen or bouncer, no need to change scenes.
+                            null
+                        } else {
+                            // The device locked while on a scene that's not Lockscreen or Bouncer,
+                            // go to Lockscreen.
+                            SceneKey.Lockscreen to
+                                "device locked in non-Lockscreen and non-Bouncer scene"
+                        }
+                    }
 
-                                // We got locked while on a scene that's not Lockscreen or Bouncer,
-                                // go to Lockscreen.
-                                else ->
-                                    SceneKey.Lockscreen to
-                                        "device locked in non-Lockscreen and non-Bouncer scene"
-                            }
+                    val isBypassEnabled = deviceEntryInteractor.isBypassEnabled.value
+                    val canSwipeToEnter = deviceEntryInteractor.canSwipeToEnter.value
+                    when {
+                        isOnBouncer ->
+                            // When the device becomes unlocked in Bouncer, go to Gone.
+                            SceneKey.Gone to "device was unlocked in Bouncer scene"
+                        isOnLockscreen ->
+                            // The lockscreen should be dismissed automatically in 2 scenarios:
+                            // 1. When face auth bypass is enabled and authentication happens while
+                            //    the user is on the lockscreen.
+                            // 2. Whenever the user authenticates using an active authentication
+                            //    mechanism like fingerprint auth. Since canSwipeToEnter is true
+                            //    when the user is passively authenticated, the false value here
+                            //    when the unlock state changes indicates this is an active
+                            //    authentication attempt.
+                            if (isBypassEnabled || !canSwipeToEnter)
+                                SceneKey.Gone to
+                                    "device has been unlocked on lockscreen with either " +
+                                        "bypass enabled or using an active authentication mechanism"
+                            else null
+                        // Not on lockscreen or bouncer, so remain in the current scene.
                         else -> null
                     }
                 }
@@ -186,24 +197,15 @@ constructor(
                         loggingReason = "device is starting to sleep",
                     )
                 } else {
-                    val authMethod = authenticationInteractor.getAuthenticationMethod()
+                    val canSwipeToEnter = deviceEntryInteractor.canSwipeToEnter.value
                     val isUnlocked = deviceEntryInteractor.isUnlocked.value
-                    when {
-                        authMethod == AuthenticationMethodModel.None -> {
-                            switchToScene(
-                                targetSceneKey = SceneKey.Gone,
-                                loggingReason =
-                                    "device is starting to wake up while auth method is" + " none",
-                            )
-                        }
-                        authMethod.isSecure && isUnlocked -> {
-                            switchToScene(
-                                targetSceneKey = SceneKey.Gone,
-                                loggingReason =
-                                    "device is starting to wake up while unlocked with a" +
-                                        " secure auth method",
-                            )
-                        }
+                    if (isUnlocked && !canSwipeToEnter) {
+                        switchToScene(
+                            targetSceneKey = SceneKey.Gone,
+                            loggingReason =
+                                "device is waking up while unlocked without the ability" +
+                                    " to swipe up on lockscreen to enter.",
+                        )
                     }
                 }
             }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
index 9c5a20189dd2505e41f4d46732590357a54429a7..20b9edee2d7056024227df3ac44338b411d4150a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt
@@ -16,7 +16,6 @@
 
 package com.android.systemui.shade.ui.viewmodel
 
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
@@ -34,8 +33,7 @@ class ShadeSceneViewModel
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    deviceEntryInteractor: DeviceEntryInteractor,
-    private val bouncerInteractor: BouncerInteractor,
+    private val deviceEntryInteractor: DeviceEntryInteractor,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
 ) {
     /** The key of the scene we should switch to when swiping up. */
@@ -60,9 +58,7 @@ constructor(
             )
 
     /** Notifies that some content in the shade was clicked. */
-    fun onContentClicked() {
-        bouncerInteractor.showOrUnlockDevice()
-    }
+    fun onContentClicked() = deviceEntryInteractor.attemptDeviceEntry()
 
     private fun upDestinationSceneKey(
         isUnlocked: Boolean,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
index 3f080c247924eb4d682278d961259c7a086142ed..0e83c78edb1d8d84492908d85315ccaecb2016fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerImpl.java
@@ -680,7 +680,7 @@ public class NotificationLockscreenUserManagerImpl implements
         }
         NotificationEntry entry = mCommonNotifCollectionLazy.get().getEntry(key);
         if (mFeatureFlags.isEnabled(Flags.NOTIF_LS_BACKGROUND_THREAD)) {
-            return entry != null
+            return entry != null && entry.getRanking().getChannel() != null
                     && entry.getRanking().getChannel().getLockscreenVisibility()
                     == Notification.VISIBILITY_PRIVATE;
         } else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/FullScreenIntentDecisionProvider.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/FullScreenIntentDecisionProvider.kt
new file mode 100644
index 0000000000000000000000000000000000000000..6af25439ecc3b57c0ace85546f56f55e6b4f5c7a
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/FullScreenIntentDecisionProvider.kt
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.systemui.statusbar.notification.interruption
+
+import android.app.NotificationManager.IMPORTANCE_HIGH
+import android.os.PowerManager
+import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.StatusBarState.KEYGUARD
+import com.android.systemui.statusbar.notification.collection.NotificationEntry
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.FSI_DEVICE_DREAMING
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.FSI_DEVICE_NOT_INTERACTIVE
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.FSI_DEVICE_NOT_PROVISIONED
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.FSI_KEYGUARD_OCCLUDED
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.FSI_KEYGUARD_SHOWING
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.FSI_LOCKED_SHADE
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_EXPECTED_TO_HUN
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_NOT_IMPORTANT_ENOUGH
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_NO_FULL_SCREEN_INTENT
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_NO_HUN_OR_KEYGUARD
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_PACKAGE_SUSPENDED
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SHOW_STICKY_HUN
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSED_BY_DND
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSED_ONLY_BY_DND
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSIVE_BUBBLE_METADATA
+import com.android.systemui.statusbar.notification.interruption.FullScreenIntentDecisionProvider.DecisionImpl.NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.KeyguardStateController
+
+class FullScreenIntentDecisionProvider(
+    private val deviceProvisionedController: DeviceProvisionedController,
+    private val keyguardStateController: KeyguardStateController,
+    private val powerManager: PowerManager,
+    private val statusBarStateController: StatusBarStateController
+) {
+    interface Decision {
+        val shouldFsi: Boolean
+        val wouldFsiWithoutDnd: Boolean
+        val logReason: String
+    }
+
+    private enum class DecisionImpl(
+        override val shouldFsi: Boolean,
+        override val logReason: String,
+        override val wouldFsiWithoutDnd: Boolean = shouldFsi,
+        val supersedesDnd: Boolean = false
+    ) : Decision {
+        NO_FSI_NO_FULL_SCREEN_INTENT(false, "no full-screen intent", supersedesDnd = true),
+        NO_FSI_SHOW_STICKY_HUN(false, "full-screen intents are disabled", supersedesDnd = true),
+        NO_FSI_NOT_IMPORTANT_ENOUGH(false, "not important enough"),
+        NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR(false, "suppressive group alert behavior"),
+        NO_FSI_SUPPRESSIVE_BUBBLE_METADATA(false, "suppressive bubble metadata"),
+        NO_FSI_PACKAGE_SUSPENDED(false, "package suspended"),
+        FSI_DEVICE_NOT_INTERACTIVE(true, "device is not interactive"),
+        FSI_DEVICE_DREAMING(true, "device is dreaming"),
+        FSI_KEYGUARD_SHOWING(true, "keyguard is showing"),
+        NO_FSI_EXPECTED_TO_HUN(false, "expected to heads-up instead"),
+        FSI_KEYGUARD_OCCLUDED(true, "keyguard is occluded"),
+        FSI_LOCKED_SHADE(true, "locked shade"),
+        FSI_DEVICE_NOT_PROVISIONED(true, "device not provisioned"),
+        NO_FSI_NO_HUN_OR_KEYGUARD(false, "no HUN or keyguard"),
+        NO_FSI_SUPPRESSED_BY_DND(false, "suppressed by DND", wouldFsiWithoutDnd = false),
+        NO_FSI_SUPPRESSED_ONLY_BY_DND(false, "suppressed only by DND", wouldFsiWithoutDnd = true)
+    }
+
+    fun makeFullScreenIntentDecision(entry: NotificationEntry, couldHeadsUp: Boolean): Decision {
+        val reasonWithoutDnd = makeDecisionWithoutDnd(entry, couldHeadsUp)
+
+        val suppressedWithoutDnd = !reasonWithoutDnd.shouldFsi
+        val suppressedByDnd = entry.shouldSuppressFullScreenIntent()
+
+        val reasonWithDnd =
+            when {
+                reasonWithoutDnd.supersedesDnd -> reasonWithoutDnd
+                suppressedByDnd && !suppressedWithoutDnd -> NO_FSI_SUPPRESSED_ONLY_BY_DND
+                suppressedByDnd -> NO_FSI_SUPPRESSED_BY_DND
+                else -> reasonWithoutDnd
+            }
+
+        return reasonWithDnd
+    }
+
+    private fun makeDecisionWithoutDnd(
+        entry: NotificationEntry,
+        couldHeadsUp: Boolean
+    ): DecisionImpl {
+        val sbn = entry.sbn
+        val notification = sbn.notification!!
+
+        if (notification.fullScreenIntent == null) {
+            return if (entry.isStickyAndNotDemoted) {
+                NO_FSI_SHOW_STICKY_HUN
+            } else {
+                NO_FSI_NO_FULL_SCREEN_INTENT
+            }
+        }
+
+        if (entry.importance < IMPORTANCE_HIGH) {
+            return NO_FSI_NOT_IMPORTANT_ENOUGH
+        }
+
+        if (sbn.isGroup && notification.suppressAlertingDueToGrouping()) {
+            return NO_FSI_SUPPRESSIVE_GROUP_ALERT_BEHAVIOR
+        }
+
+        val bubbleMetadata = notification.bubbleMetadata
+        if (bubbleMetadata != null && bubbleMetadata.isNotificationSuppressed) {
+            return NO_FSI_SUPPRESSIVE_BUBBLE_METADATA
+        }
+
+        if (entry.ranking.isSuspended) {
+            return NO_FSI_PACKAGE_SUSPENDED
+        }
+
+        if (!powerManager.isInteractive) {
+            return FSI_DEVICE_NOT_INTERACTIVE
+        }
+
+        if (statusBarStateController.isDreaming) {
+            return FSI_DEVICE_DREAMING
+        }
+
+        if (statusBarStateController.state == KEYGUARD) {
+            return FSI_KEYGUARD_SHOWING
+        }
+
+        if (couldHeadsUp) {
+            return NO_FSI_EXPECTED_TO_HUN
+        }
+
+        if (keyguardStateController.isShowing) {
+            return if (keyguardStateController.isOccluded) {
+                FSI_KEYGUARD_OCCLUDED
+            } else {
+                FSI_LOCKED_SHADE
+            }
+        }
+
+        if (!deviceProvisionedController.isDeviceProvisioned) {
+            return FSI_DEVICE_NOT_PROVISIONED
+        }
+
+        return NO_FSI_NO_HUN_OR_KEYGUARD
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
index 2730683a31c9405e2873efe369c0f293a344085b..9640682a8f39d79d6c5b1ed13cc7ecc600de9cec 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImpl.kt
@@ -18,7 +18,6 @@ package com.android.systemui.statusbar.notification.interruption
 import android.hardware.display.AmbientDisplayConfiguration
 import android.os.Handler
 import android.os.PowerManager
-import android.util.Log
 import com.android.internal.annotations.VisibleForTesting
 import com.android.systemui.dagger.qualifiers.Main
 import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -30,7 +29,9 @@ import com.android.systemui.statusbar.notification.interruption.VisualInterrupti
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PEEK
 import com.android.systemui.statusbar.notification.interruption.VisualInterruptionType.PULSE
 import com.android.systemui.statusbar.policy.BatteryController
+import com.android.systemui.statusbar.policy.DeviceProvisionedController
 import com.android.systemui.statusbar.policy.HeadsUpManager
+import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.settings.GlobalSettings
 import com.android.systemui.util.time.SystemClock
 import javax.inject.Inject
@@ -40,9 +41,11 @@ class VisualInterruptionDecisionProviderImpl
 constructor(
     private val ambientDisplayConfiguration: AmbientDisplayConfiguration,
     private val batteryController: BatteryController,
+    deviceProvisionedController: DeviceProvisionedController,
     private val globalSettings: GlobalSettings,
     private val headsUpManager: HeadsUpManager,
     private val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider,
+    keyguardStateController: KeyguardStateController,
     private val logger: NotificationInterruptLogger,
     @Main private val mainHandler: Handler,
     private val powerManager: PowerManager,
@@ -50,6 +53,36 @@ constructor(
     private val systemClock: SystemClock,
     private val userTracker: UserTracker,
 ) : VisualInterruptionDecisionProvider {
+    private class DecisionImpl(
+        override val shouldInterrupt: Boolean,
+        override val logReason: String
+    ) : Decision
+
+    private class FullScreenIntentDecisionImpl(
+        private val fsiDecision: FullScreenIntentDecisionProvider.Decision
+    ) : FullScreenIntentDecision {
+        override val shouldInterrupt
+            get() = fsiDecision.shouldFsi
+
+        override val wouldInterruptWithoutDnd
+            get() = fsiDecision.wouldFsiWithoutDnd
+
+        override val logReason
+            get() = fsiDecision.logReason
+    }
+
+    private val fullScreenIntentDecisionProvider =
+        FullScreenIntentDecisionProvider(
+            deviceProvisionedController,
+            keyguardStateController,
+            powerManager,
+            statusBarStateController
+        )
+
+    private val legacySuppressors = mutableSetOf<NotificationInterruptSuppressor>()
+    private val conditions = mutableListOf<VisualInterruptionCondition>()
+    private val filters = mutableListOf<VisualInterruptionFilter>()
+
     private var started = false
 
     override fun start() {
@@ -76,24 +109,6 @@ constructor(
         started = true
     }
 
-    private class DecisionImpl(
-        override val shouldInterrupt: Boolean,
-        override val logReason: String
-    ) : Decision
-
-    private class FullScreenIntentDecisionImpl(
-        override val shouldInterrupt: Boolean,
-        override val wouldInterruptWithoutDnd: Boolean,
-        override val logReason: String,
-        val originalEntry: NotificationEntry,
-    ) : FullScreenIntentDecision {
-        var hasBeenLogged = false
-    }
-
-    private val legacySuppressors = mutableSetOf<NotificationInterruptSuppressor>()
-    private val conditions = mutableListOf<VisualInterruptionCondition>()
-    private val filters = mutableListOf<VisualInterruptionFilter>()
-
     override fun addLegacySuppressor(suppressor: NotificationInterruptSuppressor) {
         legacySuppressors.add(suppressor)
     }
@@ -132,32 +147,21 @@ constructor(
         return makeHeadsUpDecision(entry).also { logHeadsUpDecision(entry, it) }
     }
 
+    override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision {
+        check(started)
+        return makeBubbleDecision(entry).also { logBubbleDecision(entry, it) }
+    }
+
     override fun makeUnloggedFullScreenIntentDecision(
         entry: NotificationEntry
     ): FullScreenIntentDecision {
         check(started)
-        return makeFullScreenDecision(entry)
+        return makeFullScreenIntentDecision(entry)
     }
 
     override fun logFullScreenIntentDecision(decision: FullScreenIntentDecision) {
         check(started)
-        val decisionImpl =
-            decision as? FullScreenIntentDecisionImpl
-                ?: run {
-                    Log.wtf(TAG, "Wrong subclass of FullScreenIntentDecision: $decision")
-                    return
-                }
-        if (decision.hasBeenLogged) {
-            Log.wtf(TAG, "Already logged decision: $decision")
-            return
-        }
-        logFullScreenIntentDecision(decisionImpl)
-        decision.hasBeenLogged = true
-    }
-
-    override fun makeAndLogBubbleDecision(entry: NotificationEntry): Decision {
-        check(started)
-        return makeBubbleDecision(entry).also { logBubbleDecision(entry, it) }
+        // Not yet implemented.
     }
 
     private fun makeHeadsUpDecision(entry: NotificationEntry): DecisionImpl {
@@ -234,16 +238,6 @@ constructor(
         return DecisionImpl(shouldInterrupt = true, logReason = "not suppressed")
     }
 
-    private fun makeFullScreenDecision(entry: NotificationEntry): FullScreenIntentDecisionImpl {
-        // Not yet implemented.
-        return FullScreenIntentDecisionImpl(
-            shouldInterrupt = true,
-            wouldInterruptWithoutDnd = true,
-            logReason = "FSI logic not yet implemented in VisualInterruptionDecisionProviderImpl",
-            originalEntry = entry
-        )
-    }
-
     private fun logHeadsUpDecision(entry: NotificationEntry, decision: DecisionImpl) {
         // Not yet implemented.
     }
@@ -252,8 +246,11 @@ constructor(
         // Not yet implemented.
     }
 
-    private fun logFullScreenIntentDecision(decision: FullScreenIntentDecisionImpl) {
-        // Not yet implemented.
+    private fun makeFullScreenIntentDecision(entry: NotificationEntry): FullScreenIntentDecision {
+        val wouldHeadsUp = makeUnloggedHeadsUpDecision(entry).shouldInterrupt
+        val fsiDecision =
+            fullScreenIntentDecisionProvider.makeFullScreenIntentDecision(entry, wouldHeadsUp)
+        return FullScreenIntentDecisionImpl(fsiDecision)
     }
 
     private fun checkSuppressors(entry: NotificationEntry) =
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
index 1d4f2cbe6b64de6551dc84f398df5ca7a5615614..d2f45ae8685a7c5850fc58edbb0ac1c49239151c 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerBaseTest.java
@@ -42,8 +42,8 @@ import com.android.systemui.Flags;
 import com.android.systemui.SysuiTestCase;
 import com.android.systemui.biometrics.AuthController;
 import com.android.systemui.biometrics.AuthRippleController;
-import com.android.systemui.bouncer.domain.interactor.BouncerInteractor;
 import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor;
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor;
 import com.android.systemui.doze.util.BurnInHelperKt;
 import com.android.systemui.dump.DumpManager;
 import com.android.systemui.flags.FakeFeatureFlags;
@@ -78,7 +78,7 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
     protected MockitoSession mStaticMockSession;
 
     protected final SceneTestUtils mSceneTestUtils = new SceneTestUtils(this);
-    protected @Mock BouncerInteractor mBouncerInteractor;
+    protected @Mock DeviceEntryInteractor mDeviceEntryInteractor;
     protected @Mock LockIconView mLockIconView;
     protected @Mock AnimatedStateListDrawable mIconDrawable;
     protected @Mock Context mContext;
@@ -176,7 +176,7 @@ public class LockIconViewControllerBaseTest extends SysuiTestCase {
                 mFeatureFlags,
                 mPrimaryBouncerInteractor,
                 mContext,
-                () -> mBouncerInteractor,
+                () -> mDeviceEntryInteractor,
                 mSceneTestUtils.getSceneContainerFlags()
         );
     }
diff --git a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
index adcec10f9172255e22be76e8b1b6f4a084b754f8..93a5393b41cf0014ab17aaa3d2086b99ba19cee5 100644
--- a/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/keyguard/LockIconViewControllerTest.java
@@ -381,7 +381,7 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest {
 
         // THEN show primary bouncer via keyguard view controller, not scene container
         verify(mKeyguardViewController).showPrimaryBouncer(anyBoolean());
-        verify(mBouncerInteractor, never()).showOrUnlockDevice(any());
+        verify(mDeviceEntryInteractor, never()).attemptDeviceEntry();
     }
 
     @Test
@@ -395,7 +395,7 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest {
 
         // THEN show primary bouncer
         verify(mKeyguardViewController, never()).showPrimaryBouncer(anyBoolean());
-        verify(mBouncerInteractor).showOrUnlockDevice(any());
+        verify(mDeviceEntryInteractor).attemptDeviceEntry();
     }
 
     @Test
@@ -408,6 +408,7 @@ public class LockIconViewControllerTest extends LockIconViewControllerBaseTest {
         mUnderTest.onLongPress();
 
         // THEN don't show primary bouncer
-        verify(mBouncerInteractor, never()).showOrUnlockDevice(any());
+        verify(mDeviceEntryInteractor, never()).attemptDeviceEntry();
+        verify(mKeyguardViewController, never()).showPrimaryBouncer(anyBoolean());
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
index 0c06808b10c9c897861b9f8feddd7ceae8d28e93..ae2ec2ca1fe99c6d9c5e2290da5941d773ba588e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/data/repository/AuthenticationRepositoryTest.kt
@@ -26,7 +26,7 @@ import androidx.test.filters.SmallTest
 import com.android.internal.widget.LockPatternUtils
 import com.android.keyguard.KeyguardSecurityModel
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.coroutines.collectValues
 import com.android.systemui.scene.SceneTestUtils
@@ -127,6 +127,22 @@ class AuthenticationRepositoryTest : SysuiTestCase() {
             assertThat(values.last()).isTrue()
         }
 
+    @Test
+    fun reportAuthenticationAttempt_emitsAuthenticationChallengeResult() =
+        testScope.runTest {
+            val authenticationChallengeResults by
+                collectValues(underTest.authenticationChallengeResult)
+
+            runCurrent()
+            underTest.reportAuthenticationAttempt(true)
+            runCurrent()
+            underTest.reportAuthenticationAttempt(false)
+            runCurrent()
+            underTest.reportAuthenticationAttempt(true)
+
+            assertThat(authenticationChallengeResults).isEqualTo(listOf(true, false, true))
+        }
+
     private fun setSecurityModeAndDispatchBroadcast(
         securityMode: KeyguardSecurityModel.SecurityMode,
     ) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
index 103f2b8ac3136de2414c6db57487e7004aee7bdc..7439db29b5133a4960270da243e373c8a4ea2943 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/authentication/domain/interactor/AuthenticationInteractorTest.kt
@@ -20,9 +20,8 @@ import android.app.admin.DevicePolicyManager
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.coroutines.collectLastValue
@@ -51,33 +50,16 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val authMethod by collectLastValue(underTest.authenticationMethod)
             runCurrent()
-            assertThat(authMethod).isEqualTo(DomainLayerAuthenticationMethodModel.Pin)
-            assertThat(underTest.getAuthenticationMethod())
-                .isEqualTo(DomainLayerAuthenticationMethodModel.Pin)
+            assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Pin)
+            assertThat(underTest.getAuthenticationMethod()).isEqualTo(AuthenticationMethodModel.Pin)
 
             utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Password
+                AuthenticationMethodModel.Password
             )
 
-            assertThat(authMethod).isEqualTo(DomainLayerAuthenticationMethodModel.Password)
+            assertThat(authMethod).isEqualTo(AuthenticationMethodModel.Password)
             assertThat(underTest.getAuthenticationMethod())
-                .isEqualTo(DomainLayerAuthenticationMethodModel.Password)
-        }
-
-    @Test
-    fun authenticationMethod_noneTreatedAsSwipe_whenLockscreenEnabled() =
-        testScope.runTest {
-            val authMethod by collectLastValue(underTest.authenticationMethod)
-            runCurrent()
-
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.None
-            )
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
-
-            assertThat(authMethod).isEqualTo(DomainLayerAuthenticationMethodModel.Swipe)
-            assertThat(underTest.getAuthenticationMethod())
-                .isEqualTo(DomainLayerAuthenticationMethodModel.Swipe)
+                .isEqualTo(AuthenticationMethodModel.Password)
         }
 
     @Test
@@ -86,23 +68,18 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             val authMethod by collectLastValue(underTest.authenticationMethod)
             runCurrent()
 
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.None
-            )
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(false)
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
 
-            assertThat(authMethod).isEqualTo(DomainLayerAuthenticationMethodModel.None)
+            assertThat(authMethod).isEqualTo(AuthenticationMethodModel.None)
             assertThat(underTest.getAuthenticationMethod())
-                .isEqualTo(DomainLayerAuthenticationMethodModel.None)
+                .isEqualTo(AuthenticationMethodModel.None)
         }
 
     @Test
     fun authenticate_withCorrectPin_returnsTrue() =
         testScope.runTest {
             val isThrottled by collectLastValue(underTest.isThrottled)
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
             assertThat(isThrottled).isFalse()
@@ -111,9 +88,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     @Test
     fun authenticate_withIncorrectPin_returnsFalse() =
         testScope.runTest {
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(underTest.authenticate(listOf(9, 8, 7, 6, 5, 4)))
                 .isEqualTo(AuthenticationResult.FAILED)
         }
@@ -121,9 +96,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     @Test(expected = IllegalArgumentException::class)
     fun authenticate_withEmptyPin_throwsException() =
         testScope.runTest {
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             underTest.authenticate(listOf())
         }
 
@@ -132,7 +105,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val pin = List(16) { 9 }
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 overrideCredential(pin)
             }
 
@@ -148,9 +121,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             // If the policy changes, there is work to do in SysUI.
             assertThat(DevicePolicyManager.MAX_PASSWORD_LENGTH).isLessThan(17)
 
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(underTest.authenticate(List(17) { 9 }))
                 .isEqualTo(AuthenticationResult.FAILED)
         }
@@ -160,7 +131,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val isThrottled by collectLastValue(underTest.isThrottled)
             utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Password
+                AuthenticationMethodModel.Password
             )
 
             assertThat(underTest.authenticate("password".toList()))
@@ -172,7 +143,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     fun authenticate_withIncorrectPassword_returnsFalse() =
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Password
+                AuthenticationMethodModel.Password
             )
 
             assertThat(underTest.authenticate("alohomora".toList()))
@@ -183,7 +154,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     fun authenticate_withCorrectPattern_returnsTrue() =
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pattern
+                AuthenticationMethodModel.Pattern
             )
 
             assertThat(underTest.authenticate(FakeAuthenticationRepository.PATTERN))
@@ -194,7 +165,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
     fun authenticate_withIncorrectPattern_returnsFalse() =
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pattern
+                AuthenticationMethodModel.Pattern
             )
 
             assertThat(
@@ -211,12 +182,12 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNullAndHasNoEffect() =
+    fun tryAutoConfirm_withAutoConfirmPinAndShorterPin_returnsNull() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             val isThrottled by collectLastValue(underTest.isThrottled)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
             }
             assertThat(isAutoConfirmEnabled).isTrue()
@@ -234,11 +205,11 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalseAndDoesNotUnlockDevice() =
+    fun tryAutoConfirm_withAutoConfirmWrongPinCorrectLength_returnsFalse() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
             }
             assertThat(isAutoConfirmEnabled).isTrue()
@@ -250,16 +221,14 @@ class AuthenticationInteractorTest : SysuiTestCase() {
                     )
                 )
                 .isEqualTo(AuthenticationResult.FAILED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalseAndDoesNotUnlockDevice() =
+    fun tryAutoConfirm_withAutoConfirmLongerPin_returnsFalse() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
             }
             assertThat(isAutoConfirmEnabled).isTrue()
@@ -271,16 +240,14 @@ class AuthenticationInteractorTest : SysuiTestCase() {
                     )
                 )
                 .isEqualTo(AuthenticationResult.FAILED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrueAndUnlocksDevice() =
+    fun tryAutoConfirm_withAutoConfirmCorrectPin_returnsTrue() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
             }
             assertThat(isAutoConfirmEnabled).isTrue()
@@ -292,18 +259,16 @@ class AuthenticationInteractorTest : SysuiTestCase() {
                     )
                 )
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isTrue()
         }
 
     @Test
-    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNullAndHasNoEffects() =
+    fun tryAutoConfirm_withAutoConfirmCorrectPinButDuringThrottling_returnsNull() =
         testScope.runTest {
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
             val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
                 setThrottleDuration(42)
             }
@@ -321,10 +286,10 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         }
 
     @Test
-    fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNullAndHasNoEffects() =
+    fun tryAutoConfirm_withoutAutoConfirmButCorrectPin_returnsNull() =
         testScope.runTest {
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(false)
             }
             assertThat(
@@ -334,53 +299,38 @@ class AuthenticationInteractorTest : SysuiTestCase() {
                     )
                 )
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
-    fun tryAutoConfirm_withoutCorrectPassword_returnsNullAndHasNoEffects() =
+    fun tryAutoConfirm_withoutCorrectPassword_returnsNull() =
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Password
+                AuthenticationMethodModel.Password
             )
 
             assertThat(underTest.authenticate("password".toList(), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
-            assertThat(isUnlocked).isFalse()
         }
 
     @Test
     fun throttling() =
         testScope.runTest {
-            val isUnlocked by collectLastValue(utils.deviceEntryRepository.isUnlocked)
             val throttling by collectLastValue(underTest.throttling)
             val isThrottled by collectLastValue(underTest.isThrottled)
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN)
-            assertThat(isUnlocked).isTrue()
-            assertThat(isThrottled).isFalse()
-            assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
-
-            utils.deviceEntryRepository.setUnlocked(false)
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
 
             // Make many wrong attempts, but just shy of what's needed to get throttled:
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING - 1) {
                 underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
-                assertThat(isUnlocked).isFalse()
                 assertThat(isThrottled).isFalse()
                 assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
             }
 
             // Make one more wrong attempt, leading to throttling:
             underTest.authenticate(listOf(5, 6, 7)) // Wrong PIN
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isTrue()
             assertThat(throttling)
                 .isEqualTo(
@@ -394,7 +344,6 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             // Correct PIN, but throttled, so doesn't attempt it:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isTrue()
             assertThat(throttling)
                 .isEqualTo(
@@ -427,7 +376,6 @@ class AuthenticationInteractorTest : SysuiTestCase() {
 
             // Move the clock forward one more second, to completely finish the throttling period:
             advanceTimeBy(1000)
-            assertThat(isUnlocked).isFalse()
             assertThat(isThrottled).isFalse()
             assertThat(throttling)
                 .isEqualTo(
@@ -441,7 +389,6 @@ class AuthenticationInteractorTest : SysuiTestCase() {
             // Correct PIN and no longer throttled so unlocks successfully:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(isUnlocked).isTrue()
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
         }
@@ -451,7 +398,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(false)
             }
 
@@ -463,7 +410,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 overrideCredential(
                     buildList {
                         repeat(utils.authenticationRepository.hintedPinLength - 1) { add(it + 1) }
@@ -480,7 +427,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 setAutoConfirmFeatureEnabled(true)
                 overrideCredential(
                     buildList {
@@ -497,7 +444,7 @@ class AuthenticationInteractorTest : SysuiTestCase() {
         testScope.runTest {
             val hintedPinLength by collectLastValue(underTest.hintedPinLength)
             utils.authenticationRepository.apply {
-                setAuthenticationMethod(DataLayerAuthenticationMethodModel.Pin)
+                setAuthenticationMethod(AuthenticationMethodModel.Pin)
                 overrideCredential(
                     buildList {
                         repeat(utils.authenticationRepository.hintedPinLength + 1) { add(it + 1) }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
index 577539620ee3a3eb33c26b7b0d89dd19210a4cb5..6ead0e9dc1f7864e13f19138e806844b743a120b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/domain/interactor/BouncerInteractorTest.kt
@@ -19,16 +19,14 @@ package com.android.systemui.bouncer.domain.interactor
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
 import com.android.systemui.authentication.domain.interactor.AuthenticationResult
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.res.R
 import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.shared.model.SceneKey
-import com.android.systemui.scene.shared.model.SceneModel
 import com.google.common.truth.Truth.assertThat
 import kotlin.math.ceil
 import kotlin.time.Duration.Companion.milliseconds
@@ -48,17 +46,9 @@ class BouncerInteractorTest : SysuiTestCase() {
     private val utils = SceneTestUtils(this)
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
-    private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
-        )
     private val underTest =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
         )
 
     @Before
@@ -74,16 +64,10 @@ class BouncerInteractorTest : SysuiTestCase() {
     @Test
     fun pinAuthMethod() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(underTest.message)
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
-
             underTest.clearMessage()
             assertThat(message).isEmpty()
 
@@ -94,7 +78,6 @@ class BouncerInteractorTest : SysuiTestCase() {
             assertThat(underTest.authenticate(listOf(9, 8, 7)))
                 .isEqualTo(AuthenticationResult.FAILED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PIN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
@@ -102,37 +85,25 @@ class BouncerInteractorTest : SysuiTestCase() {
             // Correct input.
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
         }
 
     @Test
     fun pinAuthMethod_tryAutoConfirm_withAutoConfirmPin() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            val message by collectLastValue(underTest.message)
             val isAutoConfirmEnabled by collectLastValue(underTest.isAutoConfirmEnabled)
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
             utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
             assertThat(isAutoConfirmEnabled).isTrue()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
-            underTest.clearMessage()
 
             // Incomplete input.
             assertThat(underTest.authenticate(listOf(1, 2), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(message).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             // Wrong 6-digit pin
             assertThat(underTest.authenticate(listOf(1, 2, 3, 5, 5, 6), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.FAILED)
-            assertThat(message).isEqualTo(MESSAGE_WRONG_PIN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             // Correct input.
             assertThat(
@@ -142,27 +113,20 @@ class BouncerInteractorTest : SysuiTestCase() {
                     )
                 )
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
         }
 
     @Test
     fun pinAuthMethod_tryAutoConfirm_withoutAutoConfirmPin() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(underTest.message)
 
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            underTest.clearMessage()
 
             // Incomplete input.
             assertThat(underTest.authenticate(listOf(1, 2), tryAutoConfirm = true))
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertThat(message).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             // Correct input.
             assertThat(
@@ -173,25 +137,16 @@ class BouncerInteractorTest : SysuiTestCase() {
                 )
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertThat(message).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
     fun passwordAuthMethod() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(underTest.message)
             utils.authenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Password
             )
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
-
-            underTest.clearMessage()
-            assertThat(message).isEmpty()
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
@@ -200,7 +155,6 @@ class BouncerInteractorTest : SysuiTestCase() {
             assertThat(underTest.authenticate("alohamora".toList()))
                 .isEqualTo(AuthenticationResult.FAILED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PASSWORD)
@@ -208,26 +162,16 @@ class BouncerInteractorTest : SysuiTestCase() {
             // Correct input.
             assertThat(underTest.authenticate("password".toList()))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
         }
 
     @Test
     fun patternAuthMethod() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(underTest.message)
             utils.authenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Pattern
             )
             runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-            underTest.showOrUnlockDevice()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
-
-            underTest.clearMessage()
-            assertThat(message).isEmpty()
-
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
 
@@ -243,7 +187,6 @@ class BouncerInteractorTest : SysuiTestCase() {
             assertThat(wrongPattern.size).isAtLeast(utils.authenticationRepository.minPatternLength)
             assertThat(underTest.authenticate(wrongPattern)).isEqualTo(AuthenticationResult.FAILED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PATTERN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
@@ -257,7 +200,6 @@ class BouncerInteractorTest : SysuiTestCase() {
             assertThat(underTest.authenticate(tooShortPattern))
                 .isEqualTo(AuthenticationResult.SKIPPED)
             assertThat(message).isEqualTo(MESSAGE_WRONG_PATTERN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
 
             underTest.resetMessage()
             assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PATTERN)
@@ -265,51 +207,6 @@ class BouncerInteractorTest : SysuiTestCase() {
             // Correct input.
             assertThat(underTest.authenticate(FakeAuthenticationRepository.PATTERN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-        }
-
-    @Test
-    fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
-        testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            utils.deviceEntryRepository.setUnlocked(true)
-            runCurrent()
-
-            underTest.showOrUnlockDevice()
-
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-        }
-
-    @Test
-    fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
-        testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
-            utils.deviceEntryRepository.setUnlocked(false)
-
-            underTest.showOrUnlockDevice()
-
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
-        }
-
-    @Test
-    fun showOrUnlockDevice_customMessageShown() =
-        testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            val message by collectLastValue(underTest.message)
-            utils.authenticationRepository.setAuthenticationMethod(
-                AuthenticationMethodModel.Password
-            )
-            runCurrent()
-            utils.deviceEntryRepository.setUnlocked(false)
-
-            val customMessage = "Hello there!"
-            underTest.showOrUnlockDevice(customMessage)
-
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(message).isEqualTo(customMessage)
         }
 
     @Test
@@ -318,15 +215,9 @@ class BouncerInteractorTest : SysuiTestCase() {
             val isThrottled by collectLastValue(underTest.isThrottled)
             val throttling by collectLastValue(underTest.throttling)
             val message by collectLastValue(underTest.message)
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            runCurrent()
-            underTest.showOrUnlockDevice()
-            runCurrent()
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
-            assertThat(message).isEqualTo(MESSAGE_ENTER_YOUR_PIN)
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) { times ->
                 // Wrong PIN.
                 assertThat(underTest.authenticate(listOf(6, 7, 8, 9)))
@@ -355,7 +246,6 @@ class BouncerInteractorTest : SysuiTestCase() {
             // Correct PIN, but throttled, so doesn't change away from the bouncer scene:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SKIPPED)
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
             assertTryAgainMessage(
                 message,
                 FakeAuthenticationRepository.THROTTLE_DURATION_MS.milliseconds.inWholeSeconds
@@ -381,42 +271,24 @@ class BouncerInteractorTest : SysuiTestCase() {
                             FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING,
                     )
                 )
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Bouncer)
 
             // Correct PIN and no longer throttled so changes to the Gone scene:
             assertThat(underTest.authenticate(FakeAuthenticationRepository.DEFAULT_PIN))
                 .isEqualTo(AuthenticationResult.SUCCEEDED)
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Gone)
             assertThat(isThrottled).isFalse()
             assertThat(throttling).isEqualTo(AuthenticationThrottlingModel())
         }
 
     @Test
-    fun hide_whenOnBouncerScene_hidesBouncerAndGoesToLockscreenScene() =
-        testScope.runTest {
-            sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "")
-            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "")
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            val bouncerSceneKey = currentScene?.key
-            assertThat(bouncerSceneKey).isEqualTo(SceneKey.Bouncer)
-
-            underTest.onImeHidden()
-
-            assertThat(currentScene?.key).isEqualTo(SceneKey.Lockscreen)
-        }
-
-    @Test
-    fun hide_whenNotOnBouncerScene_doesNothing() =
+    fun imeHiddenEvent_isTriggered() =
         testScope.runTest {
-            sceneInteractor.changeScene(SceneModel(SceneKey.Shade), "")
-            sceneInteractor.onSceneChanged(SceneModel(SceneKey.Shade), "")
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
-            val notBouncerSceneKey = currentScene?.key
-            assertThat(notBouncerSceneKey).isNotEqualTo(SceneKey.Bouncer)
+            val imeHiddenEvent by collectLastValue(underTest.onImeHidden)
+            runCurrent()
 
             underTest.onImeHidden()
+            runCurrent()
 
-            assertThat(currentScene?.key).isEqualTo(notBouncerSceneKey)
+            assertThat(imeHiddenEvent).isNotNull()
         }
 
     private fun assertTryAgainMessage(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
index 8e1f5ac58b683b16c4742d3910ed0d7e005ebeeb..cfcb5457414464faa558f7bfb110542a0bb583bc 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/AuthMethodBouncerViewModelTest.kt
@@ -19,8 +19,8 @@ package com.android.systemui.bouncer.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.scene.SceneTestUtils
 import com.android.systemui.scene.shared.model.SceneKey
@@ -37,23 +37,16 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() {
 
     private val utils = SceneTestUtils(this)
     private val testScope = utils.testScope
-    private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
+    private val bouncerInteractor =
+        utils.bouncerInteractor(
+            authenticationInteractor = utils.authenticationInteractor(),
         )
     private val underTest =
         PinBouncerViewModel(
             applicationContext = context,
             viewModelScope = testScope.backgroundScope,
-            interactor =
-                utils.bouncerInteractor(
-                    deviceEntryInteractor = deviceEntryInteractor,
-                    authenticationInteractor = authenticationInteractor,
-                    sceneInteractor = sceneInteractor,
-                ),
+            interactor = bouncerInteractor,
             isInputEnabled = MutableStateFlow(true),
         )
 
@@ -85,18 +78,14 @@ class AuthMethodBouncerViewModelTest : SysuiTestCase() {
     @Test
     fun onImeVisibilityChanged() =
         testScope.runTest {
-            val desiredScene by collectLastValue(sceneInteractor.desiredScene)
             sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "")
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "")
-            assertThat(desiredScene?.key).isEqualTo(SceneKey.Bouncer)
-
-            underTest.onImeVisibilityChanged(false)
-            assertThat(desiredScene?.key).isEqualTo(SceneKey.Bouncer)
+            val onImeHidden by collectLastValue(bouncerInteractor.onImeHidden)
 
             underTest.onImeVisibilityChanged(true)
-            assertThat(desiredScene?.key).isEqualTo(SceneKey.Bouncer)
+            assertThat(onImeHidden).isNull()
 
             underTest.onImeVisibilityChanged(false)
-            assertThat(desiredScene?.key).isEqualTo(SceneKey.Lockscreen)
+            assertThat(onImeHidden).isNotNull()
         }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
index 6ef518e3ab51c8fad8186fd6e22bd9d995a0a761..f4346b56676ddccb312967d89e0b77520532e29b 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/BouncerViewModelTest.kt
@@ -19,10 +19,8 @@ package com.android.systemui.bouncer.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.Flags
 import com.android.systemui.scene.SceneTestUtils
@@ -48,16 +46,9 @@ class BouncerViewModelTest : SysuiTestCase() {
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val actionButtonInteractor = utils.bouncerActionButtonInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
         )
     private val underTest =
         utils.bouncerViewModel(
@@ -96,8 +87,7 @@ class BouncerViewModelTest : SysuiTestCase() {
     @Test
     fun authMethodChanged_doesNotReuseInstances() =
         testScope.runTest {
-            val seen =
-                mutableMapOf<DomainLayerAuthenticationMethodModel, AuthMethodBouncerViewModel>()
+            val seen = mutableMapOf<AuthenticationMethodModel, AuthMethodBouncerViewModel>()
             val authMethodViewModel: AuthMethodBouncerViewModel? by
                 collectLastValue(underTest.authMethodViewModel)
 
@@ -137,7 +127,7 @@ class BouncerViewModelTest : SysuiTestCase() {
     @Test
     fun authMethodsToTest_returnsCompleteSampleOfAllAuthMethodTypes() {
         assertThat(authMethodsToTest().map { it::class }.toSet())
-            .isEqualTo(DomainLayerAuthenticationMethodModel::class.sealedSubclasses.toSet())
+            .isEqualTo(AuthenticationMethodModel::class.sealedSubclasses.toSet())
     }
 
     @Test
@@ -145,9 +135,7 @@ class BouncerViewModelTest : SysuiTestCase() {
         testScope.runTest {
             val message by collectLastValue(underTest.message)
             val throttling by collectLastValue(bouncerInteractor.throttling)
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(message?.isUpdateAnimated).isTrue()
 
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) {
@@ -170,9 +158,7 @@ class BouncerViewModelTest : SysuiTestCase() {
                     }
                 )
             val throttling by collectLastValue(bouncerInteractor.throttling)
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
             assertThat(isInputEnabled).isTrue()
 
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) {
@@ -189,9 +175,7 @@ class BouncerViewModelTest : SysuiTestCase() {
     fun throttlingDialogMessage() =
         testScope.runTest {
             val throttlingDialogMessage by collectLastValue(underTest.throttlingDialogMessage)
-            utils.authenticationRepository.setAuthenticationMethod(
-                DataLayerAuthenticationMethodModel.Pin
-            )
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
 
             repeat(FakeAuthenticationRepository.MAX_FAILED_AUTH_TRIES_BEFORE_THROTTLING) {
                 // Wrong PIN.
@@ -226,34 +210,29 @@ class BouncerViewModelTest : SysuiTestCase() {
             assertThat(isSideBySideSupported).isFalse()
         }
 
-    private fun authMethodsToTest(): List<DomainLayerAuthenticationMethodModel> {
-        return listOf(
-            DomainLayerAuthenticationMethodModel.None,
-            DomainLayerAuthenticationMethodModel.Swipe,
-            DomainLayerAuthenticationMethodModel.Pin,
-            DomainLayerAuthenticationMethodModel.Password,
-            DomainLayerAuthenticationMethodModel.Pattern,
-        )
-    }
+    @Test
+    fun isFoldSplitRequired() =
+        testScope.runTest {
+            val isFoldSplitRequired by collectLastValue(underTest.isFoldSplitRequired)
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+            assertThat(isFoldSplitRequired).isTrue()
+            utils.authenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Password
+            )
+            assertThat(isFoldSplitRequired).isFalse()
 
-    private fun FakeAuthenticationRepository.setAuthenticationMethod(
-        model: DomainLayerAuthenticationMethodModel,
-    ) {
-        setAuthenticationMethod(
-            when (model) {
-                is DomainLayerAuthenticationMethodModel.None,
-                is DomainLayerAuthenticationMethodModel.Swipe ->
-                    DataLayerAuthenticationMethodModel.None
-                is DomainLayerAuthenticationMethodModel.Pin ->
-                    DataLayerAuthenticationMethodModel.Pin
-                is DomainLayerAuthenticationMethodModel.Password ->
-                    DataLayerAuthenticationMethodModel.Password
-                is DomainLayerAuthenticationMethodModel.Pattern ->
-                    DataLayerAuthenticationMethodModel.Pattern
-            }
-        )
-        utils.deviceEntryRepository.setInsecureLockscreenEnabled(
-            model !is DomainLayerAuthenticationMethodModel.None
+            utils.authenticationRepository.setAuthenticationMethod(
+                AuthenticationMethodModel.Pattern
+            )
+            assertThat(isFoldSplitRequired).isTrue()
+        }
+
+    private fun authMethodsToTest(): List<AuthenticationMethodModel> {
+        return listOf(
+            AuthenticationMethodModel.None,
+            AuthenticationMethodModel.Pin,
+            AuthenticationMethodModel.Password,
+            AuthenticationMethodModel.Pattern,
         )
     }
 }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
index 390742031381f7ecb56165536ae0ee66da61bddb..c498edf0e9715acaaa3441fa980e04d866241cea 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PasswordBouncerViewModelTest.kt
@@ -19,8 +19,7 @@ package com.android.systemui.bouncer.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.res.R
 import com.android.systemui.scene.SceneTestUtils
@@ -46,16 +45,9 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
         )
     private val bouncerViewModel =
         utils.bouncerViewModel(
@@ -88,8 +80,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
             assertThat(message?.text).isEqualTo(ENTER_YOUR_PASSWORD)
             assertThat(password).isEqualTo("")
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(underTest.authenticationMethod)
-                .isEqualTo(DomainAuthenticationMethodModel.Password)
+            assertThat(underTest.authenticationMethod).isEqualTo(AuthenticationMethodModel.Password)
         }
 
     @Test
@@ -110,19 +101,19 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
     @Test
     fun onAuthenticateKeyPressed_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             lockDeviceAndOpenPasswordBouncer()
 
             underTest.onPasswordInputChanged("password")
             underTest.onAuthenticateKeyPressed()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
     fun onAuthenticateKeyPressed_whenWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(bouncerViewModel.message)
             val password by collectLastValue(underTest.password)
             lockDeviceAndOpenPasswordBouncer()
@@ -132,13 +123,11 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
 
             assertThat(password).isEqualTo("")
             assertThat(message?.text).isEqualTo(WRONG_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
     fun onAuthenticateKeyPressed_whenEmpty() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             val message by collectLastValue(bouncerViewModel.message)
             val password by collectLastValue(underTest.password)
             utils.authenticationRepository.setAuthenticationMethod(
@@ -147,7 +136,6 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
             utils.deviceEntryRepository.setUnlocked(false)
             sceneInteractor.changeScene(SceneModel(SceneKey.Bouncer), "reason")
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Bouncer), "reason")
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
             underTest.onShown()
             // Enter nothing.
 
@@ -155,13 +143,13 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
 
             assertThat(password).isEqualTo("")
             assertThat(message?.text).isEqualTo(ENTER_YOUR_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
         }
 
     @Test
     fun onAuthenticateKeyPressed_correctAfterWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val message by collectLastValue(bouncerViewModel.message)
             val password by collectLastValue(underTest.password)
             lockDeviceAndOpenPasswordBouncer()
@@ -171,7 +159,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
             underTest.onAuthenticateKeyPressed()
             assertThat(password).isEqualTo("")
             assertThat(message?.text).isEqualTo(WRONG_PASSWORD)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            assertThat(authResult).isFalse()
 
             // Enter the correct password:
             underTest.onPasswordInputChanged("password")
@@ -179,7 +167,7 @@ class PasswordBouncerViewModelTest : SysuiTestCase() {
 
             underTest.onAuthenticateKeyPressed()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
index 47db4f8faeca041e0521571cda62515386a723fb..3f5ddba2316545710ba6b8a59fd77f8369b09b4e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PatternBouncerViewModelTest.kt
@@ -19,9 +19,8 @@ package com.android.systemui.bouncer.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate as Point
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.res.R
@@ -49,16 +48,9 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
     private val testScope = utils.testScope
     private val authenticationInteractor = utils.authenticationInteractor()
     private val sceneInteractor = utils.sceneInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
         )
     private val bouncerViewModel =
         utils.bouncerViewModel(
@@ -96,8 +88,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
             assertThat(selectedDots).isEmpty()
             assertThat(currentDot).isNull()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(underTest.authenticationMethod)
-                .isEqualTo(DomainAuthenticationMethodModel.Pattern)
+            assertThat(underTest.authenticationMethod).isEqualTo(AuthenticationMethodModel.Pattern)
         }
 
     @Test
@@ -120,7 +111,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
     @Test
     fun onDragEnd_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val selectedDots by collectLastValue(underTest.selectedDots)
             val currentDot by collectLastValue(underTest.currentDot)
             lockDeviceAndOpenPatternBouncer()
@@ -150,7 +142,7 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
 
             underTest.onDragEnd()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
@@ -344,7 +336,8 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
     @Test
     fun onDragEnd_correctAfterWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val message by collectLastValue(bouncerViewModel.message)
             val selectedDots by collectLastValue(underTest.selectedDots)
             val currentDot by collectLastValue(underTest.currentDot)
@@ -356,14 +349,14 @@ class PatternBouncerViewModelTest : SysuiTestCase() {
             assertThat(selectedDots).isEmpty()
             assertThat(currentDot).isNull()
             assertThat(message?.text).isEqualTo(WRONG_PATTERN)
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            assertThat(authResult).isFalse()
 
             // Enter the correct pattern:
             CORRECT_PATTERN.forEach(::dragToCoordinate)
 
             underTest.onDragEnd()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     private fun dragOverCoordinates(vararg coordinatesDragged: Point) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
index e07c0b87bc7959062b98a5f62e7e0a317874313a..6da69519000c788af04e9a8479a97206c77b3735 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/bouncer/ui/viewmodel/PinBouncerViewModelTest.kt
@@ -19,9 +19,8 @@ package com.android.systemui.bouncer.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.res.R
 import com.android.systemui.scene.SceneTestUtils
@@ -48,16 +47,9 @@ class PinBouncerViewModelTest : SysuiTestCase() {
     private val testScope = utils.testScope
     private val sceneInteractor = utils.sceneInteractor()
     private val authenticationInteractor = utils.authenticationInteractor()
-    private val deviceEntryInteractor =
-        utils.deviceEntryInteractor(
-            authenticationInteractor = authenticationInteractor,
-            sceneInteractor = utils.sceneInteractor(),
-        )
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
         )
     private val bouncerViewModel =
         utils.bouncerViewModel(
@@ -96,8 +88,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
             assertThat(message?.text).ignoringCase().isEqualTo(ENTER_YOUR_PIN)
             assertThat(pin).isEmpty()
             assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
-            assertThat(underTest.authenticationMethod)
-                .isEqualTo(DomainAuthenticationMethodModel.Pin)
+            assertThat(underTest.authenticationMethod).isEqualTo(AuthenticationMethodModel.Pin)
         }
 
     @Test
@@ -181,7 +172,8 @@ class PinBouncerViewModelTest : SysuiTestCase() {
     @Test
     fun onAuthenticateButtonClicked_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -190,7 +182,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
 
             underTest.onAuthenticateButtonClicked()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
@@ -217,7 +209,8 @@ class PinBouncerViewModelTest : SysuiTestCase() {
     @Test
     fun onAuthenticateButtonClicked_correctAfterWrong() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             val message by collectLastValue(bouncerViewModel.message)
             val pin by collectLastValue(underTest.pinInput.map { it.getPin() })
             lockDeviceAndOpenPinBouncer()
@@ -230,7 +223,7 @@ class PinBouncerViewModelTest : SysuiTestCase() {
             underTest.onAuthenticateButtonClicked()
             assertThat(message?.text).ignoringCase().isEqualTo(WRONG_PIN)
             assertThat(pin).isEmpty()
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Bouncer))
+            assertThat(authResult).isFalse()
 
             // Enter the correct PIN:
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
@@ -240,21 +233,22 @@ class PinBouncerViewModelTest : SysuiTestCase() {
 
             underTest.onAuthenticateButtonClicked()
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
     fun onAutoConfirm_whenCorrect() =
         testScope.runTest {
-            val currentScene by collectLastValue(sceneInteractor.desiredScene)
             utils.authenticationRepository.setAutoConfirmFeatureEnabled(true)
+            val authResult by
+                collectLastValue(authenticationInteractor.authenticationChallengeResult)
             lockDeviceAndOpenPinBouncer()
 
             FakeAuthenticationRepository.DEFAULT_PIN.forEach { digit ->
                 underTest.onPinButtonClicked(digit)
             }
 
-            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+            assertThat(authResult).isTrue()
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
index 2c80035873f0900bb3e4f9a52251b807fb5e1919..97ac8c62d69daefca193c7090bb1f8854c84d0e8 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/data/repository/DeviceEntryRepositoryTest.kt
@@ -83,16 +83,27 @@ class DeviceEntryRepositoryTest : SysuiTestCase() {
         }
 
     @Test
-    fun isInsecureLockscreenEnabled() =
+    fun isLockscreenEnabled() =
         testScope.runTest {
             whenever(lockPatternUtils.isLockScreenDisabled(USER_INFOS[0].id)).thenReturn(false)
             whenever(lockPatternUtils.isLockScreenDisabled(USER_INFOS[1].id)).thenReturn(true)
 
             userRepository.setSelectedUserInfo(USER_INFOS[0])
-            assertThat(underTest.isInsecureLockscreenEnabled()).isTrue()
+            assertThat(underTest.isLockscreenEnabled()).isTrue()
 
             userRepository.setSelectedUserInfo(USER_INFOS[1])
-            assertThat(underTest.isInsecureLockscreenEnabled()).isFalse()
+            assertThat(underTest.isLockscreenEnabled()).isFalse()
+        }
+
+    @Test
+    fun reportSuccessfulAuthentication_shouldUpdateIsUnlocked() =
+        testScope.runTest {
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            assertThat(isUnlocked).isFalse()
+
+            underTest.reportSuccessfulAuthentication()
+
+            assertThat(isUnlocked).isTrue()
         }
 
     @Test
diff --git a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
index aebadc5b5730e25f86b2efca1be06e880b93ef26..abd9f2846d2f4a8220b0a4e2491b4887bbf9d736 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractorTest.kt
@@ -19,7 +19,7 @@ package com.android.systemui.deviceentry.domain.interactor
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
 import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
@@ -60,7 +60,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
             utils.deviceEntryRepository.apply {
-                setInsecureLockscreenEnabled(false)
+                setLockscreenEnabled(false)
 
                 // Toggle isUnlocked, twice.
                 //
@@ -83,8 +83,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     @Test
     fun isUnlocked_whenAuthMethodIsNoneAndLockscreenEnabled_isTrue() =
         testScope.runTest {
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
 
             val isUnlocked by collectLastValue(underTest.isUnlocked)
             assertThat(isUnlocked).isTrue()
@@ -94,8 +93,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     fun isDeviceEntered_onLockscreenWithSwipe_isFalse() =
         testScope.runTest {
             val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
             switchToScene(SceneKey.Lockscreen)
 
             assertThat(isDeviceEntered).isFalse()
@@ -105,8 +103,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     fun isDeviceEntered_onShadeBeforeDismissingLockscreenWithSwipe_isFalse() =
         testScope.runTest {
             val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
             switchToScene(SceneKey.Lockscreen)
             runCurrent()
             switchToScene(SceneKey.Shade)
@@ -118,8 +115,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     fun isDeviceEntered_afterDismissingLockscreenWithSwipe_isTrue() =
         testScope.runTest {
             val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
             switchToScene(SceneKey.Lockscreen)
             runCurrent()
             switchToScene(SceneKey.Gone)
@@ -131,8 +127,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     fun isDeviceEntered_onShadeAfterDismissingLockscreenWithSwipe_isTrue() =
         testScope.runTest {
             val isDeviceEntered by collectLastValue(underTest.isDeviceEntered)
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
             switchToScene(SceneKey.Lockscreen)
             runCurrent()
             switchToScene(SceneKey.Gone)
@@ -148,7 +143,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
             utils.authenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Pattern
             )
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            utils.deviceEntryRepository.setLockscreenEnabled(true)
             switchToScene(SceneKey.Lockscreen)
             runCurrent()
             switchToScene(SceneKey.Bouncer)
@@ -160,8 +155,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     @Test
     fun canSwipeToEnter_onLockscreenWithSwipe_isTrue() =
         testScope.runTest {
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
             switchToScene(SceneKey.Lockscreen)
 
             val canSwipeToEnter by collectLastValue(underTest.canSwipeToEnter)
@@ -172,7 +166,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     fun canSwipeToEnter_onLockscreenWithPin_isFalse() =
         testScope.runTest {
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            utils.deviceEntryRepository.setLockscreenEnabled(true)
             switchToScene(SceneKey.Lockscreen)
 
             val canSwipeToEnter by collectLastValue(underTest.canSwipeToEnter)
@@ -182,8 +176,7 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
     @Test
     fun canSwipeToEnter_afterLockscreenDismissedInSwipeMode_isFalse() =
         testScope.runTest {
-            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            setupSwipeDeviceEntryMethod()
             switchToScene(SceneKey.Lockscreen)
             runCurrent()
             switchToScene(SceneKey.Gone)
@@ -192,6 +185,11 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
             assertThat(canSwipeToEnter).isFalse()
         }
 
+    private fun setupSwipeDeviceEntryMethod() {
+        utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+        utils.deviceEntryRepository.setLockscreenEnabled(true)
+    }
+
     @Test
     fun canSwipeToEnter_whenTrustedByTrustManager_isTrue() =
         testScope.runTest {
@@ -277,6 +275,51 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
             assertThat(underTest.isBypassEnabled.value).isTrue()
         }
 
+    @Test
+    fun showOrUnlockDevice_notLocked_switchesToGoneScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            switchToScene(SceneKey.Lockscreen)
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.Pin)
+            utils.deviceEntryRepository.setUnlocked(true)
+            runCurrent()
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+        }
+
+    @Test
+    fun showOrUnlockDevice_authMethodNotSecure_switchesToGoneScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            switchToScene(SceneKey.Lockscreen)
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+        }
+
+    @Test
+    fun showOrUnlockDevice_authMethodSwipe_switchesToGoneScene() =
+        testScope.runTest {
+            val currentScene by collectLastValue(sceneInteractor.desiredScene)
+            switchToScene(SceneKey.Lockscreen)
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Lockscreen))
+
+            utils.deviceEntryRepository.setLockscreenEnabled(true)
+            utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
+
+            underTest.attemptDeviceEntry()
+
+            assertThat(currentScene).isEqualTo(SceneModel(SceneKey.Gone))
+        }
+
     @Test
     fun isBypassEnabled_disabledInRepository_false() =
         testScope.runTest {
@@ -284,6 +327,17 @@ class DeviceEntryInteractorTest : SysuiTestCase() {
             assertThat(underTest.isBypassEnabled.value).isFalse()
         }
 
+    @Test
+    fun successfulAuthenticationChallengeAttempt_updatedIsUnlockedState() =
+        testScope.runTest {
+            val isUnlocked by collectLastValue(underTest.isUnlocked)
+            assertThat(isUnlocked).isFalse()
+
+            utils.authenticationRepository.reportAuthenticationAttempt(true)
+
+            assertThat(isUnlocked).isTrue()
+        }
+
     private fun switchToScene(sceneKey: SceneKey) {
         sceneInteractor.changeScene(SceneModel(sceneKey), "reason")
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 7de28de4d436316cc04d53ebad173260dd66019f..0b3bc9daa8b7bf3c6415f617af32fe3d8249c3f1 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -19,7 +19,7 @@ package com.android.systemui.keyguard.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.scene.SceneTestUtils
 import com.android.systemui.scene.shared.model.SceneKey
@@ -45,7 +45,7 @@ class LockscreenSceneViewModelTest : SysuiTestCase() {
         testScope.runTest {
             val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            utils.deviceEntryRepository.setLockscreenEnabled(true)
             utils.deviceEntryRepository.setUnlocked(true)
             sceneInteractor.changeScene(SceneModel(SceneKey.Lockscreen), "reason")
 
diff --git a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index a9f82392c7e58b04b2bc016f1cfcaa98498a7769..d582b9e8da5a02d7337193cd597a2e7c7bd2aae5 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -19,7 +19,7 @@ package com.android.systemui.qs.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
@@ -90,13 +90,8 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() {
 
         underTest =
             QuickSettingsSceneViewModel(
-                bouncerInteractor =
-                    utils.bouncerInteractor(
-                        deviceEntryInteractor =
-                            utils.deviceEntryInteractor(
-                                authenticationInteractor = authenticationInteractor,
-                                sceneInteractor = sceneInteractor,
-                            ),
+                deviceEntryInteractor =
+                    utils.deviceEntryInteractor(
                         authenticationInteractor = authenticationInteractor,
                         sceneInteractor = sceneInteractor,
                     ),
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index e84d274b4763895054b14df78fd984183499d78c..d1db9c19cd2b11cc00bad64e3fc47abb3b2ae144 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -26,7 +26,7 @@ import com.android.internal.R
 import com.android.internal.util.EmergencyAffordanceManager
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.bouncer.domain.interactor.BouncerActionButtonInteractor
 import com.android.systemui.bouncer.ui.viewmodel.BouncerViewModel
 import com.android.systemui.bouncer.ui.viewmodel.PinBouncerViewModel
@@ -39,7 +39,6 @@ import com.android.systemui.model.SysUiState
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
-import com.android.systemui.scene.SceneTestUtils.Companion.toDataLayer
 import com.android.systemui.scene.domain.startable.SceneContainerStartable
 import com.android.systemui.scene.shared.model.ObservableTransitionState
 import com.android.systemui.scene.shared.model.SceneKey
@@ -60,6 +59,7 @@ import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
 import com.google.common.truth.Truth.assertWithMessage
+import junit.framework.Assert.assertTrue
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.Job
 import kotlinx.coroutines.flow.MutableStateFlow
@@ -72,7 +72,6 @@ import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.mockito.Mock
-import org.mockito.Mockito.times
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -135,9 +134,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
 
     private val bouncerInteractor =
         utils.bouncerInteractor(
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
         )
 
     private lateinit var mobileConnectionsRepository: FakeMobileConnectionsRepository
@@ -234,7 +231,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
                 deviceEntryInteractor = deviceEntryInteractor,
-                bouncerInteractor = bouncerInteractor,
                 shadeHeaderViewModel = shadeHeaderViewModel,
             )
 
@@ -247,7 +243,6 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
                 applicationScope = testScope.backgroundScope,
                 sceneInteractor = sceneInteractor,
                 deviceEntryInteractor = deviceEntryInteractor,
-                authenticationInteractor = authenticationInteractor,
                 keyguardInteractor = keyguardInteractor,
                 flags = utils.sceneContainerFlags,
                 sysUiState = sysUiState,
@@ -255,6 +250,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
                 sceneLogger = mock(),
                 falsingCollector = utils.falsingCollector(),
                 powerInteractor = powerInteractor,
+                bouncerInteractor = bouncerInteractor,
             )
         startable.start()
 
@@ -298,7 +294,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     @Test
     fun swipeUpOnLockscreen_withAuthMethodSwipe_dismissesLockscreen() =
         testScope.runTest {
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Swipe)
+            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
 
             val upDestinationSceneKey by
                 collectLastValue(lockscreenSceneViewModel.upDestinationSceneKey)
@@ -312,7 +308,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
         testScope.runTest {
             val upDestinationSceneKey by collectLastValue(shadeSceneViewModel.upDestinationSceneKey)
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Swipe)
+            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
             assertCurrentScene(SceneKey.Lockscreen)
 
             // Emulate a user swipe to the shade scene.
@@ -329,7 +325,8 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenDismissed_goesToGone() =
         testScope.runTest {
             val upDestinationSceneKey by collectLastValue(shadeSceneViewModel.upDestinationSceneKey)
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Swipe)
+            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
+            assertTrue(deviceEntryInteractor.canSwipeToEnter.value)
             assertCurrentScene(SceneKey.Lockscreen)
 
             // Emulate a user swipe to dismiss the lockscreen.
@@ -349,7 +346,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     @Test
     fun withAuthMethodNone_deviceWakeUp_skipsLockscreen() =
         testScope.runTest {
-            setAuthMethod(DomainLayerAuthenticationMethodModel.None)
+            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = false)
             putDeviceToSleep(instantlyLockDevice = false)
             assertCurrentScene(SceneKey.Lockscreen)
 
@@ -360,7 +357,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     @Test
     fun withAuthMethodSwipe_deviceWakeUp_doesNotSkipLockscreen() =
         testScope.runTest {
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Swipe)
+            setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
             putDeviceToSleep(instantlyLockDevice = false)
             assertCurrentScene(SceneKey.Lockscreen)
 
@@ -428,7 +425,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     @Test
     fun dismissingIme_whileOnPasswordBouncer_navigatesToLockscreen() =
         testScope.runTest {
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Password)
+            setAuthMethod(AuthenticationMethodModel.Password)
             val upDestinationSceneKey by
                 collectLastValue(lockscreenSceneViewModel.upDestinationSceneKey)
             assertThat(upDestinationSceneKey).isEqualTo(SceneKey.Bouncer)
@@ -445,7 +442,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     @Test
     fun bouncerActionButtonClick_opensEmergencyServicesDialer() =
         testScope.runTest {
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Password)
+            setAuthMethod(AuthenticationMethodModel.Password)
             val upDestinationSceneKey by
                 collectLastValue(lockscreenSceneViewModel.upDestinationSceneKey)
             assertThat(upDestinationSceneKey).isEqualTo(SceneKey.Bouncer)
@@ -464,7 +461,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     @Test
     fun bouncerActionButtonClick_duringCall_returnsToCall() =
         testScope.runTest {
-            setAuthMethod(DomainLayerAuthenticationMethodModel.Password)
+            setAuthMethod(AuthenticationMethodModel.Password)
             startPhoneCall()
             val upDestinationSceneKey by
                 collectLastValue(lockscreenSceneViewModel.upDestinationSceneKey)
@@ -508,19 +505,19 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
 
     /** Updates the current authentication method and related states in the data layer. */
     private fun TestScope.setAuthMethod(
-        authMethod: DomainLayerAuthenticationMethodModel,
+        authMethod: AuthenticationMethodModel,
+        enableLockscreen: Boolean = true
     ) {
+        if (authMethod.isSecure) {
+            assert(enableLockscreen) {
+                "Lockscreen cannot be disabled with a secure authentication method."
+            }
+        }
         // Set the lockscreen enabled bit _before_ set the auth method as the code picks up on the
         // lockscreen enabled bit _after_ the auth method is changed and the lockscreen enabled bit
         // is not an observable that can trigger a new evaluation.
-        utils.deviceEntryRepository.setInsecureLockscreenEnabled(
-            authMethod !is DomainLayerAuthenticationMethodModel.None
-        )
-        utils.authenticationRepository.setAuthenticationMethod(authMethod.toDataLayer())
-        if (!authMethod.isSecure) {
-            // When the auth method is not secure, the device is never considered locked.
-            utils.deviceEntryRepository.setUnlocked(true)
-        }
+        utils.deviceEntryRepository.setLockscreenEnabled(enableLockscreen)
+        utils.authenticationRepository.setAuthenticationMethod(authMethod)
         runCurrent()
     }
 
@@ -648,6 +645,9 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
 
         emulateUserDrivenTransition(SceneKey.Bouncer)
         enterPin()
+        // This repository state is not changed by the AuthInteractor, it relies on
+        // KeyguardStateController.
+        utils.deviceEntryRepository.setUnlocked(true)
         emulateUiSceneTransition(
             expectedVisible = false,
         )
@@ -707,7 +707,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() {
     }
 
     /** Emulates the dismissal of the IME (soft keyboard). */
-    private fun TestScope.dismissIme(
+    private suspend fun TestScope.dismissIme(
         showImeBeforeDismissing: Boolean = true,
     ) {
         bouncerViewModel.authMethodViewModel.value?.apply {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
index f6362fe528ed3b7f97341d2fa39a3dea88b6df51..2f654e22aec6b3128f5fbf37789ab11b3a7bdcca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/scene/domain/startable/SceneContainerStartableTest.kt
@@ -24,16 +24,15 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.Flags as AconfigFlags
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.classifier.FalsingCollector
 import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.kosmos.testScope
+import com.android.systemui.keyguard.data.repository.FakeDeviceEntryFaceAuthRepository
 import com.android.systemui.model.SysUiState
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
 import com.android.systemui.power.domain.interactor.PowerInteractorFactory
 import com.android.systemui.scene.SceneTestUtils
-import com.android.systemui.scene.SceneTestUtils.Companion.toDataLayer
 import com.android.systemui.scene.shared.model.ObservableTransitionState
 import com.android.systemui.scene.shared.model.SceneKey
 import com.android.systemui.scene.shared.model.SceneModel
@@ -63,8 +62,12 @@ class SceneContainerStartableTest : SysuiTestCase() {
     private val sceneInteractor = utils.sceneInteractor()
     private val sceneContainerFlags = utils.sceneContainerFlags
     private val authenticationInteractor = utils.authenticationInteractor()
+    private val bouncerInteractor =
+        utils.bouncerInteractor(authenticationInteractor = authenticationInteractor)
+    private val faceAuthRepository = FakeDeviceEntryFaceAuthRepository()
     private val deviceEntryInteractor =
         utils.deviceEntryInteractor(
+            faceAuthRepository = faceAuthRepository,
             authenticationInteractor = authenticationInteractor,
             sceneInteractor = sceneInteractor,
         )
@@ -78,7 +81,6 @@ class SceneContainerStartableTest : SysuiTestCase() {
             applicationScope = testScope.backgroundScope,
             sceneInteractor = sceneInteractor,
             deviceEntryInteractor = deviceEntryInteractor,
-            authenticationInteractor = authenticationInteractor,
             keyguardInteractor = keyguardInteractor,
             flags = sceneContainerFlags,
             sysUiState = sysUiState,
@@ -86,6 +88,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
             sceneLogger = mock(),
             falsingCollector = falsingCollector,
             powerInteractor = powerInteractor,
+            bouncerInteractor = bouncerInteractor,
         )
 
     @Before
@@ -198,11 +201,54 @@ class SceneContainerStartableTest : SysuiTestCase() {
             assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
             underTest.start()
 
+            // Authenticate using a passive auth method like face auth while bypass is disabled.
+            faceAuthRepository.isAuthenticated.value = true
             utils.deviceEntryRepository.setUnlocked(true)
 
             assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
         }
 
+    @Test
+    fun stayOnCurrentSceneWhenDeviceIsUnlockedAndUserIsNotOnLockscreen() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
+            val transitionStateFlowValue =
+                prepareState(
+                    isBypassEnabled = true,
+                    authenticationMethod = AuthenticationMethodModel.Pin,
+                    initialSceneKey = SceneKey.Lockscreen,
+                )
+            underTest.start()
+            runCurrent()
+
+            sceneInteractor.changeScene(SceneModel(SceneKey.Shade), "switch to shade")
+            transitionStateFlowValue.value = ObservableTransitionState.Idle(SceneKey.Shade)
+            assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+
+            utils.deviceEntryRepository.setUnlocked(true)
+            runCurrent()
+
+            assertThat(currentSceneKey).isEqualTo(SceneKey.Shade)
+        }
+
+    @Test
+    fun switchToGoneWhenDeviceIsUnlockedAndUserIsOnBouncerWithBypassDisabled() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
+            prepareState(
+                isBypassEnabled = false,
+                initialSceneKey = SceneKey.Bouncer,
+            )
+            assertThat(currentSceneKey).isEqualTo(SceneKey.Bouncer)
+            underTest.start()
+
+            // Authenticate using a passive auth method like face auth while bypass is disabled.
+            faceAuthRepository.isAuthenticated.value = true
+            utils.deviceEntryRepository.setUnlocked(true)
+
+            assertThat(currentSceneKey).isEqualTo(SceneKey.Gone)
+        }
+
     @Test
     fun switchToLockscreenWhenDeviceSleepsLocked() =
         testScope.runTest {
@@ -255,6 +301,7 @@ class SceneContainerStartableTest : SysuiTestCase() {
             prepareState(
                 initialSceneKey = SceneKey.Lockscreen,
                 authenticationMethod = AuthenticationMethodModel.None,
+                isLockscreenEnabled = false,
             )
             assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
             underTest.start()
@@ -269,7 +316,8 @@ class SceneContainerStartableTest : SysuiTestCase() {
             val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
             prepareState(
                 initialSceneKey = SceneKey.Lockscreen,
-                authenticationMethod = AuthenticationMethodModel.Swipe,
+                authenticationMethod = AuthenticationMethodModel.None,
+                isLockscreenEnabled = true,
             )
             assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
             underTest.start()
@@ -405,6 +453,24 @@ class SceneContainerStartableTest : SysuiTestCase() {
             verify(falsingCollector, times(2)).setShowingAod(false)
         }
 
+    @Test
+    fun bouncerImeHidden_shouldTransitionBackToLockscreen() =
+        testScope.runTest {
+            val currentSceneKey by collectLastValue(sceneInteractor.desiredScene.map { it.key })
+            prepareState(
+                initialSceneKey = SceneKey.Lockscreen,
+                authenticationMethod = AuthenticationMethodModel.Password,
+                isDeviceUnlocked = false,
+            )
+            underTest.start()
+            runCurrent()
+
+            bouncerInteractor.onImeHidden()
+            runCurrent()
+
+            assertThat(currentSceneKey).isEqualTo(SceneKey.Lockscreen)
+        }
+
     @Test
     fun collectFalsingSignals_screenOnAndOff_aodUnavailable() =
         testScope.runTest {
@@ -526,8 +592,14 @@ class SceneContainerStartableTest : SysuiTestCase() {
         isBypassEnabled: Boolean = false,
         initialSceneKey: SceneKey? = null,
         authenticationMethod: AuthenticationMethodModel? = null,
+        isLockscreenEnabled: Boolean = true,
         startsAwake: Boolean = true,
     ): MutableStateFlow<ObservableTransitionState> {
+        if (authenticationMethod?.isSecure == true) {
+            assert(isLockscreenEnabled) {
+                "Lockscreen cannot be disabled while having a secure authentication method"
+            }
+        }
         sceneContainerFlags.enabled = true
         utils.deviceEntryRepository.setUnlocked(isDeviceUnlocked)
         utils.deviceEntryRepository.setBypassEnabled(isBypassEnabled)
@@ -542,11 +614,9 @@ class SceneContainerStartableTest : SysuiTestCase() {
             sceneInteractor.onSceneChanged(SceneModel(it), "reason")
         }
         authenticationMethod?.let {
-            utils.authenticationRepository.setAuthenticationMethod(
-                authenticationMethod.toDataLayer()
-            )
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(
-                authenticationMethod != AuthenticationMethodModel.None
+            utils.authenticationRepository.setAuthenticationMethod(authenticationMethod)
+            utils.deviceEntryRepository.setLockscreenEnabled(
+                isLockscreenEnabled = isLockscreenEnabled
             )
         }
         if (startsAwake) {
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 589f9aeba19f790701fe99b909ad1512f5617c79..fa849fe806c2275865d292f8051f70b71e415ca4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -19,7 +19,7 @@ package com.android.systemui.shade.ui.viewmodel
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.SmallTest
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.flags.FakeFeatureFlagsClassic
 import com.android.systemui.flags.Flags
@@ -96,12 +96,6 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
                 deviceEntryInteractor = deviceEntryInteractor,
-                bouncerInteractor =
-                    utils.bouncerInteractor(
-                        deviceEntryInteractor = deviceEntryInteractor,
-                        authenticationInteractor = authenticationInteractor,
-                        sceneInteractor = sceneInteractor,
-                    ),
                 shadeHeaderViewModel = shadeHeaderViewModel,
             )
     }
@@ -130,7 +124,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
     fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
         testScope.runTest {
             val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            utils.deviceEntryRepository.setLockscreenEnabled(true)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
             sceneInteractor.changeScene(SceneModel(SceneKey.Lockscreen), "reason")
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Lockscreen), "reason")
@@ -142,7 +136,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() {
     fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() =
         testScope.runTest {
             val upTransitionSceneKey by collectLastValue(underTest.upDestinationSceneKey)
-            utils.deviceEntryRepository.setInsecureLockscreenEnabled(true)
+            utils.deviceEntryRepository.setLockscreenEnabled(true)
             utils.authenticationRepository.setAuthenticationMethod(AuthenticationMethodModel.None)
             sceneInteractor.changeScene(SceneModel(SceneKey.Gone), "reason")
             sceneInteractor.onSceneChanged(SceneModel(SceneKey.Gone), "reason")
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
index a1425f811a843697dbb88f1052ed922d8c75b4d1..ae3214267ff584fa29b39a8a6f7e7596f3b31f44 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationLockscreenUserManagerTest.java
@@ -322,6 +322,20 @@ public class NotificationLockscreenUserManagerTest extends SysuiTestCase {
         assertTrue(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
     }
 
+    @Test
+    public void testCurrentUserPrivateNotificationsNullChannel() {
+        // GIVEN current user allows private notifications to show
+        mSettings.putIntForUser(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS, 1,
+                mCurrentUser.id);
+        changeSetting(LOCK_SCREEN_ALLOW_PRIVATE_NOTIFICATIONS);
+
+        mCurrentUserNotif.setRanking(new RankingBuilder(mCurrentUserNotif.getRanking())
+                .setChannel(null)
+                .setVisibilityOverride(VISIBILITY_NO_OVERRIDE).build());
+        // THEN the notification is not redacted
+        assertFalse(mLockscreenUserManager.needsRedaction(mCurrentUserNotif));
+    }
+
     @Test
     public void testWorkPrivateNotificationsRedacted() {
         // GIVEN work profile doesn't private notifications to show
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
index 80d941a40cb54445063cb8a353d6aca9cdaebf0b..722b1704bb18fd746a877c842077ea8280f58af4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderImplTest.kt
@@ -32,9 +32,11 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
         VisualInterruptionDecisionProviderImpl(
             ambientDisplayConfiguration,
             batteryController,
+            deviceProvisionedController,
             globalSettings,
             headsUpManager,
             keyguardNotificationVisibilityProvider,
+            keyguardStateController,
             logger,
             mainHandler,
             powerManager,
@@ -50,6 +52,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekNotSuppressed()
             assertPulseNotSuppressed()
             assertBubbleNotSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -59,6 +62,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekNotSuppressed()
             assertPulseNotSuppressed()
             assertBubbleNotSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -68,6 +72,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekSuppressed()
             assertPulseNotSuppressed()
             assertBubbleNotSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -77,6 +82,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekSuppressed()
             assertPulseNotSuppressed()
             assertBubbleNotSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -86,6 +92,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekNotSuppressed()
             assertPulseSuppressed()
             assertBubbleNotSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -95,6 +102,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekNotSuppressed()
             assertPulseSuppressed()
             assertBubbleNotSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -104,6 +112,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekNotSuppressed()
             assertPulseNotSuppressed()
             assertBubbleSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -113,6 +122,7 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
             assertPeekNotSuppressed()
             assertPulseNotSuppressed()
             assertBubbleSuppressed()
+            assertFsiNotSuppressed()
         }
     }
 
@@ -193,6 +203,10 @@ class VisualInterruptionDecisionProviderImplTest : VisualInterruptionDecisionPro
         assertShouldBubble(buildBubbleEntry())
     }
 
+    private fun assertFsiNotSuppressed() {
+        forEachFsiState { assertShouldFsi(buildFsiEntry()) }
+    }
+
     private fun withCondition(condition: VisualInterruptionCondition, block: () -> Unit) {
         provider.addCondition(condition)
         block()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
index 7f12b22f2b4ec3199bc92c1a2de5d5d2e99acf91..0f298365bbc57f6e69af210f60fac1654606bf86 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/interruption/VisualInterruptionDecisionProviderTestBase.kt
@@ -20,6 +20,7 @@ import android.app.ActivityManager
 import android.app.Notification
 import android.app.Notification.BubbleMetadata
 import android.app.Notification.FLAG_BUBBLE
+import android.app.Notification.FLAG_FSI_REQUESTED_BUT_DENIED
 import android.app.Notification.GROUP_ALERT_ALL
 import android.app.Notification.GROUP_ALERT_CHILDREN
 import android.app.Notification.GROUP_ALERT_SUMMARY
@@ -29,6 +30,7 @@ import android.app.NotificationManager.IMPORTANCE_DEFAULT
 import android.app.NotificationManager.IMPORTANCE_HIGH
 import android.app.NotificationManager.IMPORTANCE_LOW
 import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_AMBIENT
+import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
 import android.app.NotificationManager.Policy.SUPPRESSED_EFFECT_PEEK
 import android.app.NotificationManager.VISIBILITY_NO_OVERRIDE
 import android.app.PendingIntent
@@ -56,18 +58,19 @@ import com.android.systemui.statusbar.notification.NotifPipelineFlags
 import com.android.systemui.statusbar.notification.collection.NotificationEntry
 import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
 import com.android.systemui.statusbar.notification.interruption.NotificationInterruptStateProviderImpl.MAX_HUN_WHEN_AGE_MS
-import com.android.systemui.statusbar.policy.DeviceProvisionedController
+import com.android.systemui.statusbar.policy.FakeDeviceProvisionedController
 import com.android.systemui.statusbar.policy.HeadsUpManager
-import com.android.systemui.statusbar.policy.KeyguardStateController
 import com.android.systemui.util.mockito.any
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.settings.FakeGlobalSettings
 import com.android.systemui.util.time.FakeSystemClock
 import com.android.systemui.utils.leaks.FakeBatteryController
+import com.android.systemui.utils.leaks.FakeKeyguardStateController
 import com.android.systemui.utils.leaks.LeakCheckedTest
 import com.android.systemui.utils.os.FakeHandler
 import junit.framework.Assert.assertFalse
 import junit.framework.Assert.assertTrue
+import org.junit.Assert.assertEquals
 import org.junit.Before
 import org.junit.Test
 import org.mockito.Mockito.`when` as whenever
@@ -77,13 +80,13 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
 
     protected val ambientDisplayConfiguration = FakeAmbientDisplayConfiguration(context)
     protected val batteryController = FakeBatteryController(leakCheck)
-    protected val deviceProvisionedController: DeviceProvisionedController = mock()
+    protected val deviceProvisionedController = FakeDeviceProvisionedController()
     protected val flags: NotifPipelineFlags = mock()
     protected val globalSettings = FakeGlobalSettings()
     protected val headsUpManager: HeadsUpManager = mock()
     protected val keyguardNotificationVisibilityProvider: KeyguardNotificationVisibilityProvider =
         mock()
-    protected val keyguardStateController: KeyguardStateController = mock()
+    protected val keyguardStateController = FakeKeyguardStateController(leakCheck)
     protected val logger: NotificationInterruptLogger = mock()
     protected val mainHandler = FakeHandler(Looper.getMainLooper())
     protected val powerManager: PowerManager = mock()
@@ -137,15 +140,18 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
     }
 
     @Test
-    fun testShouldNotPeek_packageSnoozed() {
+    fun testShouldNotPeek_packageSnoozed_withoutFsi() {
         ensurePeekState { hunSnoozed = true }
         assertShouldNotHeadsUp(buildPeekEntry())
     }
 
     @Test
-    fun testShouldPeek_packageSnoozedButFsi() {
-        ensurePeekState { hunSnoozed = true }
-        assertShouldHeadsUp(buildFsiEntry())
+    fun testShouldPeek_packageSnoozed_withFsi() {
+        val entry = buildFsiEntry()
+        forEachPeekableFsiState {
+            ensurePeekState { hunSnoozed = true }
+            assertShouldHeadsUp(entry)
+        }
     }
 
     @Test
@@ -217,29 +223,31 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
     @Test
     fun testShouldPeek_defaultLegacySuppressor() {
         ensurePeekState()
-        provider.addLegacySuppressor(neverSuppresses)
-        assertShouldHeadsUp(buildPeekEntry())
+        withLegacySuppressor(neverSuppresses) { assertShouldHeadsUp(buildPeekEntry()) }
     }
 
     @Test
     fun testShouldNotPeek_legacySuppressInterruptions() {
         ensurePeekState()
-        provider.addLegacySuppressor(alwaysSuppressesInterruptions)
-        assertShouldNotHeadsUp(buildPeekEntry())
+        withLegacySuppressor(alwaysSuppressesInterruptions) {
+            assertShouldNotHeadsUp(buildPeekEntry())
+        }
     }
 
     @Test
     fun testShouldNotPeek_legacySuppressAwakeInterruptions() {
         ensurePeekState()
-        provider.addLegacySuppressor(alwaysSuppressesAwakeInterruptions)
-        assertShouldNotHeadsUp(buildPeekEntry())
+        withLegacySuppressor(alwaysSuppressesAwakeInterruptions) {
+            assertShouldNotHeadsUp(buildPeekEntry())
+        }
     }
 
     @Test
     fun testShouldNotPeek_legacySuppressAwakeHeadsUp() {
         ensurePeekState()
-        provider.addLegacySuppressor(alwaysSuppressesAwakeHeadsUp)
-        assertShouldNotHeadsUp(buildPeekEntry())
+        withLegacySuppressor(alwaysSuppressesAwakeHeadsUp) {
+            assertShouldNotHeadsUp(buildPeekEntry())
+        }
     }
 
     @Test
@@ -251,29 +259,31 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
     @Test
     fun testShouldPulse_defaultLegacySuppressor() {
         ensurePulseState()
-        provider.addLegacySuppressor(neverSuppresses)
-        assertShouldHeadsUp(buildPulseEntry())
+        withLegacySuppressor(neverSuppresses) { assertShouldHeadsUp(buildPulseEntry()) }
     }
 
     @Test
     fun testShouldNotPulse_legacySuppressInterruptions() {
         ensurePulseState()
-        provider.addLegacySuppressor(alwaysSuppressesInterruptions)
-        assertShouldNotHeadsUp(buildPulseEntry())
+        withLegacySuppressor(alwaysSuppressesInterruptions) {
+            assertShouldNotHeadsUp(buildPulseEntry())
+        }
     }
 
     @Test
     fun testShouldPulse_legacySuppressAwakeInterruptions() {
         ensurePulseState()
-        provider.addLegacySuppressor(alwaysSuppressesAwakeInterruptions)
-        assertShouldHeadsUp(buildPulseEntry())
+        withLegacySuppressor(alwaysSuppressesAwakeInterruptions) {
+            assertShouldHeadsUp(buildPulseEntry())
+        }
     }
 
     @Test
     fun testShouldPulse_legacySuppressAwakeHeadsUp() {
         ensurePulseState()
-        provider.addLegacySuppressor(alwaysSuppressesAwakeHeadsUp)
-        assertShouldHeadsUp(buildPulseEntry())
+        withLegacySuppressor(alwaysSuppressesAwakeHeadsUp) {
+            assertShouldHeadsUp(buildPulseEntry())
+        }
     }
 
     @Test
@@ -439,29 +449,31 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
     @Test
     fun testShouldBubble_defaultLegacySuppressor() {
         ensureBubbleState()
-        provider.addLegacySuppressor(neverSuppresses)
-        assertShouldBubble(buildBubbleEntry())
+        withLegacySuppressor(neverSuppresses) { assertShouldBubble(buildBubbleEntry()) }
     }
 
     @Test
     fun testShouldNotBubble_legacySuppressInterruptions() {
         ensureBubbleState()
-        provider.addLegacySuppressor(alwaysSuppressesInterruptions)
-        assertShouldNotBubble(buildBubbleEntry())
+        withLegacySuppressor(alwaysSuppressesInterruptions) {
+            assertShouldNotBubble(buildBubbleEntry())
+        }
     }
 
     @Test
     fun testShouldNotBubble_legacySuppressAwakeInterruptions() {
         ensureBubbleState()
-        provider.addLegacySuppressor(alwaysSuppressesAwakeInterruptions)
-        assertShouldNotBubble(buildBubbleEntry())
+        withLegacySuppressor(alwaysSuppressesAwakeInterruptions) {
+            assertShouldNotBubble(buildBubbleEntry())
+        }
     }
 
     @Test
     fun testShouldBubble_legacySuppressAwakeHeadsUp() {
         ensureBubbleState()
-        provider.addLegacySuppressor(alwaysSuppressesAwakeHeadsUp)
-        assertShouldBubble(buildBubbleEntry())
+        withLegacySuppressor(alwaysSuppressesAwakeHeadsUp) {
+            assertShouldBubble(buildBubbleEntry())
+        }
     }
 
     @Test
@@ -476,6 +488,107 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
         assertShouldNotBubble(buildBubbleEntry())
     }
 
+    @Test
+    fun testShouldNotFsi_noFullScreenIntent() {
+        forEachFsiState { assertShouldNotFsi(buildFsiEntry { hasFsi = false }) }
+    }
+
+    @Test
+    fun testShouldNotFsi_showStickyHun() {
+        forEachFsiState {
+            assertShouldNotFsi(
+                buildFsiEntry {
+                    hasFsi = false
+                    isStickyAndNotDemoted = true
+                }
+            )
+        }
+    }
+
+    @Test
+    fun testShouldNotFsi_onlyDnd() {
+        forEachFsiState {
+            assertShouldNotFsi(
+                buildFsiEntry { suppressedVisualEffects = SUPPRESSED_EFFECT_FULL_SCREEN_INTENT },
+                expectWouldInterruptWithoutDnd = true
+            )
+        }
+    }
+
+    @Test
+    fun testShouldNotFsi_notImportantEnough() {
+        forEachFsiState { assertShouldNotFsi(buildFsiEntry { importance = IMPORTANCE_DEFAULT }) }
+    }
+
+    @Test
+    fun testShouldNotFsi_notOnlyDnd() {
+        forEachFsiState {
+            assertShouldNotFsi(
+                buildFsiEntry {
+                    suppressedVisualEffects = SUPPRESSED_EFFECT_FULL_SCREEN_INTENT
+                    importance = IMPORTANCE_DEFAULT
+                },
+                expectWouldInterruptWithoutDnd = false
+            )
+        }
+    }
+
+    @Test
+    fun testShouldNotFsi_suppressiveGroupAlertBehavior() {
+        forEachFsiState {
+            assertShouldNotFsi(
+                buildFsiEntry {
+                    isGrouped = true
+                    isGroupSummary = true
+                    groupAlertBehavior = GROUP_ALERT_CHILDREN
+                }
+            )
+        }
+    }
+
+    @Test
+    fun testShouldFsi_suppressiveGroupAlertBehavior_notGrouped() {
+        forEachFsiState {
+            assertShouldFsi(
+                buildFsiEntry {
+                    isGrouped = false
+                    isGroupSummary = true
+                    groupAlertBehavior = GROUP_ALERT_CHILDREN
+                }
+            )
+        }
+    }
+
+    @Test
+    fun testShouldFsi_suppressiveGroupAlertBehavior_notSuppressive() {
+        forEachFsiState {
+            assertShouldFsi(
+                buildFsiEntry {
+                    isGrouped = true
+                    isGroupSummary = true
+                    groupAlertBehavior = GROUP_ALERT_ALL
+                }
+            )
+        }
+    }
+
+    @Test
+    fun testShouldNotFsi_suppressiveBubbleMetadata() {
+        forEachFsiState {
+            assertShouldNotFsi(
+                buildFsiEntry {
+                    hasBubbleMetadata = true
+                    bubbleSuppressesNotification = true
+                }
+            )
+        }
+    }
+
+    @Test
+    fun testShouldNotFsi_packageSuspended() {
+        forEachFsiState { assertShouldNotFsi(buildFsiEntry { packageSuspended = true }) }
+    }
+
     @Test
     fun testShouldFsi_notInteractive() {
         ensureNotInteractiveFsiState()
@@ -494,6 +607,76 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
         assertShouldFsi(buildFsiEntry())
     }
 
+    @Test
+    fun testShouldNotFsi_expectedToHun() {
+        forEachPeekableFsiState {
+            ensurePeekState()
+            assertShouldNotFsi(buildFsiEntry())
+        }
+    }
+
+    @Test
+    fun testShouldNotFsi_expectedToHun_hunSnoozed() {
+        forEachPeekableFsiState {
+            ensurePeekState { hunSnoozed = true }
+            assertShouldNotFsi(buildFsiEntry())
+        }
+    }
+
+    @Test
+    fun testShouldFsi_lockedShade() {
+        ensureLockedShadeFsiState()
+        assertShouldFsi(buildFsiEntry())
+    }
+
+    @Test
+    fun testShouldFsi_keyguardOccluded() {
+        ensureKeyguardOccludedFsiState()
+        assertShouldFsi(buildFsiEntry())
+    }
+
+    @Test
+    fun testShouldFsi_deviceNotProvisioned() {
+        ensureDeviceNotProvisionedFsiState()
+        assertShouldFsi(buildFsiEntry())
+    }
+
+    @Test
+    fun testShouldNotFsi_noHunOrKeyguard() {
+        ensureNoHunOrKeyguardFsiState()
+        assertShouldNotFsi(buildFsiEntry())
+    }
+
+    @Test
+    fun testShouldFsi_defaultLegacySuppressor() {
+        forEachFsiState {
+            withLegacySuppressor(neverSuppresses) { assertShouldFsi(buildFsiEntry()) }
+        }
+    }
+
+    @Test
+    fun testShouldFsi_suppressInterruptions() {
+        forEachFsiState {
+            withLegacySuppressor(alwaysSuppressesInterruptions) { assertShouldFsi(buildFsiEntry()) }
+        }
+    }
+
+    @Test
+    fun testShouldFsi_suppressAwakeInterruptions() {
+        forEachFsiState {
+            withLegacySuppressor(alwaysSuppressesAwakeInterruptions) {
+                assertShouldFsi(buildFsiEntry())
+            }
+        }
+    }
+
+    @Test
+    fun testShouldFsi_suppressAwakeHeadsUp() {
+        forEachFsiState {
+            withLegacySuppressor(alwaysSuppressesAwakeHeadsUp) { assertShouldFsi(buildFsiEntry()) }
+        }
+    }
+
     protected data class State(
         var hunSettingEnabled: Boolean? = null,
         var hunSnoozed: Boolean? = null,
@@ -505,6 +688,9 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
         var keyguardShouldHideNotification: Boolean? = null,
         var pulseOnNotificationsEnabled: Boolean? = null,
         var statusBarState: Int? = null,
+        var keyguardIsShowing: Boolean = false,
+        var keyguardIsOccluded: Boolean = false,
+        var deviceProvisioned: Boolean = true
     )
 
     protected fun setState(state: State): Unit =
@@ -536,6 +722,11 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
             }
 
             statusBarState?.let { statusBarStateController.state = it }
+
+            keyguardStateController.isOccluded = keyguardIsOccluded
+            keyguardStateController.isShowing = keyguardIsShowing
+
+            deviceProvisionedController.deviceProvisioned = deviceProvisioned
         }
 
     protected fun ensureState(block: State.() -> Unit) =
@@ -565,26 +756,104 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
     protected fun ensureBubbleState(block: State.() -> Unit = {}) = ensureState(block)
 
     protected fun ensureNotInteractiveFsiState(block: State.() -> Unit = {}) = ensureState {
-        isDreaming = false
         isInteractive = false
-        statusBarState = SHADE
         run(block)
     }
 
     protected fun ensureDreamingFsiState(block: State.() -> Unit = {}) = ensureState {
+        isInteractive = true
         isDreaming = true
+        run(block)
+    }
+
+    protected fun ensureKeyguardFsiState(block: State.() -> Unit = {}) = ensureState {
+        isInteractive = true
+        isDreaming = false
+        statusBarState = KEYGUARD
+        run(block)
+    }
+
+    protected fun ensureLockedShadeFsiState(block: State.() -> Unit = {}) = ensureState {
+        // It is assumed *but not checked in the code* that statusBarState is SHADE_LOCKED.
         isInteractive = true
+        isDreaming = false
         statusBarState = SHADE
+        hunSettingEnabled = false
+        keyguardIsShowing = true
+        keyguardIsOccluded = false
         run(block)
     }
 
-    protected fun ensureKeyguardFsiState(block: State.() -> Unit = {}) = ensureState {
+    protected fun ensureKeyguardOccludedFsiState(block: State.() -> Unit = {}) = ensureState {
+        isInteractive = true
         isDreaming = false
+        statusBarState = SHADE
+        hunSettingEnabled = false
+        keyguardIsShowing = true
+        keyguardIsOccluded = true
+        run(block)
+    }
+
+    protected fun ensureDeviceNotProvisionedFsiState(block: State.() -> Unit = {}) = ensureState {
         isInteractive = true
-        statusBarState = KEYGUARD
+        isDreaming = false
+        statusBarState = SHADE
+        hunSettingEnabled = false
+        keyguardIsShowing = false
+        deviceProvisioned = false
+        run(block)
+    }
+
+    protected fun ensureNoHunOrKeyguardFsiState(block: State.() -> Unit = {}) = ensureState {
+        isInteractive = true
+        isDreaming = false
+        statusBarState = SHADE
+        hunSettingEnabled = false
+        keyguardIsShowing = false
+        deviceProvisioned = true
         run(block)
     }
 
+    protected fun forEachFsiState(block: () -> Unit) {
+        ensureNotInteractiveFsiState()
+        block()
+
+        ensureDreamingFsiState()
+        block()
+
+        ensureKeyguardFsiState()
+        block()
+
+        ensureLockedShadeFsiState()
+        block()
+
+        ensureKeyguardOccludedFsiState()
+        block()
+
+        ensureDeviceNotProvisionedFsiState()
+        block()
+    }
+
+    private fun forEachPeekableFsiState(extendState: State.() -> Unit = {}, block: () -> Unit) {
+        ensureLockedShadeFsiState(extendState)
+        block()
+
+        ensureKeyguardOccludedFsiState(extendState)
+        block()
+
+        ensureDeviceNotProvisionedFsiState(extendState)
+        block()
+    }
+
+    protected fun withLegacySuppressor(
+        suppressor: NotificationInterruptSuppressor,
+        block: () -> Unit
+    ) {
+        provider.addLegacySuppressor(suppressor)
+        block()
+        provider.removeLegacySuppressor(suppressor)
+    }
+
     protected fun assertShouldHeadsUp(entry: NotificationEntry) =
         provider.makeUnloggedHeadsUpDecision(entry).let {
             assertTrue("unexpected suppressed HUN: ${it.logReason}", it.shouldInterrupt)
@@ -610,9 +879,19 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
             assertTrue("unexpected suppressed FSI: ${it.logReason}", it.shouldInterrupt)
         }
 
-    protected fun assertShouldNotFsi(entry: NotificationEntry) =
+    protected fun assertShouldNotFsi(
+        entry: NotificationEntry,
+        expectWouldInterruptWithoutDnd: Boolean? = null
+    ) =
         provider.makeUnloggedFullScreenIntentDecision(entry).let {
             assertFalse("unexpected unsuppressed FSI: ${it.logReason}", it.shouldInterrupt)
+            if (expectWouldInterruptWithoutDnd != null) {
+                assertEquals(
+                    "unexpected unsuppressed-without-DND FSI: ${it.logReason}",
+                    expectWouldInterruptWithoutDnd,
+                    it.wouldInterruptWithoutDnd
+                )
+            }
         }
 
     protected class EntryBuilder(val context: Context) {
@@ -630,6 +909,8 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
         var isGroupSummary: Boolean? = null
         var groupAlertBehavior: Int? = null
         var hasJustLaunchedFsi = false
+        var isStickyAndNotDemoted = false
+        var packageSuspended: Boolean? = null
 
         private fun buildBubbleMetadata(): BubbleMetadata {
             val builder =
@@ -681,6 +962,10 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
                     if (isBubble) {
                         flags = flags or FLAG_BUBBLE
                     }
+
+                    if (isStickyAndNotDemoted) {
+                        flags = flags or FLAG_FSI_REQUESTED_BUT_DENIED
+                    }
                 }
                 .let { NotificationEntryBuilder().setNotification(it) }
                 .apply {
@@ -699,10 +984,15 @@ abstract class VisualInterruptionDecisionProviderTestBase : SysuiTestCase() {
                         it.notifyFullScreenIntentLaunched()
                     }
 
+                    if (isStickyAndNotDemoted) {
+                        assertFalse(it.isDemoted)
+                    }
+
                     modifyRanking(it)
                         .apply {
                             suppressedVisualEffects?.let { setSuppressedVisualEffects(it) }
                             visibilityOverride?.let { setVisibilityOverride(it) }
+                            packageSuspended?.let { setSuspended(it) }
                         }
                         .build()
                 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
index 81c5d9c248f3194ff9c86e5bb9649eaef02b2501..6e9363b744ab4571760cfe73042fe7b7148543b8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/authentication/data/repository/FakeAuthenticationRepository.kt
@@ -20,16 +20,16 @@ import com.android.internal.widget.LockPatternUtils
 import com.android.internal.widget.LockPatternView
 import com.android.internal.widget.LockscreenCredential
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel
+import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
 import com.android.systemui.authentication.shared.model.AuthenticationPatternCoordinate
 import com.android.systemui.authentication.shared.model.AuthenticationResultModel
 import com.android.systemui.authentication.shared.model.AuthenticationThrottlingModel
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
 import dagger.Binds
 import dagger.Module
 import dagger.Provides
 import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableSharedFlow
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.asStateFlow
@@ -37,13 +37,13 @@ import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.currentTime
 
 class FakeAuthenticationRepository(
-    private val deviceEntryRepository: FakeDeviceEntryRepository,
     private val currentTime: () -> Long,
 ) : AuthenticationRepository {
 
     private val _isAutoConfirmFeatureEnabled = MutableStateFlow(false)
     override val isAutoConfirmFeatureEnabled: StateFlow<Boolean> =
         _isAutoConfirmFeatureEnabled.asStateFlow()
+    override val authenticationChallengeResult = MutableSharedFlow<Boolean>()
 
     override val hintedPinLength: Int = HINTING_PIN_LENGTH
 
@@ -80,7 +80,7 @@ class FakeAuthenticationRepository(
 
     override suspend fun reportAuthenticationAttempt(isSuccessful: Boolean) {
         failedAttemptCount = if (isSuccessful) 0 else failedAttemptCount + 1
-        deviceEntryRepository.setUnlocked(isSuccessful)
+        authenticationChallengeResult.emit(isSuccessful)
     }
 
     override suspend fun getPinLength(): Int {
@@ -216,9 +216,8 @@ object FakeAuthenticationRepositoryModule {
     @Provides
     @SysUISingleton
     fun provideFake(
-        deviceEntryRepository: FakeDeviceEntryRepository,
         scope: TestScope,
-    ) = FakeAuthenticationRepository(deviceEntryRepository, currentTime = { scope.currentTime })
+    ) = FakeAuthenticationRepository(currentTime = { scope.currentTime })
 
     @Module
     interface Bindings {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
index f0293489cb871be53098b80f51442f471e984533..ba70d46fd954daf59e00e3e482922176af9e33d3 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/deviceentry/data/repository/FakeDeviceEntryRepository.kt
@@ -27,7 +27,7 @@ import kotlinx.coroutines.flow.asStateFlow
 @SysUISingleton
 class FakeDeviceEntryRepository @Inject constructor() : DeviceEntryRepository {
 
-    private var isInsecureLockscreenEnabled = true
+    private var isLockscreenEnabled = true
 
     private val _isBypassEnabled = MutableStateFlow(false)
     override val isBypassEnabled: StateFlow<Boolean> = _isBypassEnabled
@@ -35,16 +35,20 @@ class FakeDeviceEntryRepository @Inject constructor() : DeviceEntryRepository {
     private val _isUnlocked = MutableStateFlow(false)
     override val isUnlocked: StateFlow<Boolean> = _isUnlocked.asStateFlow()
 
-    override suspend fun isInsecureLockscreenEnabled(): Boolean {
-        return isInsecureLockscreenEnabled
+    override suspend fun isLockscreenEnabled(): Boolean {
+        return isLockscreenEnabled
+    }
+
+    override fun reportSuccessfulAuthentication() {
+        _isUnlocked.value = true
     }
 
     fun setUnlocked(isUnlocked: Boolean) {
         _isUnlocked.value = isUnlocked
     }
 
-    fun setInsecureLockscreenEnabled(isLockscreenEnabled: Boolean) {
-        this.isInsecureLockscreenEnabled = isLockscreenEnabled
+    fun setLockscreenEnabled(isLockscreenEnabled: Boolean) {
+        this.isLockscreenEnabled = isLockscreenEnabled
     }
 
     fun setBypassEnabled(isBypassEnabled: Boolean) {
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
index 36ec18fc4de4049ec8fa11103fc8a6b5d88087a3..72cc08f03dac1b26b98973787d866cbfb2257574 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/SceneTestUtils.kt
@@ -26,11 +26,9 @@ import android.telecom.TelecomManager
 import com.android.internal.logging.MetricsLogger
 import com.android.internal.util.EmergencyAffordanceManager
 import com.android.systemui.SysuiTestCase
-import com.android.systemui.authentication.data.model.AuthenticationMethodModel as DataLayerAuthenticationMethodModel
 import com.android.systemui.authentication.data.repository.AuthenticationRepository
 import com.android.systemui.authentication.data.repository.FakeAuthenticationRepository
 import com.android.systemui.authentication.domain.interactor.AuthenticationInteractor
-import com.android.systemui.authentication.domain.model.AuthenticationMethodModel as DomainLayerAuthenticationMethodModel
 import com.android.systemui.bouncer.data.repository.BouncerRepository
 import com.android.systemui.bouncer.data.repository.EmergencyServicesRepository
 import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
@@ -110,7 +108,6 @@ class SceneTestUtils(
     val deviceEntryRepository: FakeDeviceEntryRepository by lazy { FakeDeviceEntryRepository() }
     val authenticationRepository: FakeAuthenticationRepository by lazy {
         FakeAuthenticationRepository(
-            deviceEntryRepository = deviceEntryRepository,
             currentTime = { testScope.currentTime },
         )
     }
@@ -181,6 +178,7 @@ class SceneTestUtils(
             sceneInteractor = sceneInteractor,
             deviceEntryFaceAuthRepository = faceAuthRepository,
             trustRepository = trustRepository,
+            flags = FakeSceneContainerFlags(enabled = true)
         )
     }
 
@@ -192,7 +190,6 @@ class SceneTestUtils(
             repository = repository,
             backgroundDispatcher = testDispatcher,
             userRepository = userRepository,
-            deviceEntryRepository = deviceEntryRepository,
             clock = mock { whenever(elapsedRealtime()).thenAnswer { testScope.currentTime } }
         )
     }
@@ -221,17 +218,13 @@ class SceneTestUtils(
     }
 
     fun bouncerInteractor(
-        deviceEntryInteractor: DeviceEntryInteractor,
         authenticationInteractor: AuthenticationInteractor,
-        sceneInteractor: SceneInteractor,
     ): BouncerInteractor {
         return BouncerInteractor(
             applicationScope = applicationScope(),
             applicationContext = context,
             repository = BouncerRepository(featureFlags),
-            deviceEntryInteractor = deviceEntryInteractor,
             authenticationInteractor = authenticationInteractor,
-            sceneInteractor = sceneInteractor,
             flags = sceneContainerFlags,
             falsingInteractor = falsingInteractor(),
         )
@@ -345,19 +338,4 @@ class SceneTestUtils(
             dozeLogger = dozeLogger,
         )
     }
-
-    companion object {
-        fun DomainLayerAuthenticationMethodModel.toDataLayer(): DataLayerAuthenticationMethodModel {
-            return when (this) {
-                DomainLayerAuthenticationMethodModel.None -> DataLayerAuthenticationMethodModel.None
-                DomainLayerAuthenticationMethodModel.Swipe ->
-                    DataLayerAuthenticationMethodModel.None
-                DomainLayerAuthenticationMethodModel.Pin -> DataLayerAuthenticationMethodModel.Pin
-                DomainLayerAuthenticationMethodModel.Password ->
-                    DataLayerAuthenticationMethodModel.Password
-                DomainLayerAuthenticationMethodModel.Pattern ->
-                    DataLayerAuthenticationMethodModel.Pattern
-            }
-        }
-    }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt
new file mode 100644
index 0000000000000000000000000000000000000000..0c2b115a8af52ac2b67d8ddf70b715683715071c
--- /dev/null
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/policy/FakeDeviceProvisionedController.kt
@@ -0,0 +1,31 @@
+package com.android.systemui.statusbar.policy
+
+class FakeDeviceProvisionedController : DeviceProvisionedController {
+    @JvmField var deviceProvisioned = true
+
+    override fun addCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
+        TODO("Not yet implemented")
+    }
+
+    override fun removeCallback(listener: DeviceProvisionedController.DeviceProvisionedListener) {
+        TODO("Not yet implemented")
+    }
+
+    override fun isDeviceProvisioned() = deviceProvisioned
+
+    override fun getCurrentUser(): Int {
+        TODO("Not yet implemented")
+    }
+
+    override fun isUserSetup(user: Int): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    override fun isCurrentUserSetup(): Boolean {
+        TODO("Not yet implemented")
+    }
+
+    override fun isFrpActive(): Boolean {
+        TODO("Not yet implemented")
+    }
+}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
index bdf1aff7f985cd25329648e10f673e1dee05feed..d452810053092a82068eabd526a6fc4d013a4a99 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/utils/leaks/FakeKeyguardStateController.java
@@ -24,6 +24,9 @@ public class FakeKeyguardStateController implements KeyguardStateController {
 
     private final BaseLeakChecker<Callback> mCallbackController;
 
+    private boolean mIsShowing = false;
+    private boolean mIsOccluded = false;
+
     public FakeKeyguardStateController(LeakCheck test) {
         mCallbackController = new BaseLeakChecker<Callback>(test, "keyguard");
     }
@@ -45,7 +48,11 @@ public class FakeKeyguardStateController implements KeyguardStateController {
 
     @Override
     public boolean isShowing() {
-        return false;
+        return mIsShowing;
+    }
+
+    public void setShowing(boolean showing) {
+        mIsShowing = showing;
     }
 
     @Override
@@ -60,7 +67,11 @@ public class FakeKeyguardStateController implements KeyguardStateController {
 
     @Override
     public boolean isOccluded() {
-        return false;
+        return mIsOccluded;
+    }
+
+    public void setOccluded(boolean occluded) {
+        mIsOccluded = occluded;
     }
 
     @Override
diff --git a/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java b/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java
index 2d6b013d11c1c5b91ccd12ca7808dc9291baf21f..035a7485fe86ed5898c0b3e5a442d72a0f99f9a4 100644
--- a/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java
+++ b/services/core/java/com/android/server/inputmethod/AutofillSuggestionsController.java
@@ -39,7 +39,6 @@ final class AutofillSuggestionsController {
     private static final String TAG = AutofillSuggestionsController.class.getSimpleName();
 
     @NonNull private final InputMethodManagerService mService;
-    @NonNull private final InputMethodUtils.InputMethodSettings mSettings;
 
     private static final class CreateInlineSuggestionsRequest {
         @NonNull final InlineSuggestionsRequestInfo mRequestInfo;
@@ -76,7 +75,6 @@ final class AutofillSuggestionsController {
 
     AutofillSuggestionsController(@NonNull InputMethodManagerService service) {
         mService = service;
-        mSettings = mService.mSettings;
     }
 
     @GuardedBy("ImfLock.class")
@@ -88,7 +86,7 @@ final class AutofillSuggestionsController {
         final InputMethodInfo imi = mService.queryInputMethodForCurrentUserLocked(
                 mService.getSelectedMethodIdLocked());
         try {
-            if (userId == mSettings.getCurrentUserId()
+            if (userId == mService.getCurrentImeUserIdLocked()
                     && imi != null && isInlineSuggestionsEnabled(imi, touchExplorationEnabled)) {
                 mPendingInlineSuggestionsRequest = new CreateInlineSuggestionsRequest(
                         requestInfo, callback, imi.getPackageName());
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
index e76aa1aad0cc1fed5db8bb3728c086cdf8c1cb2a..c8c0482f5a9dd29c402e777c88ce34f5c38e9297 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodBindingController.java
@@ -63,7 +63,6 @@ final class InputMethodBindingController {
 
     @NonNull private final InputMethodManagerService mService;
     @NonNull private final Context mContext;
-    @NonNull private final InputMethodUtils.InputMethodSettings mSettings;
     @NonNull private final PackageManagerInternal mPackageManagerInternal;
     @NonNull private final WindowManagerInternal mWindowManagerInternal;
 
@@ -113,7 +112,6 @@ final class InputMethodBindingController {
             int imeConnectionBindFlags, CountDownLatch latchForTesting) {
         mService = service;
         mContext = mService.mContext;
-        mSettings = mService.mSettings;
         mPackageManagerInternal = mService.mPackageManagerInternal;
         mWindowManagerInternal = mService.mWindowManagerInternal;
         mImeConnectionBindFlags = imeConnectionBindFlags;
@@ -322,7 +320,7 @@ final class InputMethodBindingController {
         private void updateCurrentMethodUid() {
             final String curMethodPackage = mCurIntent.getComponent().getPackageName();
             final int curMethodUid = mPackageManagerInternal.getPackageUid(
-                    curMethodPackage, 0 /* flags */, mSettings.getCurrentUserId());
+                    curMethodPackage, 0 /* flags */, mService.getCurrentImeUserIdLocked());
             if (curMethodUid < 0) {
                 Slog.e(TAG, "Failed to get UID for package=" + curMethodPackage);
                 mCurMethodUid = Process.INVALID_UID;
@@ -478,7 +476,7 @@ final class InputMethodBindingController {
             return false;
         }
         return mContext.bindServiceAsUser(mCurIntent, conn, flags,
-                new UserHandle(mSettings.getCurrentUserId()));
+                new UserHandle(mService.getCurrentImeUserIdLocked()));
     }
 
     @GuardedBy("ImfLock.class")
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
index 8171e71245a72f461d176f1fb908aedb738b15ec..d656f204ebaa221630d784de4b262a13751baad5 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodManagerService.java
@@ -1728,6 +1728,12 @@ public final class InputMethodManagerService extends IInputMethodManager.Stub
         registerDeviceListenerAndCheckStylusSupport();
     }
 
+    @GuardedBy("ImfLock.class")
+    @UserIdInt
+    int getCurrentImeUserIdLocked() {
+        return mSettings.getCurrentUserId();
+    }
+
     private final class InkWindowInitializer implements Runnable {
         public void run() {
             synchronized (ImfLock.class) {
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 3b5ef4cadfdf75e6663d60c2d665d221c6dd42c8..efa1e0d66f35a085f76d47b214ae3f178d9641b7 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -79,7 +79,8 @@ final class InputMethodMenuController {
 
         synchronized (ImfLock.class) {
             final boolean isScreenLocked = mWindowManagerInternal.isKeyguardLocked()
-                    && mWindowManagerInternal.isKeyguardSecure(mSettings.getCurrentUserId());
+                    && mWindowManagerInternal.isKeyguardSecure(
+                            mService.getCurrentImeUserIdLocked());
             final String lastInputMethodId = mSettings.getSelectedInputMethod();
             int lastInputMethodSubtypeId =
                     mSettings.getSelectedInputMethodSubtypeId(lastInputMethodId);