diff options
3 files changed, 95 insertions, 32 deletions
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt index a47db2ec728b..668f568d7f46 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt @@ -16,15 +16,11 @@ package com.android.systemui.shade.domain.interactor -import android.platform.test.annotations.DisableFlags -import android.platform.test.annotations.EnableFlags import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.coroutines.collectLastValue import com.android.systemui.kosmos.testScope -import com.android.systemui.shade.data.repository.shadeRepository -import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat @@ -48,82 +44,79 @@ class ShadeModeInteractorImplTest : SysuiTestCase() { } @Test - @DisableFlags(DualShade.FLAG_NAME) fun legacyShadeMode_narrowScreen_singleShade() = testScope.runTest { val shadeMode by collectLastValue(underTest.shadeMode) - kosmos.shadeRepository.setShadeLayoutWide(false) + kosmos.enableSingleShade() assertThat(shadeMode).isEqualTo(ShadeMode.Single) } @Test - @DisableFlags(DualShade.FLAG_NAME) fun legacyShadeMode_wideScreen_splitShade() = testScope.runTest { val shadeMode by collectLastValue(underTest.shadeMode) - kosmos.shadeRepository.setShadeLayoutWide(true) + kosmos.enableSplitShade() assertThat(shadeMode).isEqualTo(ShadeMode.Split) } @Test - @EnableFlags(DualShade.FLAG_NAME) fun shadeMode_wideScreen_isDual() = testScope.runTest { val shadeMode by collectLastValue(underTest.shadeMode) - kosmos.shadeRepository.setShadeLayoutWide(true) + kosmos.enableDualShade(wideLayout = true) assertThat(shadeMode).isEqualTo(ShadeMode.Dual) } @Test - @EnableFlags(DualShade.FLAG_NAME) fun shadeMode_narrowScreen_isDual() = testScope.runTest { val shadeMode by collectLastValue(underTest.shadeMode) - kosmos.shadeRepository.setShadeLayoutWide(false) + kosmos.enableDualShade(wideLayout = false) assertThat(shadeMode).isEqualTo(ShadeMode.Dual) } @Test - @EnableFlags(DualShade.FLAG_NAME) - fun isDualShade_flagEnabled_true() = + fun isDualShade_settingEnabled_returnsTrue() = testScope.runTest { - // Initiate collection. + // TODO(b/391578667): Add a test case for user switching once the bug is fixed. val shadeMode by collectLastValue(underTest.shadeMode) + kosmos.enableDualShade() + assertThat(shadeMode).isEqualTo(ShadeMode.Dual) assertThat(underTest.isDualShade).isTrue() } @Test - @DisableFlags(DualShade.FLAG_NAME) - fun isDualShade_flagDisabled_false() = + fun isDualShade_settingDisabled_returnsFalse() = testScope.runTest { - // Initiate collection. val shadeMode by collectLastValue(underTest.shadeMode) + kosmos.disableDualShade() + assertThat(shadeMode).isNotEqualTo(ShadeMode.Dual) assertThat(underTest.isDualShade).isFalse() } @Test fun getTopEdgeSplitFraction_narrowScreen_splitInHalf() = testScope.runTest { - // Ensure isShadeLayoutWide is collected. - val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide) - kosmos.shadeRepository.setShadeLayoutWide(false) + val shadeMode by collectLastValue(underTest.shadeMode) + kosmos.enableDualShade(wideLayout = false) + assertThat(shadeMode).isEqualTo(ShadeMode.Dual) assertThat(underTest.getTopEdgeSplitFraction()).isEqualTo(0.5f) } @Test fun getTopEdgeSplitFraction_wideScreen_splitInHalf() = testScope.runTest { - // Ensure isShadeLayoutWide is collected. - val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide) - kosmos.shadeRepository.setShadeLayoutWide(true) + val shadeMode by collectLastValue(underTest.shadeMode) + kosmos.enableDualShade(wideLayout = true) + assertThat(shadeMode).isEqualTo(ShadeMode.Dual) assertThat(underTest.getTopEdgeSplitFraction()).isEqualTo(0.5f) } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt index edf503d03f3e..59d812403777 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt @@ -16,17 +16,20 @@ package com.android.systemui.shade.domain.interactor +import android.provider.Settings import androidx.annotation.FloatRange import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.shade.shared.flag.DualShade import com.android.systemui.shade.shared.model.ShadeMode +import com.android.systemui.shared.settings.data.repository.SecureSettingsRepository import javax.inject.Inject import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.MutableStateFlow import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.StateFlow -import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.stateIn /** @@ -76,29 +79,53 @@ interface ShadeModeInteractor { class ShadeModeInteractorImpl @Inject -constructor(@Application applicationScope: CoroutineScope, repository: ShadeRepository) : - ShadeModeInteractor { +constructor( + @Application applicationScope: CoroutineScope, + repository: ShadeRepository, + secureSettingsRepository: SecureSettingsRepository, +) : ShadeModeInteractor { + + private val isDualShadeEnabled: Flow<Boolean> = + secureSettingsRepository.boolSetting( + Settings.Secure.DUAL_SHADE, + defaultValue = DUAL_SHADE_ENABLED_DEFAULT, + ) override val isShadeLayoutWide: StateFlow<Boolean> = repository.isShadeLayoutWide override val shadeMode: StateFlow<ShadeMode> = - isShadeLayoutWide - .map(this::determineShadeMode) + combine(isDualShadeEnabled, repository.isShadeLayoutWide, ::determineShadeMode) .stateIn( applicationScope, SharingStarted.Eagerly, - initialValue = determineShadeMode(isShadeLayoutWide.value), + initialValue = + determineShadeMode( + isDualShadeEnabled = DUAL_SHADE_ENABLED_DEFAULT, + isShadeLayoutWide = repository.isShadeLayoutWide.value, + ), ) @FloatRange(from = 0.0, to = 1.0) override fun getTopEdgeSplitFraction(): Float = 0.5f - private fun determineShadeMode(isShadeLayoutWide: Boolean): ShadeMode { + private fun determineShadeMode( + isDualShadeEnabled: Boolean, + isShadeLayoutWide: Boolean, + ): ShadeMode { return when { - DualShade.isEnabled -> ShadeMode.Dual + isDualShadeEnabled || + // TODO(b/388793191): This ensures that the dual_shade aconfig flag can also enable + // Dual Shade, to avoid breaking unit tests. Remove this once all references to the + // flag are removed. + DualShade.isEnabled -> ShadeMode.Dual isShadeLayoutWide -> ShadeMode.Split else -> ShadeMode.Single } } + + companion object { + /* Whether the Dual Shade setting is enabled by default. */ + private const val DUAL_SHADE_ENABLED_DEFAULT = false + } } class ShadeModeInteractorEmptyImpl @Inject constructor() : ShadeModeInteractor { diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt index 7892e962d63d..1b50094ec0b7 100644 --- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorKosmos.kt @@ -16,14 +16,57 @@ package com.android.systemui.shade.domain.interactor +import android.provider.Settings import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.Kosmos.Fixture import com.android.systemui.kosmos.applicationCoroutineScope +import com.android.systemui.kosmos.testScope +import com.android.systemui.shade.data.repository.fakeShadeRepository import com.android.systemui.shade.data.repository.shadeRepository +import com.android.systemui.shared.settings.data.repository.secureSettingsRepository +import kotlinx.coroutines.launch val Kosmos.shadeModeInteractor by Fixture { ShadeModeInteractorImpl( applicationScope = applicationCoroutineScope, repository = shadeRepository, + secureSettingsRepository = secureSettingsRepository, ) } + +// TODO(b/391578667): Make this user-aware once supported by FakeSecureSettingsRepository. +/** + * Enables the Dual Shade setting, and (optionally) sets the shade layout to be wide (`true`) + * or narrow (`false`). + * + * In a wide layout, notifications and quick settings shades each take up only half the screen + * width. In a narrow layout, they each take up the entire screen width. + */ +fun Kosmos.enableDualShade(wideLayout: Boolean? = null) { + testScope.launch { + secureSettingsRepository.setInt(Settings.Secure.DUAL_SHADE, 1) + + if (wideLayout != null) { + fakeShadeRepository.setShadeLayoutWide(wideLayout) + } + } +} + +// TODO(b/391578667): Make this user-aware once supported by FakeSecureSettingsRepository. +fun Kosmos.disableDualShade() { + testScope.launch { secureSettingsRepository.setInt(Settings.Secure.DUAL_SHADE, 0) } +} + +fun Kosmos.enableSingleShade() { + testScope.launch { + disableDualShade() + fakeShadeRepository.setShadeLayoutWide(false) + } +} + +fun Kosmos.enableSplitShade() { + testScope.launch { + disableDualShade() + fakeShadeRepository.setShadeLayoutWide(true) + } +} |