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 Diff line number Diff line
@@ -167,7 +167,7 @@ class LockscreenUserActionsViewModelTest : SysuiTestCase() {

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

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

+22 −2
Original line number 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.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith

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

    private val kosmos = testKosmos().useUnconfinedTestDispatcher()
    private val secondaryDisplayStateRepository = FakeDisplayStateRepository()
    private val secondaryDisplayStateInteractor =
@@ -98,6 +97,27 @@ class ShadeDisplayStateInteractorTest : SysuiTestCase() {
            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 {
        const val DEFAULT_DISPLAY = Display.DEFAULT_DISPLAY
        const val SECONDARY_DISPLAY = DEFAULT_DISPLAY + 1
+10 −1
Original line number Diff line number Diff line
@@ -45,7 +45,16 @@ class ShadeModeInteractorImplTest : SysuiTestCase() {
    fun legacyShadeMode_narrowScreen_singleShade() =
        kosmos.runTest {
            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)
        }
+60 −3
Original line number 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.testing.TestableLooper.RunWithLooper
import android.view.Display
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.compose.animation.scene.SceneKey
import com.android.systemui.SysuiTestCase
import com.android.systemui.authentication.data.repository.fakeAuthenticationRepository
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.parameterizeSceneContainerFlag
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.shade.ShadeExpansionChangeEvent
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.enableSingleShade
import com.android.systemui.shade.domain.interactor.enableSplitShade
@@ -86,11 +94,24 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() {

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

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

            fakeShadeDisplaysRepository.setDisplayId(Display.DEFAULT_DISPLAY)
        }
    }

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

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

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

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

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

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

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

            verify(notificationStackScrollLayoutController).setIsFullWidth(false)
            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(
+1 −6
Original line number Diff line number Diff line
@@ -104,12 +104,7 @@ constructor(
                    )
                }

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

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