diff options
10 files changed, 71 insertions, 54 deletions
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt index 556bbbe9f997..c37d626ca8c5 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt @@ -18,9 +18,11 @@ package com.android.systemui.keyguard.ui.composable.section import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import com.android.compose.animation.scene.SceneScope -import com.android.systemui.keyguard.ui.viewmodel.MediaCarouselViewModel +import com.android.systemui.keyguard.ui.viewmodel.KeyguardMediaViewModel import com.android.systemui.media.controls.ui.composable.MediaCarousel import com.android.systemui.media.controls.ui.controller.MediaCarouselController import com.android.systemui.media.controls.ui.view.MediaHost @@ -33,20 +35,15 @@ class MediaCarouselSection constructor( private val mediaCarouselController: MediaCarouselController, @param:Named(MediaModule.KEYGUARD) private val mediaHost: MediaHost, - private val mediaCarouselViewModel: MediaCarouselViewModel, + private val keyguardMediaViewModel: KeyguardMediaViewModel, ) { - private fun isVisible(): Boolean { - if (mediaCarouselController.mediaFrame == null) { - return false - } - return mediaCarouselViewModel.isMediaVisible - } - @Composable fun SceneScope.KeyguardMediaCarousel() { + val isMediaVisible by keyguardMediaViewModel.isMediaVisible.collectAsState() + MediaCarousel( - isVisible = ::isVisible, + isVisible = isMediaVisible, mediaHost = mediaHost, modifier = Modifier.fillMaxWidth(), carouselController = mediaCarouselController, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt index 241c171f7862..581f3a5cacff 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/media/controls/ui/composable/MediaCarousel.kt @@ -42,12 +42,12 @@ private object MediaCarousel { @Composable fun SceneScope.MediaCarousel( - isVisible: () -> Boolean, + isVisible: Boolean, mediaHost: MediaHost, modifier: Modifier = Modifier, carouselController: MediaCarouselController, ) { - if (!isVisible()) { + if (!isVisible) { return } diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt index ec9136d50e4c..abce7428a455 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/qs/ui/composable/QuickSettingsScene.kt @@ -332,8 +332,10 @@ private fun SceneScope.QuickSettingsScene( modifier = Modifier.sysuiResTag("expanded_qs_scroll_view") ) + val isMediaVisible by viewModel.isMediaVisible.collectAsState() + MediaCarousel( - isVisible = viewModel::isMediaVisible, + isVisible = isMediaVisible, mediaHost = mediaHost, modifier = Modifier.fillMaxWidth(), carouselController = mediaCarouselController, diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt index 4ad8b9f47f70..bbf8413fc51b 100644 --- a/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt +++ b/packages/SystemUI/compose/features/src/com/android/systemui/shade/ui/composable/ShadeScene.kt @@ -214,6 +214,7 @@ private fun SceneScope.SingleShade( canOverflow = false ) val isClickable by viewModel.isClickable.collectAsState() + val isMediaVisible by viewModel.isMediaVisible.collectAsState() val shouldPunchHoleBehindScrim = layoutState.isTransitioningBetween(Scenes.Gone, Scenes.Shade) || @@ -265,7 +266,7 @@ private fun SceneScope.SingleShade( } MediaCarousel( - isVisible = viewModel::isMediaVisible, + isVisible = isMediaVisible, mediaHost = mediaHost, modifier = Modifier.fillMaxWidth(), carouselController = mediaCarouselController, @@ -366,6 +367,8 @@ private fun SceneScope.SplitShade( viewModel.notifications.setAlphaForBrightnessMirror(contentAlpha) DisposableEffect(Unit) { onDispose { viewModel.notifications.setAlphaForBrightnessMirror(1f) } } + val isMediaVisible by viewModel.isMediaVisible.collectAsState() + val brightnessMirrorShowingModifier = Modifier.graphicsLayer { alpha = contentAlpha } Box( @@ -441,7 +444,7 @@ private fun SceneScope.SplitShade( } MediaCarousel( - isVisible = viewModel::isMediaVisible, + isVisible = isMediaVisible, mediaHost = mediaHost, modifier = Modifier.fillMaxWidth(), carouselController = mediaCarouselController, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt index 179ba42cc772..0b55befce932 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModelTest.kt @@ -35,7 +35,10 @@ import com.android.systemui.flags.fakeFeatureFlagsClassic import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope +import com.android.systemui.media.controls.data.repository.mediaFilterRepository import com.android.systemui.media.controls.domain.pipeline.MediaDataManager +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor +import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter @@ -100,7 +103,7 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { footerActionsViewModelFactory = footerActionsViewModelFactory, footerActionsController = footerActionsController, sceneBackInteractor = sceneBackInteractor, - mediaDataManager = mediaDataManager, + mediaCarouselInteractor = kosmos.mediaCarouselInteractor, ) } @@ -236,20 +239,34 @@ class QuickSettingsSceneViewModelTest : SysuiTestCase() { } @Test - fun hasMedia_mediaVisible() { + fun addAndRemoveMedia_mediaVisibilityIsUpdated() = testScope.runTest { - whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(true) + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = true) - assertThat(underTest.isMediaVisible()).isTrue() + assertThat(isMediaVisible).isFalse() + + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() + + kosmos.mediaFilterRepository.removeSelectedUserMediaEntry(userMedia.instanceId) + + assertThat(isMediaVisible).isFalse() } - } @Test - fun doesNotHaveMedia_mediaNotVisible() { + fun addInactiveMedia_mediaVisibilityIsUpdated() = testScope.runTest { - whenever(mediaDataManager.hasAnyMediaOrRecommendation()).thenReturn(false) + kosmos.fakeFeatureFlagsClassic.set(Flags.MEDIA_RETAIN_RECOMMENDATIONS, false) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = false) + + assertThat(isMediaVisible).isFalse() - assertThat(underTest.isMediaVisible()).isFalse() + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() } - } } diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt index 4cb8bf84967b..9e7e766cb820 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/SceneFrameworkIntegrationTest.kt @@ -52,6 +52,7 @@ import com.android.systemui.keyguard.ui.viewmodel.KeyguardLongPressViewModel import com.android.systemui.keyguard.ui.viewmodel.LockscreenSceneViewModel import com.android.systemui.kosmos.testScope import com.android.systemui.media.controls.domain.pipeline.MediaDataManager +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest import com.android.systemui.power.domain.interactor.powerInteractor @@ -209,7 +210,7 @@ class SceneFrameworkIntegrationTest : SysuiTestCase() { qsSceneAdapter = qsFlexiglassAdapter, notifications = kosmos.notificationsPlaceholderViewModel, brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel, - mediaDataManager = mediaDataManager, + mediaCarouselInteractor = kosmos.mediaCarouselInteractor, shadeInteractor = kosmos.shadeInteractor, footerActionsController = kosmos.footerActionsController, footerActionsViewModelFactory = kosmos.footerActionsViewModelFactory, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt index 5312ad809a72..4b7e5e725e6e 100644 --- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt @@ -32,7 +32,10 @@ import com.android.systemui.flags.EnableSceneContainer import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus import com.android.systemui.kosmos.testScope +import com.android.systemui.media.controls.data.repository.mediaFilterRepository import com.android.systemui.media.controls.domain.pipeline.MediaDataManager +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor +import com.android.systemui.media.controls.shared.model.MediaData import com.android.systemui.qs.footerActionsController import com.android.systemui.qs.footerActionsViewModelFactory import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter @@ -49,7 +52,6 @@ import com.android.systemui.testKosmos import com.android.systemui.unfold.domain.interactor.unfoldTransitionInteractor import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider import com.android.systemui.util.mockito.mock -import com.android.systemui.util.mockito.whenever import com.google.common.truth.Truth.assertThat import java.util.Locale import kotlinx.coroutines.ExperimentalCoroutinesApi @@ -93,7 +95,7 @@ class ShadeSceneViewModelTest : SysuiTestCase() { qsSceneAdapter = qsSceneAdapter, notifications = kosmos.notificationsPlaceholderViewModel, brightnessMirrorViewModel = kosmos.brightnessMirrorViewModel, - mediaDataManager = mediaDataManager, + mediaCarouselInteractor = kosmos.mediaCarouselInteractor, shadeInteractor = kosmos.shadeInteractor, footerActionsViewModelFactory = kosmos.footerActionsViewModelFactory, footerActionsController = kosmos.footerActionsController, @@ -200,19 +202,20 @@ class ShadeSceneViewModelTest : SysuiTestCase() { } @Test - fun hasActiveMedia_mediaVisible() = + fun addAndRemoveMedia_mediaVisibilityisUpdated() = testScope.runTest { - whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(true) + val isMediaVisible by collectLastValue(underTest.isMediaVisible) + val userMedia = MediaData(active = true) - assertThat(underTest.isMediaVisible()).isTrue() - } + assertThat(isMediaVisible).isFalse() - @Test - fun doesNotHaveActiveMedia_mediaNotVisible() = - testScope.runTest { - whenever(mediaDataManager.hasActiveMediaOrRecommendation()).thenReturn(false) + kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + + assertThat(isMediaVisible).isTrue() + + kosmos.mediaFilterRepository.removeSelectedUserMediaEntry(userMedia.instanceId) - assertThat(underTest.isMediaVisible()).isFalse() + assertThat(isMediaVisible).isFalse() } @Test diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/MediaCarouselViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt index bf225633fa86..e68e465ed55a 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/MediaCarouselViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt @@ -16,10 +16,10 @@ package com.android.systemui.keyguard.ui.viewmodel -import com.android.systemui.media.controls.domain.pipeline.MediaDataManager +import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import javax.inject.Inject +import kotlinx.coroutines.flow.StateFlow -class MediaCarouselViewModel @Inject constructor(private val mediaDataManager: MediaDataManager) { - val isMediaVisible: Boolean - get() = mediaDataManager.hasActiveMediaOrRecommendation() +class KeyguardMediaViewModel @Inject constructor(mediaCarouselInteractor: MediaCarouselInteractor) { + val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasActiveMediaOrRecommendation } diff --git a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt index 17698f9d8647..6cf2e52ff3d9 100644 --- a/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/qs/ui/viewmodel/QuickSettingsSceneViewModel.kt @@ -29,7 +29,7 @@ import com.android.compose.animation.scene.UserActionResult import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor -import com.android.systemui.media.controls.domain.pipeline.MediaDataManager +import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.QSSceneAdapter @@ -63,7 +63,7 @@ constructor( private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, private val footerActionsController: FooterActionsController, sceneBackInteractor: SceneBackInteractor, - val mediaDataManager: MediaDataManager, + val mediaCarouselInteractor: MediaCarouselInteractor, ) { private val backScene: StateFlow<SceneKey> = sceneBackInteractor.backScene @@ -101,6 +101,8 @@ constructor( ), ) + val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasAnyMediaOrRecommendation + private fun destinationScenes( isUnlocked: Boolean, canSwipeToDismiss: Boolean?, @@ -143,9 +145,4 @@ constructor( } return footerActionsViewModelFactory.create(lifecycleOwner) } - - fun isMediaVisible(): Boolean { - // TODO(b/328207006): use new pipeline to handle updates while visible - return mediaDataManager.hasAnyMediaOrRecommendation() - } } diff --git a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt index ac76becd1797..5e1f9c91e68e 100644 --- a/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModel.kt @@ -27,7 +27,7 @@ import com.android.compose.animation.scene.UserActionResult import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor -import com.android.systemui.media.controls.domain.pipeline.MediaDataManager +import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor import com.android.systemui.qs.FooterActionsController import com.android.systemui.qs.footer.ui.viewmodel.FooterActionsViewModel import com.android.systemui.qs.ui.adapter.QSSceneAdapter @@ -60,7 +60,7 @@ constructor( val shadeHeaderViewModel: ShadeHeaderViewModel, val notifications: NotificationsPlaceholderViewModel, val brightnessMirrorViewModel: BrightnessMirrorViewModel, - val mediaDataManager: MediaDataManager, + val mediaCarouselInteractor: MediaCarouselInteractor, shadeInteractor: ShadeInteractor, private val footerActionsViewModelFactory: FooterActionsViewModel.Factory, private val footerActionsController: FooterActionsController, @@ -108,6 +108,8 @@ constructor( val shadeMode: StateFlow<ShadeMode> = shadeInteractor.shadeMode + val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasActiveMediaOrRecommendation + /** * Amount of X-axis translation to apply to various elements as the unfolded foldable is folded * slightly, in pixels. @@ -125,11 +127,6 @@ constructor( sceneInteractor.changeScene(Scenes.Lockscreen, "Shade empty content clicked") } - fun isMediaVisible(): Boolean { - // TODO(b/296122467): handle updates to carousel visibility while scene is still visible - return mediaDataManager.hasActiveMediaOrRecommendation() - } - private val footerActionsControllerInitialized = AtomicBoolean(false) fun getFooterActionsViewModel(lifecycleOwner: LifecycleOwner): FooterActionsViewModel { |