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

Commit b182cd63 authored by Sherry Zhou's avatar Sherry Zhou
Browse files

Change burn in preventing mechanism for clock

After the change, we only apply translationX and Y for large weather clock,
all small clocks, and smartspace. We apply scale and translationY for all large
non-weather clocks.

Test: atest AodBurnInViewModelTest. Manually test by clicking power
button to enter AOD from lockscreen, non-weather large
clock moves vertically with smartspace, no horizontally translation, and
scale down; small clock moves horizontally and vertically with
smartspace without scaling.
Flag: ACONFIG com.android.systemui.migrate_clocks_to_blueprint STAGING
Bug: 318740689

Change-Id: I93a0370ab38eef6e20a6ea3e5eb5242eef12afd7
parent 8cea9345
Loading
Loading
Loading
Loading
+2 −6
Original line number Diff line number Diff line
@@ -58,15 +58,11 @@ fun Modifier.burnInAware(
            .collectAsState(initial = BurnInScaleViewModel())

    return this.graphicsLayer {
        val scale =
            when {
                scaleViewModel.scaleClockOnly && isClock -> scaleViewModel.scale
                else -> 1f
            }

        this.translationX = if (isClock) 0F else translationX
        this.translationY = translationY
        this.alpha = alpha

        val scale = if (scaleViewModel.scaleClockOnly) scaleViewModel.scale else 1f
        this.scaleX = scale
        this.scaleY = scale
    }
+75 −16
Original line number Diff line number Diff line
@@ -62,8 +62,8 @@ class AodBurnInViewModelTest : SysuiTestCase() {
    private val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
    private val keyguardClockRepository = kosmos.fakeKeyguardClockRepository
    private lateinit var underTest: AodBurnInViewModel

    private var burnInParameters = BurnInParameters()
    // assign a smaller value to minViewY to avoid overflow
    private var burnInParameters = BurnInParameters(minViewY = Int.MAX_VALUE / 2)
    private val burnInFlow = MutableStateFlow(BurnInModel())

    @Before
@@ -296,52 +296,111 @@ class AodBurnInViewModelTest : SysuiTestCase() {
                    scale = 0.5f,
                )

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

    @Test
    fun translationAndScale_composeFlagOff_weatherLargeClock() =
        testBurnInViewModelForClocks(
            isSmallClock = false,
            isWeatherClock = true,
            expectedScaleOnly = false,
            enableMigrateClocksToBlueprintFlag = true,
            enableComposeLockscreenFlag = false
        )

    @Test
    fun translationAndScale_composeFlagOff_weatherSmallClock() =
        testBurnInViewModelForClocks(
            isSmallClock = true,
            isWeatherClock = true,
            expectedScaleOnly = false,
            enableMigrateClocksToBlueprintFlag = true,
            enableComposeLockscreenFlag = false
        )

    @Test
    fun translationAndScale_composeFlagOff_nonWeatherLargeClock() =
        testBurnInViewModelForClocks(
            isSmallClock = false,
            isWeatherClock = false,
            expectedScaleOnly = true,
            enableMigrateClocksToBlueprintFlag = true,
            enableComposeLockscreenFlag = false
        )

    @Test
    fun translationAndScale_composeFlagOff_nonWeatherSmallClock() =
        testBurnInViewModelForClocks(
            isSmallClock = true,
            isWeatherClock = false,
            expectedScaleOnly = false,
            enableMigrateClocksToBlueprintFlag = true,
            enableComposeLockscreenFlag = false
        )

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

    @Test
    fun translationAndScale_composeFlagOn_weatherSmallClock() =
        testBurnInViewModelWhenComposeFlagOn(
        testBurnInViewModelForClocks(
            isSmallClock = true,
            isWeatherClock = true,
            expectedScaleOnly = true
            expectedScaleOnly = false,
            enableMigrateClocksToBlueprintFlag = true,
            enableComposeLockscreenFlag = true
        )

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

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

    private fun testBurnInViewModelWhenComposeFlagOn(
    private fun testBurnInViewModelForClocks(
        isSmallClock: Boolean,
        isWeatherClock: Boolean,
        expectedScaleOnly: Boolean
        expectedScaleOnly: Boolean,
        enableMigrateClocksToBlueprintFlag: Boolean,
        enableComposeLockscreenFlag: Boolean
    ) =
        testScope.runTest {
            if (enableMigrateClocksToBlueprintFlag) {
                mSetFlagsRule.enableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
            } else {
                mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)
            }

            if (enableComposeLockscreenFlag) {
                mSetFlagsRule.enableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN)
            } else {
                mSetFlagsRule.disableFlags(AConfigFlags.FLAG_COMPOSE_LOCKSCREEN)
            }
            if (isSmallClock) {
                keyguardClockRepository.setClockSize(ClockSize.SMALL)
                // we need the following step to update stateFlow value
+12 −0
Original line number Diff line number Diff line
@@ -109,6 +109,12 @@ data class ClockMessageBuffers(
    val largeClockMessageBuffer: MessageBuffer,
)

data class AodClockBurnInModel(
    val scale: Float,
    val translationX: Float,
    val translationY: Float,
)

/** Specifies layout information for the */
interface ClockFaceLayout {
    /** All clock views to add to the root constraint layout before applying constraints. */
@@ -118,6 +124,8 @@ interface ClockFaceLayout {
    fun applyConstraints(constraints: ConstraintSet): ConstraintSet

    fun applyPreviewConstraints(constraints: ConstraintSet): ConstraintSet

    fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel)
}

/** A ClockFaceLayout that applies the default lockscreen layout to a single view */
@@ -137,6 +145,10 @@ class DefaultClockFaceLayout(val view: View) : ClockFaceLayout {
    override fun applyPreviewConstraints(constraints: ConstraintSet): ConstraintSet {
        return constraints
    }

    override fun applyAodBurnIn(aodBurnInModel: AodClockBurnInModel) {
        // Default clock doesn't need detailed control of view
    }
}

/** Events that should call when various rendering parameters change */
+30 −11
Original line number Diff line number Diff line
@@ -33,14 +33,18 @@ import com.android.systemui.keyguard.shared.model.ClockSize
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type
import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.viewmodel.KeyguardClockViewModel
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.clocks.AodClockBurnInModel
import com.android.systemui.plugins.clocks.ClockController
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch

object KeyguardClockViewBinder {
    private val TAG = KeyguardClockViewBinder::class.simpleName!!
    // When changing to new clock, we need to remove old clock views from burnInLayer
    private var lastClock: ClockController? = null

    @JvmStatic
    fun bind(
        clockSection: ClockSection,
@@ -48,6 +52,7 @@ object KeyguardClockViewBinder {
        viewModel: KeyguardClockViewModel,
        keyguardClockInteractor: KeyguardClockInteractor,
        blueprintInteractor: KeyguardBlueprintInteractor,
        rootViewModel: KeyguardRootViewModel,
    ) {
        keyguardRootView.repeatWhenAttached {
            repeatOnLifecycle(Lifecycle.State.CREATED) {
@@ -105,6 +110,28 @@ object KeyguardClockViewBinder {
                        }
                    }
                }

                launch {
                    if (!MigrateClocksToBlueprint.isEnabled) return@launch
                    combine(
                            rootViewModel.translationX,
                            rootViewModel.translationY,
                            rootViewModel.scale,
                            ::Triple
                        )
                        .collect { (translationX, translationY, scale) ->
                            viewModel.currentClock.value
                                ?.largeClock
                                ?.layout
                                ?.applyAodBurnIn(
                                    AodClockBurnInModel(
                                        translationX = translationX.value!!,
                                        translationY = translationY,
                                        scale = scale.scale
                                    )
                                )
                        }
                }
            }
        }
    }
@@ -117,17 +144,16 @@ object KeyguardClockViewBinder {
    ) {
        val burnInLayer = viewModel.burnInLayer
        val clockController = viewModel.currentClock.value
        // Large clocks won't be added to or removed from burn in layer
        // Weather large clock has customized burn in preventing mechanism
        // Non-weather large clock will only scale and translate vertically
        clockController?.let { clock ->
            when (clockSize) {
                ClockSize.LARGE -> {
                    clock.smallClock.layout.views.forEach { burnInLayer?.removeView(it) }
                    if (clock.config.useAlternateSmartspaceAODTransition) {
                        clock.largeClock.layout.views.forEach { burnInLayer?.addView(it) }
                    }
                }
                ClockSize.SMALL -> {
                    clock.smallClock.layout.views.forEach { burnInLayer?.addView(it) }
                    clock.largeClock.layout.views.forEach { burnInLayer?.removeView(it) }
                }
            }
        }
@@ -148,13 +174,6 @@ object KeyguardClockViewBinder {
                burnInLayer?.removeView(it)
                rootView.removeView(it)
            }

            // add large clock to burn in layer only when it will have same transition with other
            // components in AOD otherwise, it will have a separate scale transition while other
            // components only have translate transition
            if (clock.config.useAlternateSmartspaceAODTransition) {
                clock.largeClock.layout.views.forEach { burnInLayer?.removeView(it) }
            }
            clock.largeClock.layout.views.forEach { rootView.removeView(it) }
        }
        lastClock = currentClock
+0 −18
Original line number Diff line number Diff line
@@ -36,7 +36,6 @@ import androidx.activity.setViewTreeOnBackPressedDispatcherOwner
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.repeatOnLifecycle
import com.android.app.animation.Interpolators
import com.android.app.tracing.coroutines.launch
import com.android.internal.jank.InteractionJankMonitor
import com.android.internal.jank.InteractionJankMonitor.CUJ_SCREEN_OFF_SHOW_AOD
import com.android.systemui.Flags.newAodTransition
@@ -257,23 +256,6 @@ object KeyguardRootViewBinder {
                                        it.scaleX = scaleViewModel.scale
                                        it.scaleY = scaleViewModel.scale
                                    }
                                    // Make sure to reset these views, or they will be invisible
                                    if (childViews[burnInLayerId]?.scaleX != 1f) {
                                        childViews[burnInLayerId]?.scaleX = 1f
                                        childViews[burnInLayerId]?.scaleY = 1f
                                        childViews[aodNotificationIconContainerId]?.scaleX = 1f
                                        childViews[aodNotificationIconContainerId]?.scaleY = 1f
                                        view.requestLayout()
                                    }
                                } else {
                                    // For weather clock, large clock should have only scale
                                    // transition with other parts in burnInLayer
                                    childViews[burnInLayerId]?.scaleX = scaleViewModel.scale
                                    childViews[burnInLayerId]?.scaleY = scaleViewModel.scale
                                    childViews[aodNotificationIconContainerId]?.scaleX =
                                        scaleViewModel.scale
                                    childViews[aodNotificationIconContainerId]?.scaleY =
                                        scaleViewModel.scale
                                }
                            }
                        }
Loading