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

Commit 9cb510f9 authored by Treehugger Robot's avatar Treehugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Add preventing burn-in mechanism for large clocks" into main

parents c05d2fa7 c40c7936
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -61,11 +61,10 @@ fun Modifier.burnInAware(
        val scale =
        val scale =
            when {
            when {
                scaleViewModel.scaleClockOnly && isClock -> scaleViewModel.scale
                scaleViewModel.scaleClockOnly && isClock -> scaleViewModel.scale
                !scaleViewModel.scaleClockOnly -> scaleViewModel.scale
                else -> 1f
                else -> 1f
            }
            }


        this.translationX = translationX
        this.translationX = if (isClock) 0F else translationX
        this.translationY = translationY
        this.translationY = translationY
        this.alpha = alpha
        this.alpha = alpha
        this.scaleX = scale
        this.scaleX = scale
+8 −2
Original line number Original line Diff line number Diff line
@@ -88,7 +88,7 @@ constructor(
    }
    }


    @Composable
    @Composable
    fun SceneScope.LargeClock(modifier: Modifier = Modifier) {
    fun SceneScope.LargeClock(burnInParams: BurnInParameters, modifier: Modifier = Modifier) {
        val currentClock by viewModel.currentClock.collectAsState()
        val currentClock by viewModel.currentClock.collectAsState()
        if (currentClock?.largeClock?.view == null) {
        if (currentClock?.largeClock?.view == null) {
            return
            return
@@ -129,7 +129,13 @@ constructor(
                    update = {
                    update = {
                        it.ensureClockViewExists(checkNotNull(currentClock).largeClock.view)
                        it.ensureClockViewExists(checkNotNull(currentClock).largeClock.view)
                    },
                    },
                    modifier = Modifier.fillMaxSize()
                    modifier =
                        Modifier.fillMaxSize()
                            .burnInAware(
                                viewModel = aodBurnInViewModel,
                                params = burnInParams,
                                isClock = true
                            )
                )
                )
            }
            }
        }
        }
+13 −2
Original line number Original line Diff line number Diff line
@@ -149,6 +149,7 @@ constructor(
            }
            }
            with(clockSection) {
            with(clockSection) {
                LargeClock(
                LargeClock(
                    burnInParams = burnIn.parameters,
                    modifier =
                    modifier =
                        Modifier.fillMaxSize().thenIf(shouldOffSetClockToOneHalf) {
                        Modifier.fillMaxSize().thenIf(shouldOffSetClockToOneHalf) {
                            // If we do not have a custom position animation, we want
                            // If we do not have a custom position animation, we want
@@ -179,7 +180,12 @@ constructor(


        Column(modifier = modifier) {
        Column(modifier = modifier) {
            val currentClock = currentClockState.value ?: return@Column
            val currentClock = currentClockState.value ?: return@Column
            with(weatherClockSection) { Time(clock = currentClock, modifier = Modifier) }
            with(weatherClockSection) {
                Time(
                    clock = currentClock,
                    burnInParams = burnIn.parameters,
                )
            }
            val density = LocalDensity.current
            val density = LocalDensity.current
            val context = LocalContext.current
            val context = LocalContext.current


@@ -193,7 +199,12 @@ constructor(
                        )
                        )
                )
                )
            }
            }
            with(weatherClockSection) { LargeClockSectionBelowSmartspace(clock = currentClock) }
            with(weatherClockSection) {
                LargeClockSectionBelowSmartspace(
                    burnInParams = burnIn.parameters,
                    clock = currentClock,
                )
            }
        }
        }
    }
    }


+9 −5
Original line number Original line Diff line number Diff line
@@ -35,7 +35,9 @@ import com.android.compose.animation.scene.SceneScope
import com.android.compose.modifiers.padding
import com.android.compose.modifiers.padding
import com.android.systemui.customization.R as customizationR
import com.android.systemui.customization.R as customizationR
import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys
import com.android.systemui.keyguard.ui.composable.blueprint.WeatherClockElementKeys
import com.android.systemui.keyguard.ui.composable.modifier.burnInAware
import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
import com.android.systemui.keyguard.ui.viewmodel.AodBurnInViewModel
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.plugins.clocks.ClockController
import javax.inject.Inject
import javax.inject.Inject
@@ -50,19 +52,19 @@ constructor(
    @Composable
    @Composable
    fun SceneScope.Time(
    fun SceneScope.Time(
        clock: ClockController,
        clock: ClockController,
        modifier: Modifier = Modifier,
        burnInParams: BurnInParameters,
    ) {
    ) {
        Row(
        Row(
            modifier =
            modifier =
                Modifier.padding(
                Modifier.padding(
                        horizontal = dimensionResource(customizationR.dimen.clock_padding_start)
                        horizontal = dimensionResource(customizationR.dimen.clock_padding_start)
                    )
                    )
                    .burnInAware(aodBurnInViewModel, burnInParams, isClock = true)
        ) {
        ) {
            WeatherElement(
            WeatherElement(
                weatherClockElementViewId = customizationR.id.weather_clock_time,
                weatherClockElementViewId = customizationR.id.weather_clock_time,
                clock = clock,
                clock = clock,
                elementKey = WeatherClockElementKeys.timeElementKey,
                elementKey = WeatherClockElementKeys.timeElementKey,
                modifier = modifier,
            )
            )
        }
        }
    }
    }
@@ -124,7 +126,7 @@ constructor(
        weatherClockElementViewId: Int,
        weatherClockElementViewId: Int,
        clock: ClockController,
        clock: ClockController,
        elementKey: ElementKey,
        elementKey: ElementKey,
        modifier: Modifier
        modifier: Modifier = Modifier,
    ) {
    ) {
        MovableElement(key = elementKey, modifier) {
        MovableElement(key = elementKey, modifier) {
            content {
            content {
@@ -150,6 +152,7 @@ constructor(


    @Composable
    @Composable
    fun SceneScope.LargeClockSectionBelowSmartspace(
    fun SceneScope.LargeClockSectionBelowSmartspace(
        burnInParams: BurnInParameters,
        clock: ClockController,
        clock: ClockController,
    ) {
    ) {
        Row(
        Row(
@@ -158,6 +161,7 @@ constructor(
                    .padding(
                    .padding(
                        horizontal = dimensionResource(customizationR.dimen.clock_padding_start)
                        horizontal = dimensionResource(customizationR.dimen.clock_padding_start)
                    )
                    )
                    .burnInAware(aodBurnInViewModel, burnInParams, isClock = true)
        ) {
        ) {
            Date(clock = clock, modifier = Modifier.wrapContentSize())
            Date(clock = clock, modifier = Modifier.wrapContentSize())
            Box(
            Box(
+79 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@ import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepos
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.burnInInteractor
import com.android.systemui.keyguard.domain.interactor.burnInInteractor
import com.android.systemui.keyguard.shared.model.BurnInModel
import com.android.systemui.keyguard.shared.model.BurnInModel
import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -59,6 +60,7 @@ class AodBurnInViewModelTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val testScope = kosmos.testScope
    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
    private val keyguardClockRepository = kosmos.fakeKeyguardClockRepository
    private lateinit var underTest: AodBurnInViewModel
    private lateinit var underTest: AodBurnInViewModel


    private var burnInParameters = BurnInParameters()
    private var burnInParameters = BurnInParameters()
@@ -67,6 +69,7 @@ class AodBurnInViewModelTest : SysuiTestCase() {
    @Before
    @Before
    fun setUp() {
    fun setUp() {
        mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
        mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
        mSetFlagsRule.disableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN)


        MockitoAnnotations.initMocks(this)
        MockitoAnnotations.initMocks(this)
        whenever(burnInInteractor.burnIn(anyInt(), anyInt())).thenReturn(burnInFlow)
        whenever(burnInInteractor.burnIn(anyInt(), anyInt())).thenReturn(burnInFlow)
@@ -298,4 +301,80 @@ class AodBurnInViewModelTest : SysuiTestCase() {
            assertThat(movement?.scale).isEqualTo(0.5f)
            assertThat(movement?.scale).isEqualTo(0.5f)
            assertThat(movement?.scaleClockOnly).isEqualTo(false)
            assertThat(movement?.scaleClockOnly).isEqualTo(false)
        }
        }

    @Test
    fun translationAndScale_composeFlagOn_weatherLargeClock() =
        testBurnInViewModelWhenComposeFlagOn(
            isSmallClock = false,
            isWeatherClock = true,
            expectedScaleOnly = false
        )

    @Test
    fun translationAndScale_composeFlagOn_weatherSmallClock() =
        testBurnInViewModelWhenComposeFlagOn(
            isSmallClock = true,
            isWeatherClock = true,
            expectedScaleOnly = true
        )

    @Test
    fun translationAndScale_composeFlagOn_nonWeatherLargeClock() =
        testBurnInViewModelWhenComposeFlagOn(
            isSmallClock = false,
            isWeatherClock = false,
            expectedScaleOnly = true
        )

    @Test
    fun translationAndScale_composeFlagOn_nonWeatherSmallClock() =
        testBurnInViewModelWhenComposeFlagOn(
            isSmallClock = true,
            isWeatherClock = false,
            expectedScaleOnly = true
        )

    private fun testBurnInViewModelWhenComposeFlagOn(
        isSmallClock: Boolean,
        isWeatherClock: Boolean,
        expectedScaleOnly: Boolean
    ) =
        testScope.runTest {
            mSetFlagsRule.enableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
            mSetFlagsRule.enableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN)
            if (isSmallClock) {
                keyguardClockRepository.setClockSize(ClockSize.SMALL)
                // we need the following step to update stateFlow value
                kosmos.testScope.collectLastValue(kosmos.keyguardClockViewModel.clockSize)
            }

            whenever(clockController.config.useAlternateSmartspaceAODTransition)
                .thenReturn(if (isWeatherClock) true else false)

            val movement by collectLastValue(underTest.movement(burnInParameters))

            // Set to dozing (on AOD)
            keyguardTransitionRepository.sendTransitionStep(
                TransitionStep(
                    from = KeyguardState.LOCKSCREEN,
                    to = KeyguardState.AOD,
                    value = 1f,
                    transitionState = TransitionState.FINISHED
                ),
                validateStep = false,
            )

            // Trigger a change to the burn-in model
            burnInFlow.value =
                BurnInModel(
                    translationX = 20,
                    translationY = 30,
                    scale = 0.5f,
                )

            assertThat(movement?.translationX).isEqualTo(20)
            assertThat(movement?.translationY).isEqualTo(30)
            assertThat(movement?.scale).isEqualTo(0.5f)
            assertThat(movement?.scaleClockOnly).isEqualTo(expectedScaleOnly)
        }
}
}
Loading