diff options
| author | 2025-01-23 05:26:49 -0800 | |
|---|---|---|
| committer | 2025-01-23 05:26:49 -0800 | |
| commit | 8ee167ecf0d85d5fa015ed3f5ec4fa5dd5fd1195 (patch) | |
| tree | 9da9605501166b397c98ecf96d48f50f676902b0 | |
| parent | 849d1b8a10e649e3e3cb88717d86ffea7a934b01 (diff) | |
| parent | 9e0611aa19861a2fe5be7704e1ee6d70299d8562 (diff) | |
Merge "[Flexiglass] hide UMO on AOD." into main
4 files changed, 165 insertions, 9 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 0ff567bf90ad..d8b3f742b447 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 @@ -19,12 +19,11 @@ package com.android.systemui.keyguard.ui.composable.section import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.runtime.Composable -import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.dimensionResource -import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.android.compose.animation.scene.ContentScope import com.android.systemui.keyguard.ui.viewmodel.KeyguardMediaViewModel +import com.android.systemui.lifecycle.rememberViewModel 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 @@ -38,7 +37,7 @@ class MediaCarouselSection constructor( private val mediaCarouselController: MediaCarouselController, @param:Named(MediaModule.KEYGUARD) private val mediaHost: MediaHost, - private val keyguardMediaViewModel: KeyguardMediaViewModel, + private val keyguardMediaViewModelFactory: KeyguardMediaViewModel.Factory, ) { @Composable @@ -46,7 +45,10 @@ constructor( isShadeLayoutWide: Boolean, modifier: Modifier = Modifier, ) { - val isMediaVisible by keyguardMediaViewModel.isMediaVisible.collectAsStateWithLifecycle() + val viewModel = + rememberViewModel(traceName = "KeyguardMediaCarousel") { + keyguardMediaViewModelFactory.create() + } val horizontalPadding = if (isShadeLayoutWide) { dimensionResource(id = R.dimen.notification_side_paddings) @@ -55,7 +57,7 @@ constructor( dimensionResource(id = R.dimen.notification_panel_margin_horizontal) } MediaCarousel( - isVisible = isMediaVisible, + isVisible = viewModel.isMediaVisible, mediaHost = mediaHost, modifier = modifier.fillMaxWidth().padding(horizontal = horizontalPadding), carouselController = mediaCarouselController, diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelTest.kt new file mode 100644 index 000000000000..38829da69c28 --- /dev/null +++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelTest.kt @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import androidx.test.ext.junit.runners.AndroidJUnit4 +import androidx.test.filters.SmallTest +import com.android.systemui.SysuiTestCase +import com.android.systemui.keyguard.data.repository.keyguardRepository +import com.android.systemui.kosmos.runTest +import com.android.systemui.kosmos.testScope +import com.android.systemui.kosmos.useUnconfinedTestDispatcher +import com.android.systemui.lifecycle.activateIn +import com.android.systemui.media.controls.data.repository.mediaFilterRepository +import com.android.systemui.media.controls.shared.model.MediaData +import com.android.systemui.testKosmos +import com.google.common.truth.Truth.assertThat +import org.junit.Before +import org.junit.Test +import org.junit.runner.RunWith + +@SmallTest +@RunWith(AndroidJUnit4::class) +class KeyguardMediaViewModelTest : SysuiTestCase() { + private val kosmos = testKosmos().useUnconfinedTestDispatcher() + + private val underTest = kosmos.keyguardMediaViewModelFactory.create() + + @Before + fun setUp() { + underTest.activateIn(kosmos.testScope) + } + + @Test + fun onDozing_noActiveMedia_mediaIsHidden() = + kosmos.runTest { + keyguardRepository.setIsDozing(true) + + assertThat(underTest.isMediaVisible).isFalse() + } + + @Test + fun onDozing_activeMediaExists_mediaIsHidden() = + kosmos.runTest { + val userMedia = MediaData(active = true) + + mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + keyguardRepository.setIsDozing(true) + + assertThat(underTest.isMediaVisible).isFalse() + } + + @Test + fun onDeviceAwake_activeMediaExists_mediaIsVisible() = + kosmos.runTest { + val userMedia = MediaData(active = true) + + mediaFilterRepository.addSelectedUserMediaEntry(userMedia) + keyguardRepository.setIsDozing(false) + + assertThat(underTest.isMediaVisible).isTrue() + } + + @Test + fun onDeviceAwake_noActiveMedia_mediaIsHidden() = + kosmos.runTest { + keyguardRepository.setIsDozing(false) + + assertThat(underTest.isMediaVisible).isFalse() + } +} diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt index e68e465ed55a..ba03c48c65e9 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt +++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt @@ -16,10 +16,50 @@ package com.android.systemui.keyguard.ui.viewmodel +import androidx.compose.runtime.getValue +import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor +import com.android.systemui.lifecycle.ExclusiveActivatable +import com.android.systemui.lifecycle.Hydrator import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarouselInteractor -import javax.inject.Inject -import kotlinx.coroutines.flow.StateFlow +import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import kotlinx.coroutines.flow.flowOf -class KeyguardMediaViewModel @Inject constructor(mediaCarouselInteractor: MediaCarouselInteractor) { - val isMediaVisible: StateFlow<Boolean> = mediaCarouselInteractor.hasActiveMediaOrRecommendation +class KeyguardMediaViewModel +@AssistedInject +constructor( + mediaCarouselInteractor: MediaCarouselInteractor, + keyguardInteractor: KeyguardInteractor, +) : ExclusiveActivatable() { + + private val hydrator = Hydrator("KeyguardMediaViewModel.hydrator") + /** + * Whether media carousel is visible on lockscreen. Media may be presented on lockscreen but + * still hidden on certain surfaces like AOD + */ + val isMediaVisible: Boolean by + hydrator.hydratedStateOf( + traceName = "isMediaVisible", + source = + keyguardInteractor.isDozing.flatMapLatestConflated { isDozing -> + if (isDozing) { + flowOf(false) + } else { + mediaCarouselInteractor.hasActiveMediaOrRecommendation + } + }, + initialValue = + !keyguardInteractor.isDozing.value && + mediaCarouselInteractor.hasActiveMediaOrRecommendation.value, + ) + + override suspend fun onActivated(): Nothing { + hydrator.activate() + } + + @AssistedFactory + interface Factory { + fun create(): KeyguardMediaViewModel + } } diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelFactoryKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelFactoryKosmos.kt new file mode 100644 index 000000000000..16d3fdc26613 --- /dev/null +++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelFactoryKosmos.kt @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2025 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.android.systemui.keyguard.ui.viewmodel + +import com.android.systemui.keyguard.domain.interactor.keyguardInteractor +import com.android.systemui.kosmos.Kosmos +import com.android.systemui.media.controls.domain.pipeline.interactor.mediaCarouselInteractor + +val Kosmos.keyguardMediaViewModelFactory by + Kosmos.Fixture { + object : KeyguardMediaViewModel.Factory { + override fun create(): KeyguardMediaViewModel { + return KeyguardMediaViewModel(mediaCarouselInteractor, keyguardInteractor) + } + } + } |