Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a3ea108e authored by Danny Burakov's avatar Danny Burakov Committed by Android (Google) Code Review
Browse files

Merge "[Dual Shade] Gracefully switch from Single shade to Dual shade." into main

parents 4520900f bad84a54
Loading
Loading
Loading
Loading
+27 −27
Original line number Diff line number Diff line
@@ -207,33 +207,33 @@ private fun ContentScope.ShadeScene(
    shadeSession: SaveableSession,
    usingCollapsedLandscapeMedia: Boolean,
) {
    when (viewModel.shadeMode) {
        is ShadeMode.Single ->
            SingleShade(
    if (viewModel.shadeMode is ShadeMode.Split) {
        SplitShade(
            notificationStackScrollView = notificationStackScrollView,
            viewModel = viewModel,
            headerViewModel = headerViewModel,
            notificationsPlaceholderViewModel = notificationsPlaceholderViewModel,
            mediaCarouselController = mediaCarouselController,
                mediaHost = qqsMediaHost,
            mediaHost = qsMediaHost,
            modifier = modifier,
            shadeSession = shadeSession,
                usingCollapsedLandscapeMedia = usingCollapsedLandscapeMedia,
            jankMonitor = jankMonitor,
        )
        is ShadeMode.Split ->
            SplitShade(
    } else {
        // Compose SingleShade even if we're in Dual shade mode; the view-model will take care of
        // switching scenes.
        SingleShade(
            notificationStackScrollView = notificationStackScrollView,
            viewModel = viewModel,
            headerViewModel = headerViewModel,
            notificationsPlaceholderViewModel = notificationsPlaceholderViewModel,
            mediaCarouselController = mediaCarouselController,
                mediaHost = qsMediaHost,
            mediaHost = qqsMediaHost,
            modifier = modifier,
            shadeSession = shadeSession,
            usingCollapsedLandscapeMedia = usingCollapsedLandscapeMedia,
            jankMonitor = jankMonitor,
        )
        is ShadeMode.Dual -> error("Dual shade is implemented separately as an overlay.")
    }
}

+34 −0
Original line number Diff line number Diff line
@@ -42,6 +42,8 @@ import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.ui.viewmodel.notificationsShadeOverlayContentViewModel
import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
@@ -186,6 +188,38 @@ class NotificationsShadeOverlayContentViewModelTest : SysuiTestCase() {
            assertThat(underTest.isTransparencyEnabled).isFalse()
        }

    @Test
    fun shadeModeChanged_single_switchesToShadeScene() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            kosmos.enableDualShade()
            kosmos.shadeInteractor.expandNotificationsShade("test")
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).contains(Overlays.NotificationsShade)

            kosmos.enableSingleShade()
            assertThat(currentScene).isEqualTo(Scenes.Shade)
            assertThat(currentOverlays).doesNotContain(Overlays.NotificationsShade)
        }

    @Test
    fun shadeModeChanged_split_switchesToShadeScene() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            kosmos.enableDualShade()
            kosmos.shadeInteractor.expandNotificationsShade("test")
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).contains(Overlays.NotificationsShade)

            kosmos.enableSplitShade()
            assertThat(currentScene).isEqualTo(Scenes.Shade)
            assertThat(currentOverlays).doesNotContain(Overlays.NotificationsShade)
        }

    private fun TestScope.lockDevice() {
        val currentScene by collectLastValue(sceneInteractor.currentScene)
        kosmos.powerInteractor.setAsleepForTest()
+26 −1
Original line number Diff line number Diff line
@@ -35,10 +35,14 @@ import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.settings.brightness.ui.viewmodel.brightnessMirrorViewModelFactory
import com.android.systemui.shade.domain.interactor.disableDualShade
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.domain.interactor.shadeModeInteractor
import com.android.systemui.shade.ui.viewmodel.shadeHeaderViewModelFactory
import com.android.systemui.testKosmos
@@ -127,12 +131,33 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
        }

    @Test
    fun shadeModeChange_switchToShadeScene() =
    fun shadeModeChange_split_switchToShadeScene() =
        kosmos.runTest {
            val scene by collectLastValue(sceneInteractor.currentScene)

            enableSingleShade()
            shadeInteractor.expandQuickSettingsShade("test")
            assertThat(scene).isEqualTo(Scenes.QuickSettings)

            enableSplitShade()

            assertThat(scene).isEqualTo(Scenes.Shade)
        }

    @Test
    fun shadeModeChange_dual_switchToOverlay() =
        kosmos.runTest {
            val scene by collectLastValue(sceneInteractor.currentScene)
            val overlays by collectLastValue(sceneInteractor.currentOverlays)

            enableSingleShade()
            shadeInteractor.expandQuickSettingsShade("test")
            assertThat(scene).isEqualTo(Scenes.QuickSettings)
            assertThat(overlays).isEmpty()

            enableDualShade()

            assertThat(scene).isEqualTo(Scenes.Lockscreen)
            assertThat(overlays).containsExactly(Overlays.QuickSettingsShade)
        }
}
+40 −0
Original line number Diff line number Diff line
@@ -37,12 +37,15 @@ import com.android.systemui.scene.domain.startable.sceneContainerStartable
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimShape
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationScrollViewModel
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
@@ -50,6 +53,7 @@ import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@@ -111,6 +115,42 @@ class QuickSettingsShadeOverlayContentViewModelTest : SysuiTestCase() {
            assertThat(currentOverlays).doesNotContain(Overlays.QuickSettingsShade)
        }

    @Test
    fun shadeModeChanged_single_switchesToQuickSettingsScene() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            kosmos.enableDualShade()
            kosmos.shadeInteractor.expandQuickSettingsShade("test")
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).contains(Overlays.QuickSettingsShade)

            kosmos.enableSingleShade()
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.QuickSettings)
            assertThat(currentOverlays).doesNotContain(Overlays.QuickSettingsShade)
        }

    @Test
    fun shadeModeChanged_split_switchesToShadeScene() =
        testScope.runTest {
            val currentScene by collectLastValue(sceneInteractor.currentScene)
            val currentOverlays by collectLastValue(sceneInteractor.currentOverlays)

            kosmos.enableDualShade()
            kosmos.shadeInteractor.expandQuickSettingsShade("test")
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.Lockscreen)
            assertThat(currentOverlays).contains(Overlays.QuickSettingsShade)

            kosmos.enableSplitShade()
            runCurrent()
            assertThat(currentScene).isEqualTo(Scenes.Shade)
            assertThat(currentOverlays).doesNotContain(Overlays.QuickSettingsShade)
        }

    @Test
    fun onPanelShapeChanged() =
        testScope.runTest {
+40 −0
Original line number Diff line number Diff line
@@ -43,10 +43,12 @@ import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Overlays
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.shadeInteractor
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
import com.android.systemui.testKosmos
@@ -136,6 +138,44 @@ class ShadeSceneContentViewModelTest : SysuiTestCase() {
            assertThat(underTest.shadeMode).isEqualTo(ShadeMode.Dual)
        }

    @Test
    fun shadeModeChange_dualOnLockscreen_switchToOverlay() =
        kosmos.runTest {
            setDeviceEntered(false)
            val scene by collectLastValue(sceneInteractor.currentScene)
            val overlays by collectLastValue(sceneInteractor.currentOverlays)

            enableSingleShade()

            shadeInteractor.expandNotificationsShade("test")
            assertThat(scene).isEqualTo(Scenes.Shade)
            assertThat(overlays).isEmpty()

            enableDualShade()

            assertThat(scene).isEqualTo(Scenes.Lockscreen)
            assertThat(overlays).containsExactly(Overlays.NotificationsShade)
        }

    @Test
    fun shadeModeChange_dualOnGone_switchToOverlay() =
        kosmos.runTest {
            setDeviceEntered(true)
            val scene by collectLastValue(sceneInteractor.currentScene)
            val overlays by collectLastValue(sceneInteractor.currentOverlays)

            enableSingleShade()

            shadeInteractor.expandNotificationsShade("test")
            assertThat(scene).isEqualTo(Scenes.Shade)
            assertThat(overlays).isEmpty()

            enableDualShade()

            assertThat(scene).isEqualTo(Scenes.Gone)
            assertThat(overlays).containsExactly(Overlays.NotificationsShade)
        }

    @Test
    fun unfoldTransitionProgress() =
        testKosmos().useStandardTestDispatcher().runTest {
Loading