Merge "[Flexiglass] Hide carousel based on lock screen setting" into main
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 808e666..5f7b1ad 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
@@ -35,6 +35,7 @@
import com.android.systemui.media.controls.ui.view.MediaHost
import com.android.systemui.res.R
import com.android.systemui.util.animation.MeasurementInput
+import kotlinx.coroutines.ExperimentalCoroutinesApi
object MediaCarousel {
object Elements {
@@ -46,6 +47,7 @@
}
}
+@ExperimentalCoroutinesApi
@Composable
fun SceneScope.MediaCarousel(
isVisible: Boolean,
@@ -54,7 +56,7 @@
carouselController: MediaCarouselController,
offsetProvider: (() -> IntOffset)? = null,
) {
- if (!isVisible) {
+ if (!isVisible || carouselController.isLockedAndHidden()) {
return
}
diff --git a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
index 19cdee7..8fd578e 100644
--- a/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/controls/ui/controller/MediaCarouselController.kt
@@ -45,6 +45,7 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
@@ -75,7 +76,6 @@
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.qs.PageIndicator
import com.android.systemui.res.R
-import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shared.system.SysUiStatsLog
@@ -103,6 +103,7 @@
import javax.inject.Provider
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.distinctUntilChanged
@@ -121,6 +122,7 @@
* Class that is responsible for keeping the view carousel up to date. This also handles changes in
* state and applies them to the media carousel like the expansion.
*/
+@ExperimentalCoroutinesApi
@SysUISingleton
class MediaCarouselController
@Inject
@@ -149,7 +151,7 @@
private val secureSettings: SecureSettings,
private val mediaCarouselViewModel: MediaCarouselViewModel,
private val mediaViewControllerFactory: Provider<MediaViewController>,
- private val sceneInteractor: SceneInteractor,
+ private val deviceEntryInteractor: DeviceEntryInteractor,
) : Dumpable {
/** The current width of the carousel */
var currentCarouselWidth: Int = 0
@@ -904,9 +906,15 @@
/** Return true if the carousel should be hidden because lockscreen is currently visible */
fun isLockedAndHidden(): Boolean {
- val keyguardState = keyguardTransitionInteractor.getFinishedState()
- return !allowMediaPlayerOnLockScreen &&
- KeyguardState.lockscreenVisibleInState(keyguardState)
+ val isOnLockscreen =
+ if (SceneContainerFlag.isEnabled) {
+ !deviceEntryInteractor.isDeviceEntered.value
+ } else {
+ KeyguardState.lockscreenVisibleInState(
+ keyguardTransitionInteractor.getFinishedState()
+ )
+ }
+ return !allowMediaPlayerOnLockScreen && isOnLockscreen
}
private fun reorderAllPlayers(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
index 850916b..46c66e0 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/media/controls/ui/controller/MediaCarouselControllerTest.kt
@@ -27,19 +27,24 @@
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.compose.animation.scene.ObservableTransitionState
+import com.android.compose.animation.scene.SceneKey
import com.android.internal.logging.InstanceId
import com.android.keyguard.KeyguardUpdateMonitor
import com.android.keyguard.KeyguardUpdateMonitorCallback
import com.android.systemui.SysuiTestCase
import com.android.systemui.dagger.qualifiers.Main
+import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.dump.DumpManager
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.flags.Flags
import com.android.systemui.flags.fakeFeatureFlagsClassic
+import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFingerprintAuthRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
+import com.android.systemui.keyguard.shared.model.SuccessFingerprintAuthenticationStatus
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -71,14 +76,18 @@
import com.android.systemui.util.settings.GlobalSettings
import com.android.systemui.util.settings.SecureSettings
import com.android.systemui.util.time.FakeSystemClock
+import com.google.common.truth.Truth.assertThat
import java.util.Locale
import javax.inject.Provider
import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertFalse
import junit.framework.Assert.assertTrue
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.test.TestDispatcher
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.UnconfinedTestDispatcher
+import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Before
@@ -106,6 +115,7 @@
private const val PAUSED_LOCAL = "paused local"
private const val PLAYING_LOCAL = "playing local"
+@ExperimentalCoroutinesApi
@SmallTest
@TestableLooper.RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidJUnit4::class)
@@ -183,7 +193,7 @@
secureSettings = secureSettings,
mediaCarouselViewModel = kosmos.mediaCarouselViewModel,
mediaViewControllerFactory = mediaViewControllerFactory,
- sceneInteractor = kosmos.sceneInteractor,
+ deviceEntryInteractor = kosmos.deviceEntryInteractor,
)
verify(configurationController).addCallback(capture(configListener))
verify(visualStabilityProvider)
@@ -868,7 +878,6 @@
}
@DisableSceneContainer
- @ExperimentalCoroutinesApi
@Test
fun testKeyguardGone_showMediaCarousel() =
kosmos.testScope.runTest {
@@ -892,7 +901,6 @@
}
@EnableSceneContainer
- @ExperimentalCoroutinesApi
@Test
fun testKeyguardGone_showMediaCarousel_scene_container() =
kosmos.testScope.runTest {
@@ -910,7 +918,6 @@
job.cancel()
}
- @ExperimentalCoroutinesApi
@Test
fun keyguardShowing_notAllowedOnLockscreen_updateVisibility() {
kosmos.testScope.runTest {
@@ -940,7 +947,6 @@
}
}
- @ExperimentalCoroutinesApi
@Test
fun keyguardShowing_allowedOnLockscreen_updateVisibility() {
kosmos.testScope.runTest {
@@ -970,6 +976,74 @@
}
}
+ @EnableSceneContainer
+ @Test
+ fun deviceEntered_mediaAllowed_notLockedAndHidden() {
+ kosmos.testScope.runTest {
+ val settingsJob =
+ mediaCarouselController.listenForLockscreenSettingChanges(
+ kosmos.applicationCoroutineScope
+ )
+ secureSettings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, true)
+ setDeviceEntered(true)
+
+ assertEquals(false, mediaCarouselController.isLockedAndHidden())
+
+ settingsJob.cancel()
+ }
+ }
+
+ @EnableSceneContainer
+ @Test
+ fun deviceEntered_mediaNotAllowed_notLockedAndHidden() {
+ kosmos.testScope.runTest {
+ val settingsJob =
+ mediaCarouselController.listenForLockscreenSettingChanges(
+ kosmos.applicationCoroutineScope
+ )
+ secureSettings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, false)
+ setDeviceEntered(true)
+
+ assertEquals(false, mediaCarouselController.isLockedAndHidden())
+
+ settingsJob.cancel()
+ }
+ }
+
+ @EnableSceneContainer
+ @Test
+ fun deviceNotEntered_mediaAllowed_notLockedAndHidden() {
+ kosmos.testScope.runTest {
+ val settingsJob =
+ mediaCarouselController.listenForLockscreenSettingChanges(
+ kosmos.applicationCoroutineScope
+ )
+ secureSettings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, true)
+ setDeviceEntered(false)
+
+ assertEquals(false, mediaCarouselController.isLockedAndHidden())
+
+ settingsJob.cancel()
+ }
+ }
+
+ @EnableSceneContainer
+ @Test
+ fun deviceNotEntered_mediaNotAllowed_lockedAndHidden() {
+ kosmos.testScope.runTest {
+ val settingsJob =
+ mediaCarouselController.listenForLockscreenSettingChanges(
+ kosmos.applicationCoroutineScope
+ )
+ secureSettings.putBool(Settings.Secure.MEDIA_CONTROLS_LOCK_SCREEN, false)
+ setDeviceEntered(false)
+
+ assertEquals(true, mediaCarouselController.isLockedAndHidden())
+
+ settingsJob.cancel()
+ }
+ }
+
@Test
fun testInvisibleToUserAndExpanded_playersNotListening() {
// Add players to carousel.
@@ -1129,4 +1203,30 @@
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
)
}
+
+ private fun TestScope.setDeviceEntered(isEntered: Boolean) {
+ if (isEntered) {
+ // Unlock the device, marking the device as entered
+ kosmos.fakeDeviceEntryFingerprintAuthRepository.setAuthenticationStatus(
+ SuccessFingerprintAuthenticationStatus(0, true)
+ )
+ runCurrent()
+ }
+ setScene(
+ if (isEntered) {
+ Scenes.Gone
+ } else {
+ Scenes.Lockscreen
+ }
+ )
+ assertThat(kosmos.deviceEntryInteractor.isDeviceEntered.value).isEqualTo(isEntered)
+ }
+
+ private fun TestScope.setScene(key: SceneKey) {
+ kosmos.sceneInteractor.changeScene(key, "test")
+ kosmos.sceneInteractor.setTransitionState(
+ MutableStateFlow<ObservableTransitionState>(ObservableTransitionState.Idle(key))
+ )
+ runCurrent()
+ }
}