[flexiglass] Require single swipe up to return to LS from QS scene

Utilizes the previousScene flow to build the destination scenes for the
QS scene.

Fix: 330695017
Test: unit test added
Test: manually verified that, when the device is locked and the QS scene
is opened with a two finger swipe-down from near the top edge of the
screen, hitting back or swipine up while on the QS scene, correctly
returns to the locscreen scene and not the shade scene
Test: manually verified that when arriving to the QS scene from the
shade scene via normal swipe down, back/up returns to the shade scene
Test: manually verified that, when the device is NOT locked and the QS scene
is opened with a swipe-down from near the top edge of the
screen, hitting back or swipine up while on the QS scene, correctly
returns to the gone scene and not the shade scene
Flag: ACONFIG com.android.systemui.scene_container DEVELOPMENT

Change-Id: Iae554155e5c3bd2a9b673c1b9d0a21ba7b60943e
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 d9ab3b1..e5a3731 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
@@ -31,6 +31,7 @@
 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.sceneInteractor
 import com.android.systemui.scene.shared.model.Scenes
 import com.android.systemui.shade.domain.interactor.privacyChipInteractor
 import com.android.systemui.shade.domain.interactor.shadeHeaderClockInteractor
@@ -87,6 +88,7 @@
             flags,
             scope = testScope.backgroundScope,
         )
+    private val sceneInteractor = kosmos.sceneInteractor
 
     private lateinit var shadeHeaderViewModel: ShadeHeaderViewModel
 
@@ -113,11 +115,12 @@
                 notifications = kosmos.notificationsPlaceholderViewModel,
                 footerActionsViewModelFactory = footerActionsViewModelFactory,
                 footerActionsController = footerActionsController,
+                sceneInteractor = sceneInteractor,
             )
     }
 
     @Test
-    fun destinationsNotCustomizing() =
+    fun destinations_whenNotCustomizing() =
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, false)
             val destinations by collectLastValue(underTest.destinationScenes)
@@ -133,7 +136,30 @@
         }
 
     @Test
-    fun destinationsCustomizing_noDestinations() =
+    fun destinations_whenNotCustomizing_withPreviousSceneLockscreen() =
+        testScope.runTest {
+            overrideResource(R.bool.config_use_split_notification_shade, false)
+            qsFlexiglassAdapter.setCustomizing(false)
+            val destinations by collectLastValue(underTest.destinationScenes)
+
+            val currentScene by collectLastValue(sceneInteractor.currentScene)
+            val previousScene by collectLastValue(sceneInteractor.previousScene)
+            sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
+            sceneInteractor.changeScene(Scenes.QuickSettings, "reason")
+            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
+            assertThat(previousScene).isEqualTo(Scenes.Lockscreen)
+
+            assertThat(destinations)
+                .isEqualTo(
+                    mapOf(
+                        Back to UserActionResult(Scenes.Lockscreen),
+                        Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Lockscreen),
+                    )
+                )
+        }
+
+    @Test
+    fun destinations_whenCustomizing_noDestinations() =
         testScope.runTest {
             overrideResource(R.bool.config_use_split_notification_shade, false)
             val destinations by collectLastValue(underTest.destinationScenes)
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 62ed491..1908d88 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
@@ -25,11 +25,14 @@
 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.Scenes
 import com.android.systemui.shade.ui.viewmodel.ShadeHeaderViewModel
 import com.android.systemui.statusbar.notification.stack.ui.viewmodel.NotificationsPlaceholderViewModel
 import java.util.concurrent.atomic.AtomicBoolean
 import javax.inject.Inject
+import kotlinx.coroutines.flow.flatMapLatest
+import kotlinx.coroutines.flow.flowOf
 import kotlinx.coroutines.flow.map
 
 /** Models UI state and handles user input for the quick settings scene. */
@@ -42,20 +45,23 @@
     val notifications: NotificationsPlaceholderViewModel,
     private val footerActionsViewModelFactory: FooterActionsViewModel.Factory,
     private val footerActionsController: FooterActionsController,
+    private val sceneInteractor: SceneInteractor,
 ) {
     val destinationScenes =
-        qsSceneAdapter.isCustomizing.map { customizing ->
+        qsSceneAdapter.isCustomizing.flatMapLatest { customizing ->
             if (customizing) {
                 // TODO(b/332749288) Empty map so there are no back handlers and back can close
                 // customizer
-                emptyMap()
+                flowOf(emptyMap())
                 // TODO(b/330200163) Add an Up from Bottom to be able to collapse the shade
                 // while customizing
             } else {
-                mapOf(
-                    Back to UserActionResult(Scenes.Shade),
-                    Swipe(SwipeDirection.Up) to UserActionResult(Scenes.Shade),
-                )
+                sceneInteractor.previousScene.map { previousScene ->
+                    mapOf(
+                        Back to UserActionResult(previousScene ?: Scenes.Shade),
+                        Swipe(SwipeDirection.Up) to UserActionResult(previousScene ?: Scenes.Shade),
+                    )
+                }
             }
         }