[flexiglass] Factor out HomeSceneFamilyResolver

Flag: com.android.systemui.scene_container DEVELOPMENT
Bug: 344624611
Test: atest SceneInteractorTest
Change-Id: Idef141600e3087b8d78786d9536ce8daaba2730a
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt
index 9d8ec95..6b1794e2 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModelTest.kt
@@ -30,7 +30,9 @@
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.homeSceneFamilyResolver
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.ui.viewmodel.notificationsShadeSceneViewModel
 import com.android.systemui.testKosmos
@@ -62,7 +64,9 @@
             val destinationScenes by collectLastValue(underTest.destinationScenes)
             lockDevice()
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(kosmos.homeSceneFamilyResolver.resolvedScene.value)
+                .isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
@@ -72,7 +76,8 @@
             lockDevice()
             unlockDevice()
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(sceneInteractor.currentScene.value).isEqualTo(Scenes.Gone)
         }
 
     @Test
@@ -85,7 +90,9 @@
             )
             sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(kosmos.homeSceneFamilyResolver.resolvedScene.value)
+                .isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
@@ -96,10 +103,12 @@
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.None
             )
+            sceneInteractor // force the lazy; this will kick off StateFlows
             runCurrent()
             sceneInteractor.changeScene(Scenes.Gone, "reason")
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(kosmos.homeSceneFamilyResolver.resolvedScene.value).isEqualTo(Scenes.Gone)
         }
 
     private fun TestScope.lockDevice() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
index 0b55bef..7ee20e5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt
@@ -28,7 +28,6 @@
 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.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.flags.Flags
 import com.android.systemui.flags.fakeFeatureFlagsClassic
@@ -36,16 +35,17 @@
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
 import com.android.systemui.media.controls.data.repository.mediaFilterRepository
-import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
 import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
 import com.android.systemui.media.controls.shared.model.MediaData
 import com.android.systemui.qs.FooterActionsController
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.homeSceneFamilyResolver
 import com.android.systemui.scene.domain.interactor.sceneBackInteractor
 import com.android.systemui.scene.domain.interactor.sceneContainerStartable
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
 import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModel
@@ -55,7 +55,6 @@
 import com.android.systemui.util.mockito.mock
 import com.android.systemui.util.mockito.whenever
 import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.test.runTest
 import org.junit.Before
 import org.junit.Test
@@ -82,11 +81,8 @@
     private val sceneBackInteractor = kosmos.sceneBackInteractor
     private val sceneContainerStartable = kosmos.sceneContainerStartable
 
-    private val mediaDataManager = mock<MediaDataManager>()
-
     private lateinit var underTest: QuickSettingsSceneViewModel
 
-    @OptIn(ExperimentalCoroutinesApi::class)
     @Before
     fun setUp() {
         kosmos.fakeFeatureFlagsClassic.set(Flags.NEW_NETWORK_SLICE_UI, false)
@@ -95,7 +91,6 @@
         underTest =
             QuickSettingsSceneViewModel(
                 applicationScope = testScope.backgroundScope,
-                deviceEntryInteractor = kosmos.deviceEntryInteractor,
                 brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel,
                 shadeHeaderViewModel = kosmos.shadeHeaderViewModel,
                 qsSceneAdapter = qsFlexiglassAdapter,
@@ -112,6 +107,7 @@
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, false)
             val destinations by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             qsFlexiglassAdapter.setCustomizing(false)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Pin
@@ -128,9 +124,10 @@
                         Swipe(
                             fromSource = Edge.Bottom,
                             direction = SwipeDirection.Up,
-                        ) to UserActionResult(Scenes.Gone)
+                        ) to UserActionResult(SceneFamilies.Home)
                     )
                 )
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
         }
 
     @Test
@@ -142,6 +139,7 @@
 
             val currentScene by collectLastValue(sceneInteractor.currentScene)
             val backScene by collectLastValue(sceneBackInteractor.backScene)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
             sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
             assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
@@ -155,9 +153,10 @@
                         Swipe(
                             fromSource = Edge.Bottom,
                             direction = SwipeDirection.Up,
-                        ) to UserActionResult(Scenes.Lockscreen)
+                        ) to UserActionResult(SceneFamilies.Home)
                     )
                 )
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
@@ -165,6 +164,7 @@
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, false)
             val destinations by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             qsFlexiglassAdapter.setCustomizing(false)
             kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
@@ -179,9 +179,10 @@
                         Swipe(
                             fromSource = Edge.Bottom,
                             direction = SwipeDirection.Up,
-                        ) to UserActionResult(Scenes.Lockscreen)
+                        ) to UserActionResult(SceneFamilies.Home)
                     )
                 )
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
@@ -199,6 +200,7 @@
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, true)
             val destinations by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             qsFlexiglassAdapter.setCustomizing(false)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Pin
@@ -215,9 +217,10 @@
                         Swipe(
                             fromSource = Edge.Bottom,
                             direction = SwipeDirection.Up,
-                        ) to UserActionResult(Scenes.Gone),
+                        ) to UserActionResult(SceneFamilies.Home)
                     )
                 )
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
         }
 
     @Test
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt
index 034c2e9..f28ddeb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModelTest.kt
@@ -30,7 +30,9 @@
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.homeSceneFamilyResolver
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.ui.viewmodel.quickSettingsShadeSceneViewModel
 import com.android.systemui.testKosmos
@@ -60,38 +62,45 @@
     fun upTransitionSceneKey_deviceLocked_lockscreen() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             lockDevice()
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
     fun upTransitionSceneKey_deviceUnlocked_gone() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             lockDevice()
             unlockDevice()
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
         }
 
     @Test
     fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.None
             )
             sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Lockscreen)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
     fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.None
@@ -99,7 +108,8 @@
             runCurrent()
             sceneInteractor.changeScene(Scenes.Gone, "reason")
 
-            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(Scenes.Gone)
+            assertThat(destinationScenes?.get(Swipe.Up)?.toScene).isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
         }
 
     private fun TestScope.lockDevice() {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
index 9e7e766..f8a62cb 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt
@@ -51,7 +51,6 @@
 import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel
 import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel
 import com.android.systemui.kosmos.testScope
-import com.android.systemui.media.controls.domain.pipeline.MediaDataManager
 import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
 import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
@@ -59,8 +58,10 @@
 import com.android.systemui.qs.footerActionsController
 import com.android.systemui.qs.footerActionsViewModelFactory
 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
+import com.android.systemui.scene.domain.interactor.homeSceneFamilyResolver
 import com.android.systemui.scene.domain.interactor.sceneContainerStartable
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
@@ -91,7 +92,6 @@
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
-import org.mockito.Mock
 import org.mockito.Mockito.verify
 import org.mockito.MockitoAnnotations
 
@@ -169,8 +169,6 @@
 
     private val qsFlexiglassAdapter = FakeQSSceneAdapter(inflateDelegate = { mock() })
 
-    @Mock private lateinit var mediaDataManager: MediaDataManager
-
     private lateinit var emergencyAffordanceManager: EmergencyAffordanceManager
     private lateinit var telecomManager: TelecomManager
     private val fakeSceneDataSource = kosmos.fakeSceneDataSource
@@ -205,7 +203,6 @@
         shadeSceneViewModel =
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
-                deviceEntryInteractor = deviceEntryInteractor,
                 shadeHeaderViewModel = kosmos.shadeHeaderViewModel,
                 qsSceneAdapter = qsFlexiglassAdapter,
                 notifications = kosmos.notificationsPlaceholderViewModel,
@@ -280,6 +277,7 @@
     fun swipeUpOnShadeScene_withAuthMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
         testScope.runTest {
             val destinationScenes by collectLastValue(shadeSceneViewModel.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
             assertCurrentScene(Scenes.Lockscreen)
 
@@ -288,9 +286,10 @@
             assertCurrentScene(Scenes.Shade)
 
             val upDestinationSceneKey = destinationScenes?.get(Swipe.Up)?.toScene
-            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Lockscreen)
+            assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
             emulateUserDrivenTransition(
-                to = upDestinationSceneKey,
+                to = homeScene,
             )
         }
 
@@ -299,6 +298,7 @@
         testScope.runTest {
             val destinationScenes by collectLastValue(shadeSceneViewModel.destinationScenes)
             val canSwipeToEnter by collectLastValue(deviceEntryInteractor.canSwipeToEnter)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
 
             setAuthMethod(AuthenticationMethodModel.None, enableLockscreen = true)
 
@@ -314,9 +314,10 @@
             assertCurrentScene(Scenes.Shade)
 
             val upDestinationSceneKey = destinationScenes?.get(Swipe.Up)?.toScene
-            assertThat(upDestinationSceneKey).isEqualTo(Scenes.Gone)
+            assertThat(upDestinationSceneKey).isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
             emulateUserDrivenTransition(
-                to = upDestinationSceneKey,
+                to = homeScene,
             )
         }
 
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
index 229a711..881ce41 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/domain/interactor/SceneInteractorTest.kt
@@ -31,6 +31,7 @@
 import com.android.systemui.scene.sceneContainerConfig
 import com.android.systemui.scene.sceneKeys
 import com.android.systemui.scene.shared.model.SceneContainerConfig
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.fakeSceneDataSource
 import com.android.systemui.testKosmos
@@ -38,6 +39,7 @@
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.flowOf
+import kotlinx.coroutines.flow.toList
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
 import org.junit.Test
@@ -151,6 +153,18 @@
         }
 
     @Test
+    fun changeScene_toHomeSceneFamily() =
+        testScope.runTest {
+            underTest = kosmos.sceneInteractor
+            val currentScene by collectLastValue(underTest.currentScene)
+
+            underTest.changeScene(SceneFamilies.Home, "reason")
+            runCurrent()
+
+            assertThat(currentScene).isEqualTo(kosmos.homeSceneFamilyResolver.resolvedScene.value)
+        }
+
+    @Test
     fun snapToScene_toUnknownScene_doesNothing() =
         testScope.runTest {
             val sceneKeys =
@@ -216,6 +230,18 @@
         }
 
     @Test
+    fun snapToScene_toHomeSceneFamily() =
+        testScope.runTest {
+            underTest = kosmos.sceneInteractor
+            val currentScene by collectLastValue(underTest.currentScene)
+
+            underTest.snapToScene(SceneFamilies.Home, "reason")
+            runCurrent()
+
+            assertThat(currentScene).isEqualTo(kosmos.homeSceneFamilyResolver.resolvedScene.value)
+        }
+
+    @Test
     fun sceneChanged_inDataSource() =
         testScope.runTest {
             underTest = kosmos.sceneInteractor
@@ -428,4 +454,20 @@
 
             assertThat(isVisible).isFalse()
         }
+
+    @Test
+    fun resolveSceneFamily_home() =
+        testScope.runTest {
+            underTest = kosmos.sceneInteractor
+            assertThat(underTest.resolveSceneFamily(SceneFamilies.Home))
+                .isEqualTo(kosmos.homeSceneFamilyResolver.resolvedScene)
+        }
+
+    @Test
+    fun resolveSceneFamily_nonFamily() =
+        testScope.runTest {
+            underTest = kosmos.sceneInteractor
+            val resolved = underTest.resolveSceneFamily(Scenes.Gone).toList()
+            assertThat(resolved).containsExactly(Scenes.Gone).inOrder()
+        }
 }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt
index 468c39d..3a5ff00 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImplTest.kt
@@ -29,6 +29,7 @@
 import com.android.systemui.keyguard.data.repository.deviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
 import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.domain.interactor.homeSceneFamilyResolver
 import com.android.systemui.scene.domain.interactor.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shared.recents.utilities.Utilities
@@ -36,6 +37,7 @@
 import com.google.common.truth.Truth.assertThat
 import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.launchIn
 import kotlinx.coroutines.test.TestScope
 import kotlinx.coroutines.test.runCurrent
 import kotlinx.coroutines.test.runTest
@@ -77,6 +79,8 @@
     @Test
     fun animateCollapseQs_fullyCollapse_entered() =
         testScope.runTest {
+            // Ensure that HomeSceneFamilyResolver is running
+            kosmos.homeSceneFamilyResolver.resolvedScene.launchIn(backgroundScope)
             val actual by collectLastValue(sceneInteractor.currentScene)
             enterDevice()
             setScene(Scenes.QuickSettings)
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 482dc5d..f88d102 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -27,7 +27,6 @@
 import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository
 import com.android.systemui.coroutines.collectLastValue
 import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.flags.EnableSceneContainer
 import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
 import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
@@ -40,7 +39,9 @@
 import com.android.systemui.qs.footerActionsViewModelFactory
 import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
 import com.android.systemui.res.R
+import com.android.systemui.scene.domain.interactor.homeSceneFamilyResolver
 import com.android.systemui.scene.domain.interactor.sceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
 import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
@@ -75,7 +76,6 @@
     private val kosmos = testKosmos()
     private val testScope = kosmos.testScope
     private val sceneInteractor by lazy { kosmos.sceneInteractor }
-    private val deviceEntryInteractor by lazy { kosmos.deviceEntryInteractor }
     private val shadeRepository by lazy { kosmos.shadeRepository }
 
     private val qsSceneAdapter = FakeQSSceneAdapter({ mock() })
@@ -91,7 +91,6 @@
         underTest =
             ShadeSceneViewModel(
                 applicationScope = testScope.backgroundScope,
-                deviceEntryInteractor = deviceEntryInteractor,
                 shadeHeaderViewModel = kosmos.shadeHeaderViewModel,
                 qsSceneAdapter = qsSceneAdapter,
                 notifications = kosmos.notificationsPlaceholderViewModel,
@@ -109,18 +108,21 @@
     fun upTransitionSceneKey_deviceLocked_lockScreen() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Pin
             )
 
             assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.toScene)
-                .isEqualTo(Scenes.Lockscreen)
+                .isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
     fun upTransitionSceneKey_deviceUnlocked_gone() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.Pin
             )
@@ -129,13 +131,15 @@
             )
 
             assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.toScene)
-                .isEqualTo(Scenes.Gone)
+                .isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
         }
 
     @Test
     fun upTransitionSceneKey_authMethodSwipe_lockscreenNotDismissed_goesToLockscreen() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.None
@@ -143,13 +147,15 @@
             sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
 
             assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.toScene)
-                .isEqualTo(Scenes.Lockscreen)
+                .isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Lockscreen)
         }
 
     @Test
     fun upTransitionSceneKey_authMethodSwipe_lockscreenDismissed_goesToGone() =
         testScope.runTest {
             val destinationScenes by collectLastValue(underTest.destinationScenes)
+            val homeScene by collectLastValue(kosmos.homeSceneFamilyResolver.resolvedScene)
             kosmos.fakeDeviceEntryRepository.setLockscreenEnabled(true)
             kosmos.fakeAuthenticationRepository.setAuthenticationMethod(
                 AuthenticationMethodModel.None
@@ -158,7 +164,8 @@
             sceneInteractor.changeScene(Scenes.Gone, "reason")
 
             assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.toScene)
-                .isEqualTo(Scenes.Gone)
+                .isEqualTo(SceneFamilies.Home)
+            assertThat(homeScene).isEqualTo(Scenes.Gone)
         }
 
     @Test
diff --git a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt
index f677ec1b..d0c7fbc 100644
--- a/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/notifications/ui/viewmodel/NotificationsShadeSceneViewModel.kt
@@ -17,41 +17,25 @@
 package com.android.systemui.notifications.ui.viewmodel
 
 import com.android.compose.animation.scene.Back
-import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
+import com.android.systemui.scene.shared.model.SceneFamilies
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.asStateFlow
 
 /** Models UI state and handles user input for the Notifications Shade scene. */
 @SysUISingleton
-class NotificationsShadeSceneViewModel
-@Inject
-constructor(
-    @Application private val applicationScope: CoroutineScope,
-    overlayShadeViewModel: OverlayShadeViewModel,
-) {
+class NotificationsShadeSceneViewModel @Inject constructor() {
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
-        overlayShadeViewModel.backgroundScene
-            .map(::destinationScenes)
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = destinationScenes(overlayShadeViewModel.backgroundScene.value),
+        MutableStateFlow(
+                mapOf(
+                    Swipe.Up to SceneFamilies.Home,
+                    Back to SceneFamilies.Home,
+                )
             )
-
-    private fun destinationScenes(backgroundScene: SceneKey): Map<UserAction, UserActionResult> {
-        return mapOf(
-            Swipe.Up to backgroundScene,
-            Back to backgroundScene,
-        )
-    }
+            .asStateFlow()
 }
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 6cf2e52..79cdfec 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
@@ -14,8 +14,6 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
 package com.android.systemui.qs.ui.viewmodel
 
 import androidx.lifecycle.LifecycleOwner
@@ -28,12 +26,12 @@
 import com.android.compose.animation.scene.UserActionResult
 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.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
 import com.android.systemui.qs.FooterActionsController
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
 import com.android.systemui.scene.domain.interactor.SceneBackInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
@@ -41,7 +39,6 @@
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
@@ -55,7 +52,6 @@
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    deviceEntryInteractor: DeviceEntryInteractor,
     val brightnessMirrorViewModel: BrightnessMirrorViewModel,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
     val qsSceneAdapter: QSSceneAdapter,
@@ -77,25 +73,15 @@
 
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
         combine(
-                deviceEntryInteractor.isUnlocked,
-                deviceEntryInteractor.canSwipeToEnter,
                 qsSceneAdapter.isCustomizerShowing,
                 backScene,
-            ) { isUnlocked, canSwipeToDismiss, isCustomizerShowing, backScene ->
-                destinationScenes(
-                    isUnlocked,
-                    canSwipeToDismiss,
-                    isCustomizerShowing,
-                    backScene,
-                )
-            }
+                transform = ::destinationScenes,
+            )
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
                 initialValue =
                     destinationScenes(
-                        isUnlocked = deviceEntryInteractor.isUnlocked.value,
-                        canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
                         isCustomizing = qsSceneAdapter.isCustomizerShowing.value,
                         backScene = backScene.value,
                     ),
@@ -104,18 +90,9 @@
     val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasAnyMediaOrRecommendation
 
     private fun destinationScenes(
-        isUnlocked: Boolean,
-        canSwipeToDismiss: Boolean?,
         isCustomizing: Boolean,
         backScene: SceneKey?,
     ): Map<UserAction, UserActionResult> {
-        val upBottomEdge =
-            when {
-                canSwipeToDismiss == true -> Scenes.Lockscreen
-                isUnlocked -> Scenes.Gone
-                else -> Scenes.Lockscreen
-            }
-
         return buildMap {
             if (isCustomizing) {
                 // TODO(b/332749288) Empty map so there are no back handlers and back can close
@@ -127,11 +104,8 @@
                 put(Back, UserActionResult(backScene ?: Scenes.Shade))
                 put(Swipe(SwipeDirection.Up), UserActionResult(backScene ?: Scenes.Shade))
                 put(
-                    Swipe(
-                        fromSource = Edge.Bottom,
-                        direction = SwipeDirection.Up,
-                    ),
-                    UserActionResult(upBottomEdge),
+                    Swipe(fromSource = Edge.Bottom, direction = SwipeDirection.Up),
+                    UserActionResult(SceneFamilies.Home),
                 )
             }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt
index c1a5646..bd748d5 100644
--- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsShadeSceneViewModel.kt
@@ -17,30 +17,26 @@
 package com.android.systemui.qs.ui.viewmodel
 
 import com.android.compose.animation.scene.Back
-import com.android.compose.animation.scene.SceneKey
 import com.android.compose.animation.scene.Swipe
 import com.android.compose.animation.scene.UserAction
 import com.android.compose.animation.scene.UserActionResult
 import com.android.systemui.brightness.ui.viewmodel.BrightnessSliderViewModel
 import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.qs.panels.ui.viewmodel.EditModeViewModel
 import com.android.systemui.qs.panels.ui.viewmodel.TileGridViewModel
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.shade.ui.viewmodel.OverlayShadeViewModel
 import javax.inject.Inject
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.MutableStateFlow
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.flow.stateIn
+import kotlinx.coroutines.flow.asStateFlow
 
 /** Models UI state and handles user input for the Quick Settings Shade scene. */
 @SysUISingleton
 class QuickSettingsShadeSceneViewModel
 @Inject
 constructor(
-    @Application private val applicationScope: CoroutineScope,
     val overlayShadeViewModel: OverlayShadeViewModel,
     val brightnessSliderViewModel: BrightnessSliderViewModel,
     val tileGridViewModel: TileGridViewModel,
@@ -48,18 +44,11 @@
     val qsSceneAdapter: QSSceneAdapter,
 ) {
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
-        overlayShadeViewModel.backgroundScene
-            .map(::destinationScenes)
-            .stateIn(
-                scope = applicationScope,
-                started = SharingStarted.WhileSubscribed(),
-                initialValue = destinationScenes(overlayShadeViewModel.backgroundScene.value),
+        MutableStateFlow(
+                mapOf(
+                    Swipe.Up to SceneFamilies.Home,
+                    Back to SceneFamilies.Home,
+                )
             )
-
-    private fun destinationScenes(backgroundScene: SceneKey): Map<UserAction, UserActionResult> {
-        return mapOf(
-            Swipe.Up to backgroundScene,
-            Back to backgroundScene,
-        )
-    }
+            .asStateFlow()
 }
diff --git a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
index 7a9d09a..da23936 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/KeyguardlessSceneContainerFrameworkModule.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.CoreStartable
 import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
+import com.android.systemui.scene.domain.SceneDomainModule
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.startable.SceneContainerStartable
 import com.android.systemui.scene.domain.startable.ScrimStartable
@@ -40,6 +41,7 @@
             NotificationsShadeSessionModule::class,
             QuickSettingsSceneModule::class,
             ShadeSceneModule::class,
+            SceneDomainModule::class,
         ],
 )
 interface KeyguardlessSceneContainerFrameworkModule {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
index 7e6dfb8..a0cf82a 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/SceneContainerFrameworkModule.kt
@@ -19,6 +19,7 @@
 import com.android.systemui.CoreStartable
 import com.android.systemui.bouncer.shared.flag.ComposeBouncerFlagsModule
 import com.android.systemui.notifications.ui.composable.NotificationsShadeSessionModule
+import com.android.systemui.scene.domain.SceneDomainModule
 import com.android.systemui.scene.domain.interactor.WindowRootViewVisibilityInteractor
 import com.android.systemui.scene.domain.startable.SceneContainerStartable
 import com.android.systemui.scene.domain.startable.ScrimStartable
@@ -46,6 +47,7 @@
             QuickSettingsShadeSceneModule::class,
             NotificationsShadeSceneModule::class,
             NotificationsShadeSessionModule::class,
+            SceneDomainModule::class,
         ],
 )
 interface SceneContainerFrameworkModule {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
index b918277..a326ec1 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ShadelessSceneContainerFrameworkModule.kt
@@ -16,6 +16,7 @@
 
 package com.android.systemui.scene
 
+import com.android.systemui.scene.domain.SceneDomainModule
 import com.android.systemui.scene.shared.model.SceneContainerConfig
 import com.android.systemui.scene.shared.model.Scenes
 import dagger.Module
@@ -29,6 +30,7 @@
             EmptySceneModule::class,
             GoneSceneModule::class,
             LockscreenSceneModule::class,
+            SceneDomainModule::class,
         ],
 )
 object ShadelessSceneContainerFrameworkModule {
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/SceneDomainModule.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/SceneDomainModule.kt
new file mode 100644
index 0000000..9b2a6dd
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/SceneDomainModule.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2024 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.scene.domain
+
+import com.android.systemui.scene.domain.resolver.HomeSceneFamilyResolverModule
+import com.android.systemui.scene.domain.resolver.SceneResolverModule
+import dagger.Module
+
+@Module(
+    includes =
+        [
+            HomeSceneFamilyResolverModule::class,
+            SceneResolverModule::class,
+        ]
+)
+object SceneDomainModule
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
index b1700e3..2f66d6b 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/interactor/SceneInteractor.kt
@@ -23,9 +23,12 @@
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
 import com.android.systemui.scene.data.repository.SceneContainerRepository
+import com.android.systemui.scene.domain.resolver.SceneResolver
 import com.android.systemui.scene.shared.logger.SceneLogger
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.util.kotlin.pairwiseBy
+import dagger.Lazy
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
 import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -52,6 +55,7 @@
     @Application private val applicationScope: CoroutineScope,
     private val repository: SceneContainerRepository,
     private val logger: SceneLogger,
+    private val sceneFamilyResolvers: Lazy<Map<SceneKey, @JvmSuppressWildcards SceneResolver>>,
     private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
 ) {
 
@@ -180,10 +184,11 @@
         sceneState: Any? = null,
     ) {
         val currentSceneKey = currentScene.value
+        val resolvedScene = sceneFamilyResolvers.get()[toScene]?.resolvedScene?.value ?: toScene
         if (
             !validateSceneChange(
                 from = currentSceneKey,
-                to = toScene,
+                to = resolvedScene,
                 loggingReason = loggingReason,
             )
         ) {
@@ -192,13 +197,13 @@
 
         logger.logSceneChangeRequested(
             from = currentSceneKey,
-            to = toScene,
+            to = resolvedScene,
             reason = loggingReason,
             isInstant = false,
         )
 
-        onSceneAboutToChangeListener.forEach { it.onSceneAboutToChange(toScene, sceneState) }
-        repository.changeScene(toScene, transitionKey)
+        onSceneAboutToChangeListener.forEach { it.onSceneAboutToChange(resolvedScene, sceneState) }
+        repository.changeScene(resolvedScene, transitionKey)
     }
 
     /**
@@ -212,10 +217,11 @@
         loggingReason: String,
     ) {
         val currentSceneKey = currentScene.value
+        val resolvedScene = sceneFamilyResolvers.get()[toScene]?.resolvedScene?.value ?: toScene
         if (
             !validateSceneChange(
                 from = currentSceneKey,
-                to = toScene,
+                to = resolvedScene,
                 loggingReason = loggingReason,
             )
         ) {
@@ -224,12 +230,12 @@
 
         logger.logSceneChangeRequested(
             from = currentSceneKey,
-            to = toScene,
+            to = resolvedScene,
             reason = loggingReason,
             isInstant = true,
         )
 
-        repository.snapToScene(toScene)
+        repository.snapToScene(resolvedScene)
     }
 
     /**
@@ -288,6 +294,13 @@
         repository.setTransitionState(transitionState)
     }
 
+    /**
+     * Returns the [concrete scene][Scenes] for [sceneKey] if it is a [scene family][SceneFamilies],
+     * otherwise returns a singleton [Flow] containing [sceneKey].
+     */
+    fun resolveSceneFamily(sceneKey: SceneKey): Flow<SceneKey> =
+        sceneFamilyResolvers.get()[sceneKey]?.resolvedScene ?: flowOf(sceneKey)
+
     private fun isVisibleInternal(
         raw: Boolean = repository.isVisible.value,
         isRemoteUserInteractionOngoing: Boolean = repository.isRemoteUserInteractionOngoing.value,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt
new file mode 100644
index 0000000..f19929c
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/HomeSceneFamilyResolver.kt
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+@file:OptIn(ExperimentalCoroutinesApi::class)
+
+package com.android.systemui.scene.domain.resolver
+
+import com.android.compose.animation.scene.SceneKey
+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.scene.shared.model.SceneFamilies
+import com.android.systemui.scene.shared.model.Scenes
+import dagger.Binds
+import dagger.Module
+import dagger.multibindings.IntoSet
+import javax.inject.Inject
+import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.stateIn
+
+/**
+ * Resolver for [SceneFamilies.Home]. The "home" scene family resolves to the scene that is
+ * currently underneath any "overlay" scene, such as shades or bouncer.
+ */
+@SysUISingleton
+class HomeSceneFamilyResolver
+@Inject
+constructor(
+    @Application private val applicationScope: CoroutineScope,
+    deviceEntryInteractor: DeviceEntryInteractor,
+) : SceneResolver {
+    override val targetFamily: SceneKey = SceneFamilies.Home
+
+    override val resolvedScene: StateFlow<SceneKey> =
+        combine(
+                deviceEntryInteractor.canSwipeToEnter,
+                deviceEntryInteractor.isUnlocked,
+                transform = ::homeScene,
+            )
+            .stateIn(
+                scope = applicationScope,
+                started = SharingStarted.WhileSubscribed(),
+                initialValue =
+                    homeScene(
+                        deviceEntryInteractor.canSwipeToEnter.value,
+                        deviceEntryInteractor.isUnlocked.value,
+                    )
+            )
+
+    private fun homeScene(canSwipeToEnter: Boolean?, isUnlocked: Boolean): SceneKey =
+        when {
+            canSwipeToEnter == true -> Scenes.Lockscreen
+            isUnlocked -> Scenes.Gone
+            else -> Scenes.Lockscreen
+        }
+}
+
+@Module
+interface HomeSceneFamilyResolverModule {
+    @Binds @IntoSet fun provideSceneResolver(interactor: HomeSceneFamilyResolver): SceneResolver
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/SceneResolver.kt b/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/SceneResolver.kt
new file mode 100644
index 0000000..8372529
--- /dev/null
+++ b/packages/SystemUI/src/com/android/systemui/scene/domain/resolver/SceneResolver.kt
@@ -0,0 +1,45 @@
+/*
+ * Copyright (C) 2024 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.scene.domain.resolver
+
+import com.android.compose.animation.scene.SceneKey
+import dagger.Module
+import dagger.Provides
+import dagger.multibindings.Multibinds
+import kotlinx.coroutines.flow.StateFlow
+
+/** Resolves [concrete scenes][Scenes] from a [scene family][SceneFamilies]. */
+interface SceneResolver {
+    /** The scene family that this resolves. */
+    val targetFamily: SceneKey
+
+    /** The concrete scene that [targetFamily] is currently resolved to. */
+    val resolvedScene: StateFlow<SceneKey>
+}
+
+@Module
+interface SceneResolverModule {
+
+    @Multibinds fun resolverSet(): Set<@JvmSuppressWildcards SceneResolver>
+
+    companion object {
+        @Provides
+        fun provideResolverMap(
+            resolverSet: Set<@JvmSuppressWildcards SceneResolver>
+        ): Map<SceneKey, SceneResolver> = resolverSet.associateBy { it.targetFamily }
+    }
+}
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
index 09c80b0..ab24e0b 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/SceneContainerViewModel.kt
@@ -34,6 +34,8 @@
 import kotlinx.coroutines.flow.Flow
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /** Models UI state for the scene container. */
@@ -61,7 +63,9 @@
     val isVisible: StateFlow<Boolean> = sceneInteractor.isVisible
 
     private val destinationScenesBySceneKey =
-        scenes.associate { scene -> scene.key to scene.destinationScenes }
+        scenes.associate { scene ->
+            scene.key to scene.destinationScenes.flatMapLatestConflated { replaceSceneFamilies(it) }
+        }
 
     fun currentDestinationScenes(
         scope: CoroutineScope,
@@ -140,7 +144,24 @@
             val fromLockscreenScene = currentScene.value == Scenes.Lockscreen
 
             !fromLockscreenScene || !isFalseTouch
-        }
-            ?: true
+        } ?: true
+    }
+
+    private fun replaceSceneFamilies(
+        destinationScenes: Map<UserAction, UserActionResult>,
+    ): Flow<Map<UserAction, UserActionResult>> {
+        return destinationScenes
+            .mapValues { (_, actionResult) ->
+                sceneInteractor.resolveSceneFamily(actionResult.toScene).map { scene ->
+                    actionResult.copy(toScene = scene)
+                }
+            }
+            .combineValueFlows()
     }
 }
+
+private fun <K, V> Map<K, Flow<V>>.combineValueFlows(): Flow<Map<K, V>> =
+    combine(
+        asIterable().map { (k, fv) -> fv.map { k to it } },
+        transform = Array<Pair<K, V>>::toMap,
+    )
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
index 884ccef..ac1f971 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeControllerSceneImpl.kt
@@ -17,16 +17,14 @@
 package com.android.systemui.shade
 
 import android.view.MotionEvent
-import com.android.compose.animation.scene.SceneKey
 import com.android.systemui.assist.AssistManager
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Background
 import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
-import com.android.systemui.deviceentry.domain.interactor.DeviceUnlockedInteractor
 import com.android.systemui.log.LogBuffer
 import com.android.systemui.log.dagger.ShadeTouchLog
 import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse
 import com.android.systemui.shade.ShadeController.ShadeVisibilityListener
@@ -61,8 +59,6 @@
     @Background private val scope: CoroutineScope,
     private val shadeInteractor: ShadeInteractor,
     private val sceneInteractor: SceneInteractor,
-    private val deviceEntryInteractor: DeviceEntryInteractor,
-    private val deviceUnlockedInteractor: DeviceUnlockedInteractor,
     private val notificationStackScrollLayout: NotificationStackScrollLayout,
     @ShadeTouchLog private val touchLog: LogBuffer,
     private val vibratorHelper: VibratorHelper,
@@ -100,7 +96,7 @@
 
     override fun instantCollapseShade() {
         sceneInteractor.snapToScene(
-            getCollapseDestinationScene(),
+            SceneFamilies.Home,
             "hide shade",
         )
     }
@@ -140,24 +136,12 @@
 
     private fun animateCollapseShadeInternal() {
         sceneInteractor.changeScene(
-            getCollapseDestinationScene(), // TODO(b/336581871): add sceneState?
+            SceneFamilies.Home, // TODO(b/336581871): add sceneState?
             "ShadeController.animateCollapseShade",
             SlightlyFasterShadeCollapse,
         )
     }
 
-    private fun getCollapseDestinationScene(): SceneKey {
-        // Always check whether device is unlocked before transitioning to gone scene.
-        return if (
-            deviceUnlockedInteractor.deviceUnlockStatus.value.isUnlocked &&
-                deviceEntryInteractor.isDeviceEntered.value
-        ) {
-            Scenes.Gone
-        } else {
-            Scenes.Lockscreen
-        }
-    }
-
     override fun cancelExpansionAndCollapseShade() {
         // TODO do we need to actually cancel the touch session?
         animateCollapseShade()
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
index 55bd8c6..3a483f4 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeBackActionInteractorImpl.kt
@@ -18,6 +18,7 @@
 
 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
 import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.shared.model.ShadeMode
 import javax.inject.Inject
@@ -36,11 +37,7 @@
         if (shadeInteractor.isQsExpanded.value) {
             val key =
                 if (fullyCollapse || shadeInteractor.shadeMode.value is ShadeMode.Dual) {
-                    if (deviceEntryInteractor.isDeviceEntered.value) {
-                        Scenes.Gone
-                    } else {
-                        Scenes.Lockscreen
-                    }
+                    SceneFamilies.Home
                 } else {
                     Scenes.Shade
                 }
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt
index b8dd628..0314091 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModel.kt
@@ -19,49 +19,41 @@
 import com.android.compose.animation.scene.SceneKey
 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.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
 /**
  * Models UI state and handles user input for the overlay shade UI, which shows a shade as an
  * overlay on top of another scene UI.
  */
-@OptIn(ExperimentalCoroutinesApi::class)
 @SysUISingleton
 class OverlayShadeViewModel
 @Inject
 constructor(
-    @Application private val applicationScope: CoroutineScope,
+    @Application applicationScope: CoroutineScope,
     private val sceneInteractor: SceneInteractor,
-    deviceEntryInteractor: DeviceEntryInteractor,
 ) {
     /** The scene to show in the background when the overlay shade is open. */
     val backgroundScene: StateFlow<SceneKey> =
-        deviceEntryInteractor.isDeviceEntered
-            .map(::backgroundScene)
+        sceneInteractor
+            .resolveSceneFamily(SceneFamilies.Home)
             .stateIn(
                 scope = applicationScope,
                 started = SharingStarted.WhileSubscribed(),
-                initialValue = backgroundScene(deviceEntryInteractor.isDeviceEntered.value)
+                initialValue = Scenes.Lockscreen,
             )
 
     /** Notifies that the user has clicked the semi-transparent background scrim. */
     fun onScrimClicked() {
         sceneInteractor.changeScene(
-            toScene = backgroundScene.value,
+            toScene = SceneFamilies.Home,
             loggingReason = "Shade scrim clicked",
         )
     }
-
-    private fun backgroundScene(isDeviceEntered: Boolean): SceneKey {
-        return if (isDeviceEntered) Scenes.Gone else Scenes.Lockscreen
-    }
 }
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 e4a2424..b0100b9 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
@@ -26,12 +26,12 @@
 import com.android.compose.animation.scene.UserActionResult
 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.media.controls.domain.pipeline.interactor.MediaCarouselInteractor
 import com.android.systemui.qs.FooterActionsController
 import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
 import com.android.systemui.qs.ui.adapter.QSSceneAdapter
 import com.android.systemui.scene.domain.interactor.SceneInteractor
+import com.android.systemui.scene.shared.model.SceneFamilies
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
 import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
@@ -39,6 +39,7 @@
 import com.android.systemui.shade.shared.model.ShadeMode
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
+import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
 import kotlinx.coroutines.CoroutineScope
@@ -47,6 +48,7 @@
 import kotlinx.coroutines.flow.SharingStarted
 import kotlinx.coroutines.flow.StateFlow
 import kotlinx.coroutines.flow.combine
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 import kotlinx.coroutines.flow.stateIn
 
@@ -56,7 +58,6 @@
 @Inject
 constructor(
     @Application private val applicationScope: CoroutineScope,
-    deviceEntryInteractor: DeviceEntryInteractor,
     val qsSceneAdapter: QSSceneAdapter,
     val shadeHeaderViewModel: ShadeHeaderViewModel,
     val notifications: NotificationsPlaceholderViewModel,
@@ -70,16 +71,12 @@
 ) {
     val destinationScenes: StateFlow<Map<UserAction, UserActionResult>> =
         combine(
-                deviceEntryInteractor.isUnlocked,
-                deviceEntryInteractor.canSwipeToEnter,
                 shadeInteractor.shadeMode,
-                qsSceneAdapter.isCustomizerShowing
-            ) { isUnlocked, canSwipeToDismiss, shadeMode, isCustomizerShowing ->
+                qsSceneAdapter.isCustomizerShowing,
+            ) { shadeMode, isCustomizerShowing ->
                 destinationScenes(
-                    isUnlocked = isUnlocked,
-                    canSwipeToDismiss = canSwipeToDismiss,
                     shadeMode = shadeMode,
-                    isCustomizing = isCustomizerShowing
+                    isCustomizing = isCustomizerShowing,
                 )
             }
             .stateIn(
@@ -87,8 +84,6 @@
                 started = SharingStarted.WhileSubscribed(),
                 initialValue =
                     destinationScenes(
-                        isUnlocked = deviceEntryInteractor.isUnlocked.value,
-                        canSwipeToDismiss = deviceEntryInteractor.canSwipeToEnter.value,
                         shadeMode = shadeInteractor.shadeMode.value,
                         isCustomizing = qsSceneAdapter.isCustomizerShowing.value,
                     ),
@@ -100,6 +95,9 @@
     /** Whether or not the shade container should be clickable. */
     val isClickable: StateFlow<Boolean> =
         upDestinationSceneKey
+            .flatMapLatestConflated { key ->
+                key?.let { sceneInteractor.resolveSceneFamily(key) } ?: flowOf(null)
+            }
             .map { it == Scenes.Lockscreen }
             .stateIn(
                 scope = applicationScope,
@@ -138,27 +136,22 @@
     }
 
     private fun destinationScenes(
-        isUnlocked: Boolean,
-        canSwipeToDismiss: Boolean?,
         shadeMode: ShadeMode,
         isCustomizing: Boolean,
     ): Map<UserAction, UserActionResult> {
-        val up =
-            when {
-                canSwipeToDismiss == true -> Scenes.Lockscreen
-                isUnlocked -> Scenes.Gone
-                else -> Scenes.Lockscreen
-            }
-
-        val upTransitionKey = ToSplitShade.takeIf { shadeMode is ShadeMode.Split }
-
-        val down = Scenes.QuickSettings.takeIf { shadeMode is ShadeMode.Single }
-
         return buildMap {
             if (!isCustomizing) {
-                this[Swipe(SwipeDirection.Up)] = UserActionResult(up, upTransitionKey)
+                set(
+                    Swipe(SwipeDirection.Up),
+                    UserActionResult(
+                        SceneFamilies.Home,
+                        ToSplitShade.takeIf { shadeMode is ShadeMode.Split }
+                    )
+                )
             } // TODO(b/330200163) Add an else to be able to collapse the shade while customizing
-            down?.let { this[Swipe(SwipeDirection.Down)] = UserActionResult(down) }
+            if (shadeMode is ShadeMode.Single) {
+                set(Swipe(SwipeDirection.Down), UserActionResult(Scenes.QuickSettings))
+            }
         }
     }
 }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt
index ef7aa63..d1fbb5e 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/scene/domain/interactor/SceneInteractorKosmos.kt
@@ -16,11 +16,16 @@
 
 package com.android.systemui.scene.domain.interactor
 
+import com.android.compose.animation.scene.SceneKey
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.scene.data.repository.sceneContainerRepository
+import com.android.systemui.scene.domain.resolver.HomeSceneFamilyResolver
+import com.android.systemui.scene.domain.resolver.SceneResolver
 import com.android.systemui.scene.shared.logger.sceneLogger
+import com.android.systemui.scene.shared.model.SceneFamilies
 
 val Kosmos.sceneInteractor by
     Kosmos.Fixture {
@@ -28,6 +33,18 @@
             applicationScope = applicationCoroutineScope,
             repository = sceneContainerRepository,
             logger = sceneLogger,
+            sceneFamilyResolvers = { sceneFamilyResolvers },
             deviceUnlockedInteractor = deviceUnlockedInteractor,
         )
     }
+
+val Kosmos.sceneFamilyResolvers: Map<SceneKey, SceneResolver>
+    get() = mapOf(SceneFamilies.Home to homeSceneFamilyResolver)
+
+val Kosmos.homeSceneFamilyResolver by
+    Kosmos.Fixture {
+        HomeSceneFamilyResolver(
+            applicationScope = applicationCoroutineScope,
+            deviceEntryInteractor = deviceEntryInteractor,
+        )
+    }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt
index d08855f..cc836ac 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ShadeControllerKosmos.kt
@@ -20,8 +20,6 @@
 
 import com.android.systemui.assist.AssistManager
 import com.android.systemui.concurrency.fakeExecutor
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
-import com.android.systemui.deviceentry.domain.interactor.deviceUnlockedInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.kosmos.testDispatcher
@@ -52,15 +50,14 @@
             shadeInteractor = shadeInteractor,
             sceneInteractor = sceneInteractor,
             notificationStackScrollLayout = mock<NotificationStackScrollLayout>(),
-            deviceEntryInteractor = deviceEntryInteractor,
             touchLog = mock<LogBuffer>(),
             vibratorHelper = mock<VibratorHelper>(),
             commandQueue = mock<CommandQueue>(),
             statusBarKeyguardViewManager = mock<StatusBarKeyguardViewManager>(),
             notificationShadeWindowController = mock<NotificationShadeWindowController>(),
-            assistManagerLazy = { mock<AssistManager>() },
-            deviceUnlockedInteractor = deviceUnlockedInteractor,
-        )
+        ) {
+            mock<AssistManager>()
+        }
     }
 
 val Kosmos.shadeControllerImpl by
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt
index 872eba06..1ca3509 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/NotificationsShadeSceneViewModelKosmos.kt
@@ -17,13 +17,7 @@
 package com.android.systemui.shade.ui.viewmodel
 
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.notifications.ui.viewmodel.NotificationsShadeSceneViewModel
 
 val Kosmos.notificationsShadeSceneViewModel: NotificationsShadeSceneViewModel by
-    Kosmos.Fixture {
-        NotificationsShadeSceneViewModel(
-            applicationScope = applicationCoroutineScope,
-            overlayShadeViewModel = overlayShadeViewModel,
-        )
-    }
+    Kosmos.Fixture { NotificationsShadeSceneViewModel() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt
index 45ec032..fec1028 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/OverlayShadeViewModelKosmos.kt
@@ -14,21 +14,16 @@
  * limitations under the License.
  */
 
-@file:OptIn(ExperimentalCoroutinesApi::class)
-
 package com.android.systemui.shade.ui.viewmodel
 
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
 import com.android.systemui.kosmos.Kosmos
 import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.scene.domain.interactor.sceneInteractor
-import kotlinx.coroutines.ExperimentalCoroutinesApi
 
 val Kosmos.overlayShadeViewModel: OverlayShadeViewModel by
     Kosmos.Fixture {
         OverlayShadeViewModel(
             applicationScope = applicationCoroutineScope,
             sceneInteractor = sceneInteractor,
-            deviceEntryInteractor = deviceEntryInteractor,
         )
     }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt
index c5625e4..4d81ea1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/ui/viewmodel/QuickSettingsShadeSceneViewModelKosmos.kt
@@ -18,7 +18,6 @@
 
 import com.android.systemui.brightness.ui.viewmodel.brightnessSliderViewModel
 import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
 import com.android.systemui.qs.panels.ui.viewmodel.editModeViewModel
 import com.android.systemui.qs.panels.ui.viewmodel.tileGridViewModel
 import com.android.systemui.qs.ui.adapter.qsSceneAdapter
@@ -27,7 +26,6 @@
 val Kosmos.quickSettingsShadeSceneViewModel: QuickSettingsShadeSceneViewModel by
     Kosmos.Fixture {
         QuickSettingsShadeSceneViewModel(
-            applicationScope = applicationCoroutineScope,
             overlayShadeViewModel = overlayShadeViewModel,
             brightnessSliderViewModel = brightnessSliderViewModel,
             tileGridViewModel = tileGridViewModel,