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

Commit e9366ecd authored by burakov's avatar burakov
Browse files

[Dual Shade] Show single shade on phones in landscape orientation.

Prior to this change, a narrow device (phone) in landscape orientation
would show either split shade (if dual shade is disabled) or dual shade
(if enabled).

This would cause the effect that when the user opted out of dual shade,
they would see split shade when rotating the phone to landscape. Once we
get rid of split shade this would be dual shade, also a surprising
behavior for the user. The single shade UI is preferred in this state.

Fix: 433709856
Test: Tested manually by rotating a phone with single shade, and
 observing that single shade is shown in landscape orientation as well.
Test: Added and updated unit tests.
Flag: com.android.systemui.scene_container
Change-Id: Ia34dc03a2845c03e3600d631e5699fec87001100
parent 0d147139
Loading
Loading
Loading
Loading
+4 −13
Original line number Original line Diff line number Diff line
@@ -167,7 +167,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() {


    @Test
    @Test
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
    @EnableFlags(Flags.FLAG_COMMUNAL_HUB)
    fun userActions_fullscreenShade() =
    fun userActions_combinedShade() =
        kosmos.runTest {
        kosmos.runTest {
            disableDualShade()
            disableDualShade()
            fakeDeviceEntryRepository.setLockscreenEnabled(true)
            fakeDeviceEntryRepository.setLockscreenEnabled(true)
@@ -180,13 +180,9 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() {
            )
            )
            sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
            sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
            shadeRepository.setShadeLayoutWide(!isNarrowScreen)
            shadeRepository.setShadeLayoutWide(!isNarrowScreen)
            shadeRepository.setLargeScreen(!isNarrowScreen)
            fakePowerRepository.updateWakefulness(
            fakePowerRepository.updateWakefulness(
                rawState =
                rawState = if (isShadeTouchable) WakefulnessState.AWAKE else WakefulnessState.ASLEEP
                    if (isShadeTouchable) {
                        WakefulnessState.AWAKE
                    } else {
                        WakefulnessState.ASLEEP
                    }
            )
            )
            keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = isOccluded)
            keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = isOccluded)


@@ -256,12 +252,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() {
            )
            )
            sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
            sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
            fakePowerRepository.updateWakefulness(
            fakePowerRepository.updateWakefulness(
                rawState =
                rawState = if (isShadeTouchable) WakefulnessState.AWAKE else WakefulnessState.ASLEEP
                    if (isShadeTouchable) {
                        WakefulnessState.AWAKE
                    } else {
                        WakefulnessState.ASLEEP
                    }
            )
            )
            keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = isOccluded)
            keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = isOccluded)


+22 −2
Original line number Original line Diff line number Diff line
@@ -35,16 +35,15 @@ import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.shade.shared.flag.ShadeWindowGoesAround
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Before
import org.junit.Before
import org.junit.Test
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.runner.RunWith


@SmallTest
@SmallTest
@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@EnableFlags(ShadeWindowGoesAround.FLAG_NAME)
@EnableFlags(ShadeWindowGoesAround.FLAG_NAME)
class ShadeDisplayStateInteractorTest : SysuiTestCase() {
class ShadeDisplayStateInteractorTest : SysuiTestCase() {

    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val secondaryDisplayStateRepository = FakeDisplayStateRepository()
    private val secondaryDisplayStateRepository = FakeDisplayStateRepository()
    private val secondaryDisplayStateInteractor =
    private val secondaryDisplayStateInteractor =
@@ -98,6 +97,27 @@ class ShadeDisplayStateInteractorTest : SysuiTestCase() {
            assertThat(isWideScreen).isFalse()
            assertThat(isWideScreen).isFalse()
        }
        }


    @Test
    fun isLargeScreen_afterDisplayChange_returnsCorrectValue() =
        kosmos.runTest {
            defaultDisplayStateRepository.setIsLargeScreen(false)
            secondaryDisplayStateRepository.setIsLargeScreen(true)

            fakeShadeDisplaysRepository.setDisplayId(DEFAULT_DISPLAY)

            val isLargeScreen by collectLastValue(underTest.isLargeScreen)

            assertThat(isLargeScreen).isFalse()

            fakeShadeDisplaysRepository.setDisplayId(SECONDARY_DISPLAY)

            assertThat(isLargeScreen).isTrue()

            fakeShadeDisplaysRepository.setDisplayId(DEFAULT_DISPLAY)

            assertThat(isLargeScreen).isFalse()
        }

    private companion object {
    private companion object {
        const val DEFAULT_DISPLAY = Display.DEFAULT_DISPLAY
        const val DEFAULT_DISPLAY = Display.DEFAULT_DISPLAY
        const val SECONDARY_DISPLAY = DEFAULT_DISPLAY + 1
        const val SECONDARY_DISPLAY = DEFAULT_DISPLAY + 1
+10 −1
Original line number Original line Diff line number Diff line
@@ -45,7 +45,16 @@ class ShadeModeInteractorImplTest : SysuiTestCase() {
    fun legacyShadeMode_narrowScreen_singleShade() =
    fun legacyShadeMode_narrowScreen_singleShade() =
        kosmos.runTest {
        kosmos.runTest {
            val shadeMode by collectLastValue(underTest.shadeMode)
            val shadeMode by collectLastValue(underTest.shadeMode)
            enableSingleShade()
            enableSingleShade(wideLayout = false)

            assertThat(shadeMode).isEqualTo(ShadeMode.Single)
        }

    @Test
    fun legacyShadeMode_wideScreen_singleShade() =
        kosmos.runTest {
            val shadeMode by collectLastValue(underTest.shadeMode)
            enableSingleShade(wideLayout = true)


            assertThat(shadeMode).isEqualTo(ShadeMode.Single)
            assertThat(shadeMode).isEqualTo(ShadeMode.Single)
        }
        }
+60 −3
Original line number Original line Diff line number Diff line
@@ -18,12 +18,18 @@ package com.android.systemui.shade.domain.startable


import android.platform.test.flag.junit.FlagsParameterization
import android.platform.test.flag.junit.FlagsParameterization
import android.testing.TestableLooper.RunWithLooper
import android.testing.TestableLooper.RunWithLooper
import android.view.Display
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.authentication.shared.model.AuthenticationMethodModel
import com.android.systemui.display.data.repository.createFakeDisplaySubcomponent
import com.android.systemui.display.data.repository.displayStateRepository
import com.android.systemui.display.data.repository.displaySubcomponentPerDisplayRepository
import com.android.systemui.display.domain.interactor.createDisplayStateInteractor
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.flags.parameterizeSceneContainerFlag
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
@@ -37,6 +43,8 @@ import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.scene.shared.model.fakeSceneDataSource
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionListener
import com.android.systemui.shade.ShadeExpansionListener
import com.android.systemui.shade.data.repository.fakeShadeDisplaysRepository
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableDualShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
@@ -86,11 +94,24 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {


    @Before
    @Before
    fun setUp() {
    fun setUp() {
        kosmos.shadeExpansionStateManager.addExpansionListener(
        with(kosmos) {
            kosmos.notificationShadeDepthController
            shadeExpansionStateManager.addExpansionListener(notificationShadeDepthController)

            displaySubcomponentPerDisplayRepository.apply {
                add(
                    Display.DEFAULT_DISPLAY,
                    createFakeDisplaySubcomponent(
                        displayStateRepository = displayStateRepository,
                        displayStateInteractor =
                            createDisplayStateInteractor(displayStateRepository),
                    ),
                )
                )
            }
            }


            fakeShadeDisplaysRepository.setDisplayId(Display.DEFAULT_DISPLAY)
        }
    }

    @Test
    @Test
    fun hydrateShadeMode_dualShadeDisabled() =
    fun hydrateShadeMode_dualShadeDisabled() =
        kosmos.runTest {
        kosmos.runTest {
@@ -204,44 +225,80 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {
    @EnableSceneContainer
    @EnableSceneContainer
    fun hydrateFullWidth_singleShade() =
    fun hydrateFullWidth_singleShade() =
        kosmos.runTest {
        kosmos.runTest {
            val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
            enableSingleShade()
            enableSingleShade()
            underTest.start()
            underTest.start()


            verify(notificationStackScrollLayoutController).setIsFullWidth(true)
            verify(notificationStackScrollLayoutController).setIsFullWidth(true)
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(isShadeLayoutWide).isFalse()
        }
        }


    @Test
    @Test
    @EnableSceneContainer
    @EnableSceneContainer
    fun hydrateFullWidth_splitShade() =
    fun hydrateFullWidth_splitShade() =
        kosmos.runTest {
        kosmos.runTest {
            val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
            enableSplitShade()
            enableSplitShade()
            underTest.start()
            underTest.start()


            verify(notificationStackScrollLayoutController).setIsFullWidth(false)
            verify(notificationStackScrollLayoutController).setIsFullWidth(false)
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(isShadeLayoutWide).isTrue()
        }
        }


    @Test
    @Test
    @EnableSceneContainer
    @EnableSceneContainer
    fun hydrateFullWidth_dualShade_narrowScreen() =
    fun hydrateFullWidth_dualShade_narrowScreen() =
        kosmos.runTest {
        kosmos.runTest {
            val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
            enableDualShade(wideLayout = false)
            enableDualShade(wideLayout = false)
            underTest.start()
            underTest.start()


            verify(notificationStackScrollLayoutController).setIsFullWidth(true)
            verify(notificationStackScrollLayoutController).setIsFullWidth(true)
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(isShadeLayoutWide).isFalse()
        }
        }


    @Test
    @Test
    @EnableSceneContainer
    @EnableSceneContainer
    fun hydrateFullWidth_dualShade_wideScreen() =
    fun hydrateFullWidth_dualShade_wideScreen() =
        kosmos.runTest {
        kosmos.runTest {
            val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
            enableDualShade(wideLayout = true)
            enableDualShade(wideLayout = true)
            underTest.start()
            underTest.start()


            verify(notificationStackScrollLayoutController).setIsFullWidth(false)
            verify(notificationStackScrollLayoutController).setIsFullWidth(false)
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(scrimController.clipQsScrim).isFalse()
            assertThat(isShadeLayoutWide).isTrue()
        }

    @Test
    @EnableSceneContainer
    fun hydrateLargeScreen_sceneContainer() =
        kosmos.runTest {
            val isLargeScreen by collectLastValue(shadeRepository.isLargeScreen)
            underTest.start()

            displayStateRepository.setIsLargeScreen(false)
            assertThat(isLargeScreen).isFalse()

            displayStateRepository.setIsLargeScreen(true)
            assertThat(isLargeScreen).isTrue()
        }

    @Test
    @DisableSceneContainer
    fun hydrateLargeScreen_nonSceneContainer() =
        kosmos.runTest {
            val isLargeScreen by collectLastValue(shadeRepository.isLargeScreen)
            underTest.start()

            displayStateRepository.setIsLargeScreen(false)
            assertThat(isLargeScreen).isFalse()

            displayStateRepository.setIsLargeScreen(true)
            assertThat(isLargeScreen).isTrue()
        }
        }


    private fun Kosmos.changeScene(
    private fun Kosmos.changeScene(
+1 −6
Original line number Original line Diff line number Diff line
@@ -104,12 +104,7 @@ constructor(
                    )
                    )
                }
                }


                val callback =
                val callback = FoldProvider.FoldCallback(sendFoldStateUpdate)
                    object : FoldProvider.FoldCallback {
                        override fun onFoldUpdated(isFolded: Boolean) {
                            sendFoldStateUpdate(isFolded)
                        }
                    }


                sendFoldStateUpdate(false)
                sendFoldStateUpdate(false)
                screenSizeFoldProvider.registerCallback(callback, mainExecutor)
                screenSizeFoldProvider.registerCallback(callback, mainExecutor)
Loading