Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b015b4e9 authored by Danny Burakov's avatar Danny Burakov Committed by Android (Google) Code Review
Browse files

Merge "[Dual Shade] Fix inconsistent clock size values on the lockscreen." into main

parents 0544d258 82d3cf64
Loading
Loading
Loading
Loading
+37 −5
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos
import com.android.systemui.keyguard.data.repository.keyguardClockRepository
import com.android.systemui.keyguard.data.repository.keyguardRepository
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.shared.model.ClockSizeSetting
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardState
@@ -68,6 +69,7 @@ class KeyguardClockInteractorTest : SysuiTestCase() {
    fun clockSize_sceneContainerFlagOff_basedOnRepository() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            kosmos.fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.DYNAMIC)
            kosmos.keyguardClockRepository.setClockSize(ClockSize.LARGE)
            assertThat(value).isEqualTo(ClockSize.LARGE)

@@ -75,6 +77,17 @@ class KeyguardClockInteractorTest : SysuiTestCase() {
            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @DisableSceneContainer
    fun clockSize_sceneContainerFlagOff_smallClockSettingSelected_SMALL() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            kosmos.fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.SMALL)
            kosmos.keyguardClockRepository.setClockSize(ClockSize.LARGE)

            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @EnableSceneContainer
    fun clockSize_forceSmallClock_SMALL() =
@@ -91,59 +104,78 @@ class KeyguardClockInteractorTest : SysuiTestCase() {

    @Test
    @EnableSceneContainer
    fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasNotifs_SMALL() =
    fun clockSize_sceneContainerFlagOn_shadeModeSingle_hasNotifs_SMALL() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            kosmos.shadeRepository.setShadeLayoutWide(false)
            kosmos.activeNotificationListRepository.setActiveNotifs(1)

            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @EnableSceneContainer
    fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasMedia_SMALL() =
    fun clockSize_sceneContainerFlagOn_shadeModeSingle_hasMedia_SMALL() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            kosmos.shadeRepository.setShadeLayoutWide(false)
            val userMedia = MediaData().copy(active = true)
            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)

            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @EnableSceneContainer
    fun clockSize_SceneContainerFlagOn_shadeModeSplit_isMediaVisible_SMALL() =
    fun clockSize_sceneContainerFlagOn_shadeModeSplit_isMediaVisible_SMALL() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            val userMedia = MediaData().copy(active = true)
            kosmos.shadeRepository.setShadeLayoutWide(true)
            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
            kosmos.keyguardRepository.setIsDozing(false)

            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @EnableSceneContainer
    fun clockSize_SceneContainerFlagOn_shadeModeSplit_noMedia_LARGE() =
    fun clockSize_sceneContainerFlagOn_shadeModeSplit_noMedia_LARGE() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            kosmos.shadeRepository.setShadeLayoutWide(true)
            kosmos.keyguardRepository.setIsDozing(false)

            assertThat(value).isEqualTo(ClockSize.LARGE)
        }

    @Test
    @EnableSceneContainer
    fun clockSize_SceneContainerFlagOn_shadeModeSplit_isDozing_LARGE() =
    fun clockSize_sceneContainerFlagOn_shadeModeSplit_isDozing_LARGE() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            val userMedia = MediaData().copy(active = true)
            kosmos.shadeRepository.setShadeLayoutWide(true)
            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
            kosmos.keyguardRepository.setIsDozing(true)

            assertThat(value).isEqualTo(ClockSize.LARGE)
        }

    @Test
    @EnableSceneContainer
    fun clockSize_sceneContainerFlagOn_shadeModeSplit_smallClockSettingSelectd_SMALL() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)
            val userMedia = MediaData().copy(active = true)
            kosmos.fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.SMALL)
            kosmos.shadeRepository.setShadeLayoutWide(true)
            kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
            kosmos.keyguardRepository.setIsDozing(true)

            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @EnableSceneContainer
    fun clockShouldBeCentered_sceneContainerFlagOn_notSplitMode_true() =
+10 −39
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardClockRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.data.repository.keyguardClockRepository
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.shared.model.ClockSizeSetting
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel.ClockLayout
import com.android.systemui.kosmos.testScope
@@ -55,17 +54,18 @@ import platform.test.runner.parameterized.Parameters
@SmallTest
@RunWith(ParameterizedAndroidJunit4::class)
class KeyguardClockViewModelTest(flags: FlagsParameterization) : SysuiTestCase() {
    val kosmos = testKosmos()
    val testScope = kosmos.testScope
    val underTest by lazy { kosmos.keyguardClockViewModel }
    val res = context.resources

    @Mock lateinit var clockController: ClockController
    @Mock lateinit var largeClock: ClockFaceController
    @Mock lateinit var smallClock: ClockFaceController
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val underTest by lazy { kosmos.keyguardClockViewModel }
    private val res = context.resources

    var config = ClockConfig("TEST", "Test", "")
    var faceConfig = ClockFaceConfig()
    @Mock private lateinit var clockController: ClockController
    @Mock private lateinit var largeClock: ClockFaceController
    @Mock private lateinit var smallClock: ClockFaceController

    private var config = ClockConfig("TEST", "Test", "")
    private var faceConfig = ClockFaceConfig()

    init {
        mSetFlagsRule.setFlagsParameterization(flags)
@@ -195,35 +195,6 @@ class KeyguardClockViewModelTest(flags: FlagsParameterization) : SysuiTestCase()
            assertThat(hasCustomPositionUpdatedAnimation).isEqualTo(false)
        }

    @Test
    fun testClockSize_alwaysSmallClockSize() =
        testScope.runTest {
            val value by collectLastValue(underTest.clockSize)

            with(kosmos) {
                fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.SMALL)
                keyguardClockRepository.setClockSize(ClockSize.LARGE)
            }

            assertThat(value).isEqualTo(ClockSize.SMALL)
        }

    @Test
    @DisableSceneContainer
    fun testClockSize_dynamicClockSize() =
        testScope.runTest {
            with(kosmos) {
                val value by collectLastValue(underTest.clockSize)
                fakeKeyguardClockRepository.setSelectedClockSize(ClockSizeSetting.DYNAMIC)

                keyguardClockRepository.setClockSize(ClockSize.SMALL)
                assertThat(value).isEqualTo(ClockSize.SMALL)

                keyguardClockRepository.setClockSize(ClockSize.LARGE)
                assertThat(value).isEqualTo(ClockSize.LARGE)
            }
        }

    @Test
    fun isLargeClockVisible_whenLargeClockSize_isTrue() =
        testScope.runTest {
+41 −26
Original line number Diff line number Diff line
@@ -24,7 +24,6 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardClockRepository
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.shared.model.ClockSizeSetting
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
@@ -33,12 +32,13 @@ import com.android.systemui.media.controls.domain.pipeline.interactor.MediaCarou
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockId
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import com.android.systemui.statusbar.notification.domain.interactor.ActiveNotificationsInteractor
import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor
import com.android.systemui.statusbar.notification.promoted.PromotedNotificationUiAod
import com.android.systemui.statusbar.notification.promoted.domain.interactor.AODPromotedNotificationInteractor
import com.android.systemui.util.kotlin.combine
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import com.android.systemui.wallpapers.domain.interactor.WallpaperFocalAreaInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -61,7 +61,7 @@ constructor(
    mediaCarouselInteractor: MediaCarouselInteractor,
    activeNotificationsInteractor: ActiveNotificationsInteractor,
    aodPromotedNotificationInteractor: AODPromotedNotificationInteractor,
    shadeInteractor: ShadeInteractor,
    shadeModeInteractor: ShadeModeInteractor,
    keyguardInteractor: KeyguardInteractor,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    headsUpNotificationInteractor: HeadsUpNotificationInteractor,
@@ -70,8 +70,13 @@ constructor(
    private val wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor,
) {
    private val isOnAod: Flow<Boolean> =
        keyguardTransitionInteractor.currentKeyguardState.map { it == KeyguardState.AOD }
        keyguardTransitionInteractor.currentKeyguardState.map { it == AOD }

    /**
     * The clock size setting explicitly selected by the user. When it is `SMALL`, the large clock
     * is never shown. When it is `DYNAMIC`, the clock size gets determined based on a combination
     * of system signals.
     */
    val selectedClockSize: StateFlow<ClockSizeSetting> = keyguardClockRepository.selectedClockSize

    val currentClockId: Flow<ClockId> = keyguardClockRepository.currentClockId
@@ -103,16 +108,16 @@ constructor(
            activeNotificationsInteractor.areAnyNotificationsPresent
        }

    val clockSize: StateFlow<ClockSize> =
    private val dynamicClockSize: Flow<ClockSize> =
        if (SceneContainerFlag.isEnabled) {
            combine(
                    shadeInteractor.isShadeLayoutWide,
                shadeModeInteractor.isShadeLayoutWide,
                areAnyNotificationsPresent,
                mediaCarouselInteractor.hasActiveMediaOrRecommendation,
                keyguardInteractor.isDozing,
                isOnAod,
            ) { isShadeLayoutWide, hasNotifs, hasMedia, isDozing, isOnAod ->
                    return@combine when {
                when {
                    keyguardClockRepository.shouldForceSmallClock && !isOnAod -> ClockSize.SMALL
                    !isShadeLayoutWide && (hasNotifs || hasMedia) -> ClockSize.SMALL
                    !isShadeLayoutWide -> ClockSize.LARGE
@@ -120,19 +125,29 @@ constructor(
                    else -> ClockSize.LARGE
                }
            }
        } else {
            keyguardClockRepository.clockSize
        }

    val clockSize: StateFlow<ClockSize> =
        selectedClockSize
            .flatMapLatestConflated { selectedSize ->
                if (selectedSize == ClockSizeSetting.SMALL) {
                    flowOf(ClockSize.SMALL)
                } else {
                    dynamicClockSize
                }
            }
            .stateIn(
                scope = applicationScope,
                    started = SharingStarted.WhileSubscribed(),
                started = SharingStarted.Eagerly,
                initialValue = ClockSize.LARGE,
            )
        } else {
            keyguardClockRepository.clockSize
        }

    val clockShouldBeCentered: Flow<Boolean> =
        if (SceneContainerFlag.isEnabled) {
            combine(
                shadeInteractor.isShadeLayoutWide,
                shadeModeInteractor.isShadeLayoutWide,
                areAnyNotificationsPresent,
                isAodPromotedNotificationPresent,
                isOnAod,
@@ -156,7 +171,7 @@ constructor(
            }
        } else {
            combine(
                    shadeInteractor.isShadeLayoutWide,
                    shadeModeInteractor.isShadeLayoutWide,
                    areAnyNotificationsPresent,
                    isAodPromotedNotificationPresent,
                    keyguardInteractor.dozeTransitionModel,
@@ -203,7 +218,7 @@ constructor(

    val renderedClockId: ClockId
        get() {
            return clock?.let { clock -> clock.config.id }
            return clock?.config?.id
                ?: run {
                    Log.e(TAG, "No clock is available")
                    "MISSING_CLOCK_ID"
+5 −5
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.BurnInModel
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.StateToValue
@@ -35,6 +34,7 @@ import com.android.systemui.shade.ShadeDisplayAware
import javax.inject.Inject
import kotlin.math.max
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
@@ -51,6 +51,7 @@ import kotlinx.coroutines.flow.stateIn
 * Models UI state for elements that need to apply anti-burn-in tactics when showing in AOD
 * (always-on display).
 */
@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class AodBurnInViewModel
@Inject
@@ -184,10 +185,9 @@ constructor(
                keyguardClockViewModel.currentClock.value
                    ?.config
                    ?.useAlternateSmartspaceAODTransition == true
            // Only scale large non-weather clocks
            // elements in large weather clock will translate the same as smartspace
            val useScaleOnly =
                (!useAltAod) && keyguardClockViewModel.clockSize.value == ClockSize.LARGE
            // Only scale large non-weather clocks elements in large weather clock will translate
            // the same as smartspace
            val useScaleOnly = (!useAltAod) && keyguardClockViewModel.isLargeClockVisible.value

            val burnInY = MathUtils.lerp(0, burnIn.translationY, interpolated).toInt()
            val translationY = max(params.topInset - params.minViewY, burnInY)
+7 −19
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.keyguard.ui.viewmodel

import android.content.Context
import android.content.res.Resources
import androidx.annotation.VisibleForTesting
import androidx.constraintlayout.helper.widget.Layer
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
import com.android.systemui.customization.R as customR
@@ -27,11 +26,10 @@ import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.shared.model.ClockSizeSetting
import com.android.systemui.plugins.clocks.ClockPreviewConfig
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.shade.domain.interactor.ShadeModeInteractor
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel
import com.android.systemui.statusbar.ui.SystemBarUtilsProxy
import javax.inject.Inject
@@ -47,11 +45,11 @@ import kotlinx.coroutines.flow.stateIn
class KeyguardClockViewModel
@Inject
constructor(
    val context: Context,
    private val context: Context,
    keyguardClockInteractor: KeyguardClockInteractor,
    @Application private val applicationScope: CoroutineScope,
    aodNotificationIconViewModel: NotificationIconContainerAlwaysOnDisplayViewModel,
    @get:VisibleForTesting val shadeInteractor: ShadeInteractor,
    private val shadeModeInteractor: ShadeModeInteractor,
    private val systemBarUtils: SystemBarUtilsProxy,
    @ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
    // TODO: b/374267505 - Use ShadeDisplayAware resources here.
@@ -59,17 +57,7 @@ constructor(
) {
    var burnInLayer: Layer? = null

    val clockSize: StateFlow<ClockSize> =
        combine(keyguardClockInteractor.selectedClockSize, keyguardClockInteractor.clockSize) {
                selectedSize,
                clockSize ->
                if (selectedSize == ClockSizeSetting.SMALL) ClockSize.SMALL else clockSize
            }
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.Eagerly,
                initialValue = ClockSize.LARGE,
            )
    val clockSize: StateFlow<ClockSize> = keyguardClockInteractor.clockSize

    val isLargeClockVisible: StateFlow<Boolean> =
        clockSize
@@ -118,7 +106,7 @@ constructor(
        combine(
                isLargeClockVisible,
                clockShouldBeCentered,
                shadeInteractor.isShadeLayoutWide,
                shadeModeInteractor.isShadeLayoutWide,
                currentClock,
            ) { isLargeClockVisible, clockShouldBeCentered, isShadeLayoutWide, currentClock ->
                if (currentClock?.config?.useCustomClockScene == true) {
@@ -163,7 +151,7 @@ constructor(
    fun getSmallClockTopMargin(): Int {
        return ClockPreviewConfig(
                context,
                shadeInteractor.isShadeLayoutWide.value,
                shadeModeInteractor.isShadeLayoutWide.value,
                SceneContainerFlag.isEnabled,
            )
            .getSmallClockTopPadding(systemBarUtils.getStatusBarHeaderHeightKeyguard())
@@ -172,7 +160,7 @@ constructor(
    val smallClockTopMargin =
        combine(
            configurationInteractor.onAnyConfigurationChange,
            shadeInteractor.isShadeLayoutWide,
            shadeModeInteractor.isShadeLayoutWide,
        ) { _, _ ->
            getSmallClockTopMargin()
        }
Loading