Loading packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt +111 −0 Original line number Diff line number Diff line Loading @@ -17,19 +17,24 @@ package com.android.systemui.shade.domain.interactor import android.content.testableContext import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.display.data.repository.displayStateRepository import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.res.R import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.runBlocking import org.junit.Test import org.junit.runner.RunWith Loading Loading @@ -148,4 +153,110 @@ class ShadeModeInteractorImplTest : SysuiTestCase() { assertThat(shadeMode).isNotEqualTo(ShadeMode.Dual) assertThat(underTest.isDualShade).isFalse() } @Test fun isFullWidthShade_largeScreenPortrait() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Large screen portrait setupScreenConfig(wideScreen = true, legacyUseSplitShade = false) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() } @Test fun isFullWidthShade_largeScreenLandscape() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Large screen landscape setupScreenConfig(wideScreen = true, legacyUseSplitShade = true) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() } @Test fun isFullWidthShade_compactScreenPortrait() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Compact screen portrait setupScreenConfig(wideScreen = false, legacyUseSplitShade = false) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() } @Test fun isFullWidthShade_compactScreenLandscape() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Compact screen landscape setupScreenConfig(wideScreen = true, legacyUseSplitShade = false) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() } private fun Kosmos.setupScreenConfig(wideScreen: Boolean, legacyUseSplitShade: Boolean) { testableContext.orCreateTestableResources.apply { addOverride(R.bool.config_use_split_notification_shade, legacyUseSplitShade) addOverride(R.bool.config_use_large_screen_shade_header, legacyUseSplitShade) } fakeConfigurationRepository.onAnyConfigurationChange() shadeRepository.legacyUseSplitShade.value = legacyUseSplitShade shadeRepository.isWideScreen.value = wideScreen } private fun Kosmos.setupShadeConfig( dualShadeSettingEnabled: Boolean, disableSplitShade: Boolean, ) = runBlocking { fakeSecureSettingsRepository.setBoolean(Settings.Secure.DUAL_SHADE, dualShadeSettingEnabled) testableContext.orCreateTestableResources.addOverride( R.bool.config_disableSplitShade, disableSplitShade, ) fakeConfigurationRepository.onAnyConfigurationChange() } } packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -277,7 +277,7 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() { verify(notificationStackScrollLayoutController).setIsFullWidth(false) assertThat(scrimController.clipQsScrim).isFalse() assertThat(isWideScreen).isTrue() assertThat(legacyUseSplitShade).isFalse() assertThat(legacyUseSplitShade).isTrue() } private fun Kosmos.changeScene( Loading packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt +12 −10 Original line number Diff line number Diff line Loading @@ -95,17 +95,19 @@ constructor( flowOf(false) } private val isSplitShadeEnabled: Boolean = !SceneContainerFlag.isEnabled || !context.resources.getBoolean(R.bool.config_disableSplitShade) private val isSplitShadeDisabled: Boolean = SceneContainerFlag.isEnabled && context.resources.getBoolean(R.bool.config_disableSplitShade) override val isFullWidthShade: StateFlow<Boolean> = isDualShadeSettingEnabled .flatMapLatest { isDualShadeSettingEnabled -> if (isDualShadeSettingEnabled) { if (isDualShadeSettingEnabled || isSplitShadeDisabled) { // Dual Shade should be shown; derive the layout from the screen width. Log.d(TAG, "Shade layout is derived from screen width") repository.isWideScreen.map { !it } } else { // Single/Split shade should be shown; derive the layout from the config. Log.d(TAG, "Shade layout is derived from the legacy config") repository.legacyUseSplitShade.map { !it } } Loading Loading @@ -146,15 +148,15 @@ constructor( "the setting is 'combined', and the device is a phone " + "(in any orientation) or large screen in portrait" isSplitShadeEnabled -> ShadeMode.Split to "the setting is 'combined', split shade is enabled, " + "and the device has a large screen in landscape orientation" else -> isSplitShadeDisabled -> ShadeMode.Dual to "the setting is 'combined', " + "but split shade disabled and the device has a large screen" else -> ShadeMode.Split to "the setting is 'combined', split shade is enabled, " + "and the device has a large screen in landscape orientation" } Log.d(TAG, "Shade mode is $newMode because $reason") return newMode Loading packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt +8 −21 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.shade.domain.interactor.ShadeDisplayStateInteractor import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.domain.interactor.ShadeModeInteractor import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.transition.ScrimShadeTransitionController import com.android.systemui.statusbar.NotificationShadeDepthController import com.android.systemui.statusbar.PulseExpansionHandler Loading @@ -46,8 +45,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart Loading Loading @@ -122,25 +119,15 @@ constructor( } applicationScope.launch { val shadeModeInteractor = shadeModeInteractorProvider.get() shadeModeInteractor.shadeMode .flatMapLatest { shadeMode -> if (shadeMode is ShadeMode.Dual) { flowOf(false) } else { configurationRepository.onAnyConfigurationChange // Force initial collection. .onStart { emit(Unit) } .map { // The configuration for 'shouldUseSplitNotificationShade' dictates // the width of the shade in single/split shade modes. splitShadeStateController.shouldUseSplitNotificationShade( context.resources ) // The configuration for 'shouldUseSplitNotificationShade' dictates the width of // the shade in single/split shade modes. splitShadeStateController.shouldUseSplitNotificationShade(context.resources) } .distinctUntilChanged() } } .collect { shadeRepository.legacyUseSplitShade.value = it } } } Loading Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractorImplTest.kt +111 −0 Original line number Diff line number Diff line Loading @@ -17,19 +17,24 @@ package com.android.systemui.shade.domain.interactor import android.content.testableContext import android.provider.Settings import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.common.ui.data.repository.fakeConfigurationRepository import com.android.systemui.display.data.repository.displayStateRepository import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.kosmos.Kosmos import com.android.systemui.kosmos.collectLastValue import com.android.systemui.kosmos.runTest import com.android.systemui.kosmos.useUnconfinedTestDispatcher import com.android.systemui.res.R import com.android.systemui.shade.data.repository.shadeRepository import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shared.settings.data.repository.fakeSecureSettingsRepository import com.android.systemui.testKosmos import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.runBlocking import org.junit.Test import org.junit.runner.RunWith Loading Loading @@ -148,4 +153,110 @@ class ShadeModeInteractorImplTest : SysuiTestCase() { assertThat(shadeMode).isNotEqualTo(ShadeMode.Dual) assertThat(underTest.isDualShade).isFalse() } @Test fun isFullWidthShade_largeScreenPortrait() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Large screen portrait setupScreenConfig(wideScreen = true, legacyUseSplitShade = false) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() } @Test fun isFullWidthShade_largeScreenLandscape() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Large screen landscape setupScreenConfig(wideScreen = true, legacyUseSplitShade = true) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() } @Test fun isFullWidthShade_compactScreenPortrait() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Compact screen portrait setupScreenConfig(wideScreen = false, legacyUseSplitShade = false) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() } @Test fun isFullWidthShade_compactScreenLandscape() = kosmos.runTest { val isFullWidthShade by collectLastValue(underTest.isFullWidthShade) // Compact screen landscape setupScreenConfig(wideScreen = true, legacyUseSplitShade = false) setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = false) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = true, disableSplitShade = true) assertThat(isFullWidthShade).isFalse() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = true) assertThat(isFullWidthShade).isTrue() setupShadeConfig(dualShadeSettingEnabled = false, disableSplitShade = false) assertThat(isFullWidthShade).isTrue() } private fun Kosmos.setupScreenConfig(wideScreen: Boolean, legacyUseSplitShade: Boolean) { testableContext.orCreateTestableResources.apply { addOverride(R.bool.config_use_split_notification_shade, legacyUseSplitShade) addOverride(R.bool.config_use_large_screen_shade_header, legacyUseSplitShade) } fakeConfigurationRepository.onAnyConfigurationChange() shadeRepository.legacyUseSplitShade.value = legacyUseSplitShade shadeRepository.isWideScreen.value = wideScreen } private fun Kosmos.setupShadeConfig( dualShadeSettingEnabled: Boolean, disableSplitShade: Boolean, ) = runBlocking { fakeSecureSettingsRepository.setBoolean(Settings.Secure.DUAL_SHADE, dualShadeSettingEnabled) testableContext.orCreateTestableResources.addOverride( R.bool.config_disableSplitShade, disableSplitShade, ) fakeConfigurationRepository.onAnyConfigurationChange() } }
packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/startable/ShadeStartableTest.kt +1 −1 Original line number Diff line number Diff line Loading @@ -277,7 +277,7 @@ class ShadeStartableTest(flags: FlagsParameterization) : SysuiTestCase() { verify(notificationStackScrollLayoutController).setIsFullWidth(false) assertThat(scrimController.clipQsScrim).isFalse() assertThat(isWideScreen).isTrue() assertThat(legacyUseSplitShade).isFalse() assertThat(legacyUseSplitShade).isTrue() } private fun Kosmos.changeScene( Loading
packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeModeInteractor.kt +12 −10 Original line number Diff line number Diff line Loading @@ -95,17 +95,19 @@ constructor( flowOf(false) } private val isSplitShadeEnabled: Boolean = !SceneContainerFlag.isEnabled || !context.resources.getBoolean(R.bool.config_disableSplitShade) private val isSplitShadeDisabled: Boolean = SceneContainerFlag.isEnabled && context.resources.getBoolean(R.bool.config_disableSplitShade) override val isFullWidthShade: StateFlow<Boolean> = isDualShadeSettingEnabled .flatMapLatest { isDualShadeSettingEnabled -> if (isDualShadeSettingEnabled) { if (isDualShadeSettingEnabled || isSplitShadeDisabled) { // Dual Shade should be shown; derive the layout from the screen width. Log.d(TAG, "Shade layout is derived from screen width") repository.isWideScreen.map { !it } } else { // Single/Split shade should be shown; derive the layout from the config. Log.d(TAG, "Shade layout is derived from the legacy config") repository.legacyUseSplitShade.map { !it } } Loading Loading @@ -146,15 +148,15 @@ constructor( "the setting is 'combined', and the device is a phone " + "(in any orientation) or large screen in portrait" isSplitShadeEnabled -> ShadeMode.Split to "the setting is 'combined', split shade is enabled, " + "and the device has a large screen in landscape orientation" else -> isSplitShadeDisabled -> ShadeMode.Dual to "the setting is 'combined', " + "but split shade disabled and the device has a large screen" else -> ShadeMode.Split to "the setting is 'combined', split shade is enabled, " + "and the device has a large screen in landscape orientation" } Log.d(TAG, "Shade mode is $newMode because $reason") return newMode Loading
packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt +8 −21 Original line number Diff line number Diff line Loading @@ -33,7 +33,6 @@ import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.shade.domain.interactor.ShadeDisplayStateInteractor import com.android.systemui.shade.domain.interactor.ShadeInteractor import com.android.systemui.shade.domain.interactor.ShadeModeInteractor import com.android.systemui.shade.shared.model.ShadeMode import com.android.systemui.shade.transition.ScrimShadeTransitionController import com.android.systemui.statusbar.NotificationShadeDepthController import com.android.systemui.statusbar.PulseExpansionHandler Loading @@ -46,8 +45,6 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.combine import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onStart Loading Loading @@ -122,25 +119,15 @@ constructor( } applicationScope.launch { val shadeModeInteractor = shadeModeInteractorProvider.get() shadeModeInteractor.shadeMode .flatMapLatest { shadeMode -> if (shadeMode is ShadeMode.Dual) { flowOf(false) } else { configurationRepository.onAnyConfigurationChange // Force initial collection. .onStart { emit(Unit) } .map { // The configuration for 'shouldUseSplitNotificationShade' dictates // the width of the shade in single/split shade modes. splitShadeStateController.shouldUseSplitNotificationShade( context.resources ) // The configuration for 'shouldUseSplitNotificationShade' dictates the width of // the shade in single/split shade modes. splitShadeStateController.shouldUseSplitNotificationShade(context.resources) } .distinctUntilChanged() } } .collect { shadeRepository.legacyUseSplitShade.value = it } } } Loading