summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Michael Mikhail <michaelmikhil@google.com> 2025-01-23 05:26:49 -0800
committer Android (Google) Code Review <android-gerrit@google.com> 2025-01-23 05:26:49 -0800
commit8ee167ecf0d85d5fa015ed3f5ec4fa5dd5fd1195 (patch)
tree9da9605501166b397c98ecf96d48f50f676902b0
parent849d1b8a10e649e3e3cb88717d86ffea7a934b01 (diff)
parent9e0611aa19861a2fe5be7704e1ee6d70299d8562 (diff)
Merge "[Flexiglass] hide UMO on AOD." into main
-rw-r--r--packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/MediaCarouselSection.kt12
-rw-r--r--packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelTest.kt84
-rw-r--r--packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModel.kt48
-rw-r--r--packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardMediaViewModelFactoryKosmos.kt30
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)
+ }
+ }
+ }