Merge "[Flexiglass] Fix split shade layout and transitions" into main
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt
index 3eb1b14..604b517 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/common/ui/compose/windowinsets/DisplayCutout.kt
@@ -35,6 +35,7 @@
     val viewDisplayCutoutKeyguardStatusBarView: ViewDisplayCutout? = null,
 ) {
     fun width() = abs(right.value - left.value).dp
+    fun height() = abs(bottom.value - top.value).dp
 }
 
 enum class CutoutLocation {
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
index ec9136d..bca8fde 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt
@@ -320,7 +320,6 @@
                                 createTintedIconManager = createTintedIconManager,
                                 createBatteryMeterViewController = createBatteryMeterViewController,
                                 statusBarIconController = statusBarIconController,
-                                modifier = Modifier.padding(horizontal = 16.dp),
                             )
                     }
                     Spacer(modifier = Modifier.height(16.dp))
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
index 7eaebc2..ff9c5a5 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/SceneContainerTransitions.kt
@@ -5,10 +5,13 @@
 import com.android.systemui.bouncer.ui.composable.Bouncer
 import com.android.systemui.notifications.ui.composable.Notifications
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.shared.model.TransitionKeys.CollapseShadeInstantly
+import com.android.systemui.scene.shared.model.TransitionKeys.GoneToSplitShade
 import com.android.systemui.scene.shared.model.TransitionKeys.SlightlyFasterShadeCollapse
 import com.android.systemui.scene.ui.composable.transitions.bouncerToGoneTransition
 import com.android.systemui.scene.ui.composable.transitions.goneToQuickSettingsTransition
 import com.android.systemui.scene.ui.composable.transitions.goneToShadeTransition
+import com.android.systemui.scene.ui.composable.transitions.goneToSplitShadeTransition
 import com.android.systemui.scene.ui.composable.transitions.lockscreenToBouncerTransition
 import com.android.systemui.scene.ui.composable.transitions.lockscreenToCommunalTransition
 import com.android.systemui.scene.ui.composable.transitions.lockscreenToGoneTransition
@@ -38,6 +41,13 @@
     from(
         Scenes.Gone,
         to = Scenes.Shade,
+        key = GoneToSplitShade,
+    ) {
+        goneToSplitShadeTransition()
+    }
+    from(
+        Scenes.Gone,
+        to = Scenes.Shade,
         key = SlightlyFasterShadeCollapse,
     ) {
         goneToShadeTransition(durationScale = 0.9)
@@ -68,5 +78,9 @@
             Notifications.Elements.NotificationScrim,
             y = { Shade.Dimensions.ScrimOverscrollLimit }
         )
+        translate(
+            Shade.Elements.SplitShadeStartColumn,
+            y = { Shade.Dimensions.ScrimOverscrollLimit }
+        )
     }
 }
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
new file mode 100644
index 0000000..4dc36d6
--- /dev/null
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/scene/ui/composable/transitions/FromGoneToSplitShadeTransition.kt
@@ -0,0 +1,65 @@
+/*
+ * 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.ui.composable.transitions
+
+import androidx.compose.animation.core.Spring
+import androidx.compose.animation.core.spring
+import androidx.compose.animation.core.tween
+import androidx.compose.foundation.gestures.Orientation
+import androidx.compose.ui.unit.IntSize
+import com.android.compose.animation.scene.TransitionBuilder
+import com.android.compose.animation.scene.UserActionDistance
+import com.android.compose.animation.scene.UserActionDistanceScope
+import com.android.systemui.notifications.ui.composable.Notifications
+import com.android.systemui.qs.ui.composable.QuickSettings
+import com.android.systemui.shade.ui.composable.Shade
+import com.android.systemui.shade.ui.composable.ShadeHeader
+import kotlin.time.Duration.Companion.milliseconds
+
+fun TransitionBuilder.goneToSplitShadeTransition(
+    durationScale: Double = 1.0,
+) {
+    spec = tween(durationMillis = (DefaultDuration * durationScale).inWholeMilliseconds.toInt())
+    swipeSpec =
+        spring(
+            stiffness = Spring.StiffnessMediumLow,
+            visibilityThreshold = Shade.Dimensions.ScrimVisibilityThreshold,
+        )
+    distance =
+        object : UserActionDistance {
+            override fun UserActionDistanceScope.absoluteDistance(
+                fromSceneSize: IntSize,
+                orientation: Orientation,
+            ): Float {
+                return fromSceneSize.height.toFloat() * 2 / 3f
+            }
+        }
+
+    fractionRange(end = .33f) { fade(Shade.Elements.BackgroundScrim) }
+
+    fractionRange(start = .33f) {
+        fade(ShadeHeader.Elements.Clock)
+        fade(ShadeHeader.Elements.CollapsedContentStart)
+        fade(ShadeHeader.Elements.CollapsedContentEnd)
+        fade(ShadeHeader.Elements.PrivacyChip)
+        fade(QuickSettings.Elements.SplitShadeQuickSettings)
+        fade(QuickSettings.Elements.FooterActions)
+        fade(Notifications.Elements.NotificationScrim)
+    }
+}
+
+private val DefaultDuration = 500.milliseconds
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
index 0bd38a1..709a416 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeHeader.kt
@@ -50,6 +50,7 @@
 import androidx.compose.ui.unit.Constraints
 import androidx.compose.ui.unit.LayoutDirection
 import androidx.compose.ui.unit.dp
+import androidx.compose.ui.unit.max
 import androidx.compose.ui.viewinterop.AndroidView
 import com.android.compose.animation.scene.ElementKey
 import com.android.compose.animation.scene.LowestZIndexScenePicker
@@ -63,6 +64,7 @@
 import com.android.systemui.battery.BatteryMeterViewController
 import com.android.systemui.common.ui.compose.windowinsets.CutoutLocation
 import com.android.systemui.common.ui.compose.windowinsets.LocalDisplayCutout
+import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius
 import com.android.systemui.compose.modifiers.sysuiResTag
 import com.android.systemui.privacy.OngoingPrivacyChip
 import com.android.systemui.res.R
@@ -77,6 +79,7 @@
 import com.android.systemui.statusbar.pipeline.mobile.ui.view.ModernShadeCarrierGroupMobileView
 import com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.ShadeCarrierGroupMobileIconViewModel
 import com.android.systemui.statusbar.policy.Clock
+import kotlin.math.max
 
 object ShadeHeader {
     object Elements {
@@ -121,7 +124,11 @@
     }
 
     val cutoutWidth = LocalDisplayCutout.current.width()
+    val cutoutHeight = LocalDisplayCutout.current.height()
+    val cutoutTop = LocalDisplayCutout.current.top
     val cutoutLocation = LocalDisplayCutout.current.location
+    val horizontalPadding =
+        max(LocalScreenCornerRadius.current / 2f, Shade.Dimensions.HorizontalPadding)
 
     val useExpandedFormat by
         remember(cutoutLocation) {
@@ -140,7 +147,7 @@
         contents =
             listOf(
                 {
-                    Row {
+                    Row(modifier = Modifier.padding(horizontal = horizontalPadding)) {
                         Clock(
                             scale = 1f,
                             viewModel = viewModel,
@@ -157,7 +164,12 @@
                 },
                 {
                     if (isPrivacyChipVisible) {
-                        Box(modifier = Modifier.height(CollapsedHeight).fillMaxWidth()) {
+                        Box(
+                            modifier =
+                                Modifier.height(CollapsedHeight)
+                                    .fillMaxWidth()
+                                    .padding(horizontal = horizontalPadding)
+                        ) {
                             PrivacyChip(
                                 viewModel = viewModel,
                                 modifier = Modifier.align(Alignment.CenterEnd),
@@ -166,9 +178,13 @@
                     } else {
                         Row(
                             horizontalArrangement = Arrangement.End,
-                            modifier = Modifier.element(ShadeHeader.Elements.CollapsedContentEnd)
+                            modifier =
+                                Modifier.element(ShadeHeader.Elements.CollapsedContentEnd)
+                                    .padding(horizontal = horizontalPadding)
                         ) {
-                            SystemIconContainer {
+                            SystemIconContainer(
+                                modifier = Modifier.align(Alignment.CenterVertically)
+                            ) {
                                 when (LocalWindowSizeClass.current.widthSizeClass) {
                                     WindowWidthSizeClass.Medium,
                                     WindowWidthSizeClass.Expanded ->
@@ -206,7 +222,7 @@
 
         val screenWidth = constraints.maxWidth
         val cutoutWidthPx = cutoutWidth.roundToPx()
-        val height = CollapsedHeight.roundToPx()
+        val height = max(cutoutHeight + (cutoutTop * 2), CollapsedHeight).roundToPx()
         val childConstraints = Constraints.fixed((screenWidth - cutoutWidthPx) / 2, height)
 
         val startMeasurable = measurables[0][0]
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
index 4ad8b9f..36b60d6 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt
@@ -67,6 +67,7 @@
 import com.android.compose.modifiers.padding
 import com.android.compose.modifiers.thenIf
 import com.android.systemui.battery.BatteryMeterViewController
+import com.android.systemui.common.ui.compose.windowinsets.LocalScreenCornerRadius
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.media.controls.ui.composable.MediaCarousel
 import com.android.systemui.media.controls.ui.controller.MediaCarouselController
@@ -97,6 +98,7 @@
         val MediaCarousel = ElementKey("ShadeMediaCarousel")
         val BackgroundScrim =
             ElementKey("ShadeBackgroundScrim", scenePicker = LowestZIndexScenePicker)
+        val SplitShadeStartColumn = ElementKey("SplitShadeStartColumn")
     }
 
     object Dimensions {
@@ -250,10 +252,6 @@
                                 createTintedIconManager = createTintedIconManager,
                                 createBatteryMeterViewController = createBatteryMeterViewController,
                                 statusBarIconController = statusBarIconController,
-                                modifier =
-                                    Modifier.padding(
-                                        horizontal = Shade.Dimensions.HorizontalPadding
-                                    )
                             )
                             Box(Modifier.element(QuickSettings.Elements.QuickQuickSettings)) {
                                 QuickSettings(
@@ -312,6 +310,8 @@
     modifier: Modifier = Modifier,
     shadeSession: SaveableSession,
 ) {
+    val screenCornerRadius = LocalScreenCornerRadius.current
+
     val isCustomizing by viewModel.qsSceneAdapter.isCustomizing.collectAsState()
     val isCustomizerShowing by viewModel.qsSceneAdapter.isCustomizerShowing.collectAsState()
     val customizingAnimationDuration by
@@ -320,7 +320,11 @@
     val footerActionsViewModel =
         remember(lifecycleOwner, viewModel) { viewModel.getFooterActionsViewModel(lifecycleOwner) }
     val tileSquishiness by
-        animateSceneFloatAsState(value = 1f, key = QuickSettings.SharedValues.TilesSquishiness)
+        animateSceneFloatAsState(
+            value = 1f,
+            key = QuickSettings.SharedValues.TilesSquishiness,
+            canOverflow = false,
+        )
     val unfoldTranslationXForStartSide by
         viewModel
             .unfoldTranslationX(
@@ -388,8 +392,7 @@
                 createBatteryMeterViewController = createBatteryMeterViewController,
                 statusBarIconController = statusBarIconController,
                 modifier =
-                    Modifier.padding(horizontal = Shade.Dimensions.HorizontalPadding)
-                        .then(brightnessMirrorShowingModifier)
+                    Modifier.then(brightnessMirrorShowingModifier)
                         .padding(
                             horizontal = { unfoldTranslationXForStartSide.roundToInt() },
                         )
@@ -398,9 +401,9 @@
             Row(modifier = Modifier.fillMaxWidth().weight(1f)) {
                 Box(
                     modifier =
-                        Modifier.weight(1f).graphicsLayer {
-                            translationX = unfoldTranslationXForStartSide
-                        },
+                        Modifier.element(Shade.Elements.SplitShadeStartColumn)
+                            .weight(1f)
+                            .graphicsLayer { translationX = unfoldTranslationXForStartSide },
                 ) {
                     BrightnessMirror(
                         viewModel = viewModel.brightnessMirrorViewModel,
@@ -467,7 +470,7 @@
                     modifier =
                         Modifier.weight(1f)
                             .fillMaxHeight()
-                            .padding(bottom = navBarBottomHeight)
+                            .padding(end = screenCornerRadius / 2f, bottom = navBarBottomHeight)
                             .then(brightnessMirrorShowingModifier)
                 )
             }
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt
new file mode 100644
index 0000000..a2ffe70
--- /dev/null
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt
@@ -0,0 +1,82 @@
+/*
+ * 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.scene.ui.viewmodel
+
+import android.testing.TestableLooper
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.Swipe
+import com.android.compose.animation.scene.SwipeDirection
+import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.flags.EnableSceneContainer
+import com.android.systemui.kosmos.testScope
+import com.android.systemui.scene.shared.model.TransitionKeys.GoneToSplitShade
+import com.android.systemui.shade.data.repository.shadeRepository
+import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.shared.model.ShadeMode
+import com.android.systemui.testKosmos
+import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.runCurrent
+import kotlinx.coroutines.test.runTest
+import org.junit.Before
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@OptIn(ExperimentalCoroutinesApi::class)
+@SmallTest
+@RunWith(AndroidJUnit4::class)
+@TestableLooper.RunWithLooper
+@EnableSceneContainer
+class GoneSceneViewModelTest : SysuiTestCase() {
+
+    private val kosmos = testKosmos()
+    private val testScope = kosmos.testScope
+    private val shadeRepository by lazy { kosmos.shadeRepository }
+    private lateinit var underTest: GoneSceneViewModel
+
+    @Before
+    fun setUp() {
+        underTest =
+            GoneSceneViewModel(
+                applicationScope = testScope.backgroundScope,
+                shadeInteractor = kosmos.shadeInteractor,
+            )
+    }
+
+    @Test
+    fun downTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
+        testScope.runTest {
+            val destinationScenes by collectLastValue(underTest.destinationScenes)
+            shadeRepository.setShadeMode(ShadeMode.Split)
+            runCurrent()
+
+            assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey)
+                .isEqualTo(GoneToSplitShade)
+        }
+
+    @Test
+    fun downTransitionKey_splitShadeDisabled_isNull() =
+        testScope.runTest {
+            val destinationScenes by collectLastValue(underTest.destinationScenes)
+            shadeRepository.setShadeMode(ShadeMode.Single)
+            runCurrent()
+
+            assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
+        }
+}
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 5312ad8..2439217 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
@@ -39,6 +39,7 @@
 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.scene.shared.model.TransitionKeys.GoneToSplitShade
 import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModel
 import com.android.systemui.shade.data.repository.shadeRepository
 import com.android.systemui.shade.domain.interactor.shadeInteractor
@@ -159,6 +160,27 @@
         }
 
     @Test
+    fun upTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
+        testScope.runTest {
+            val destinationScenes by collectLastValue(underTest.destinationScenes)
+            shadeRepository.setShadeMode(ShadeMode.Split)
+            runCurrent()
+
+            assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.transitionKey)
+                .isEqualTo(GoneToSplitShade)
+        }
+
+    @Test
+    fun upTransitionKey_splitShadeDisabled_isNull() =
+        testScope.runTest {
+            val destinationScenes by collectLastValue(underTest.destinationScenes)
+            shadeRepository.setShadeMode(ShadeMode.Single)
+            runCurrent()
+
+            assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.transitionKey).isNull()
+        }
+
+    @Test
     fun isClickable_deviceUnlocked_false() =
         testScope.runTest {
             val isClickable by collectLastValue(underTest.isClickable)
diff --git a/packages/SystemUI/src/com/android/systemui/scene/shared/model/TransitionKeys.kt b/packages/SystemUI/src/com/android/systemui/scene/shared/model/TransitionKeys.kt
index b91dd04..0603d21 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/shared/model/TransitionKeys.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/shared/model/TransitionKeys.kt
@@ -24,6 +24,8 @@
  * These are the subset of transitions that can be referenced by key when asking for a scene change.
  */
 object TransitionKeys {
+    /** Reference to the gone to shade transition with split shade enabled. */
+    val GoneToSplitShade = TransitionKey("GoneToSplitShade")
 
     /** Reference to a scene transition that can collapse the shade scene instantly. */
     val CollapseShadeInstantly = TransitionKey("CollapseShadeInstantly")
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
index 78704e1..c20d577 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootViewBinder.kt
@@ -198,7 +198,7 @@
     private fun getDisplayWidth(context: Context): Dp {
         val point = Point()
         checkNotNull(context.display).getRealSize(point)
-        return point.x.dp
+        return point.x.toDp(context)
     }
 
     // TODO(b/298525212): remove once Compose exposes window inset bounds.
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt
index b0af7f9..016fe57 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModel.kt
@@ -24,6 +24,7 @@
 import com.android.systemui.dagger.SysUISingleton
 import com.android.systemui.dagger.qualifiers.Application
 import com.android.systemui.scene.shared.model.Scenes
+import com.android.systemui.scene.shared.model.TransitionKeys.GoneToSplitShade
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
 import javax.inject.Inject
@@ -70,10 +71,11 @@
                     )] = UserActionResult(Scenes.QuickSettingsShade)
             }
 
+            val downSceneKey =
+                if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade
+            val downTransitionKey = GoneToSplitShade.takeIf { shadeMode is ShadeMode.Split }
             this[Swipe(direction = SwipeDirection.Down)] =
-                UserActionResult(
-                    if (shadeMode is ShadeMode.Dual) Scenes.NotificationsShade else Scenes.Shade
-                )
+                UserActionResult(downSceneKey, downTransitionKey)
         }
     }
 }
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 ac76bec..d15a488 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
@@ -33,6 +33,7 @@
 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.scene.shared.model.TransitionKeys.GoneToSplitShade
 import com.android.systemui.settings.brightness.ui.viewModel.BrightnessMirrorViewModel
 import com.android.systemui.shade.domain.interactor.ShadeInteractor
 import com.android.systemui.shade.shared.model.ShadeMode
@@ -152,11 +153,13 @@
                 else -> Scenes.Lockscreen
             }
 
+        val upTransitionKey = GoneToSplitShade.takeIf { shadeMode is ShadeMode.Split }
+
         val down = Scenes.QuickSettings.takeIf { shadeMode is ShadeMode.Single }
 
         return buildMap {
             if (!isCustomizing) {
-                this[Swipe(SwipeDirection.Up)] = UserActionResult(up)
+                this[Swipe(SwipeDirection.Up)] = UserActionResult(up, upTransitionKey)
             } // TODO(b/330200163) Add an else to be able to collapse the shade while customizing
             down?.let { this[Swipe(SwipeDirection.Down)] = UserActionResult(down) }
         }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 773a6bf..232b4e9 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -1469,9 +1469,10 @@
     public void setExpandedHeight(float height) {
         final boolean skipHeightUpdate = shouldSkipHeightUpdate();
 
-        // when scene framework is enabled, updateStackPosition is already called by
-        // updateTopPadding every time the stack moves, so skip it here to avoid flickering.
-        if (!SceneContainerFlag.isEnabled()) {
+        // when scene framework is enabled and in single shade, updateStackPosition is already
+        // called by updateTopPadding every time the stack moves, so skip it here to avoid
+        // flickering.
+        if (!SceneContainerFlag.isEnabled() || mShouldUseSplitNotificationShade) {
             updateStackPosition();
         }