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

Commit b2eb12e9 authored by Matt Pietal's avatar Matt Pietal
Browse files

Smooth burn-in transitions

GONE->AOD transitions are easily interruptible by a power button push
to keep the phone on, or to prevent unlocking. This adds a smoother
transition from AOD->LOCKSCREEN which is next in the sequence. Rather
than rely on a preset starting point, it begins from the current
y-translation value and interpolates to the final resting point.

Also, adds the ability for animation flows to return both a value and
the transition state. The transition state is frequently used in view
models to know which transition is truly active.

Fixes: 322197793
Test: manual - interrupt GONE->AOD
Test: atest com.android.systemui.keyguard
Flag: ACONFIG com.android.systemui.keyguard_shade_migration_nssl
DEVELOPMENT

Change-Id: If9501500796bee9d421a291bf555077e8eefcc14
parent df39b491
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ package com.android.systemui.keyguard.ui.viewmodel

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags as AConfigFlags
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
@@ -68,6 +69,8 @@ class AodBurnInViewModelTest : SysuiTestCase() {

    @Before
    fun setUp() {
        mSetFlagsRule.disableFlags(AConfigFlags.FLAG_MIGRATE_CLOCKS_TO_BLUEPRINT)

        MockitoAnnotations.initMocks(this)
        whenever(burnInInteractor.keyguardBurnIn).thenReturn(burnInFlow)
        kosmos.burnInInteractor = burnInInteractor
+1 −0
Original line number Diff line number Diff line
@@ -74,6 +74,7 @@ constructor(
                BurnInModel(translationX, translationY, burnInHelperWrapper.burnInScale())
            }
            .distinctUntilChanged()
            .stateIn(scope, SharingStarted.Lazily, BurnInModel())

    /**
     * Use for max burn-in offsets that are NOT specified in pixels. This flow will recalculate the
+2 −0
Original line number Diff line number Diff line
@@ -97,6 +97,8 @@ constructor(
                        val modeOnCanceled =
                            if (lastStartedStep.from == KeyguardState.LOCKSCREEN) {
                                TransitionModeOnCanceled.REVERSE
                            } else if (lastStartedStep.from == KeyguardState.GONE) {
                                TransitionModeOnCanceled.RESET
                            } else {
                                TransitionModeOnCanceled.LAST_VALUE
                            }
+37 −6
Original line number Diff line number Diff line
@@ -112,6 +112,38 @@ constructor(
            interpolator: Interpolator = LINEAR,
            name: String? = null
        ): Flow<Float> {
            return sharedFlowWithState(
                    duration = duration,
                    onStep = onStep,
                    startTime = startTime,
                    onStart = onStart,
                    onCancel = onCancel,
                    onFinish = onFinish,
                    interpolator = interpolator,
                    name = name,
                )
                .mapNotNull { stateToValue -> stateToValue.value }
        }

        /**
         * Transitions will occur over a [transitionDuration] with [TransitionStep]s being emitted
         * in the range of [0, 1]. View animations should begin and end within a subset of this
         * range. This function maps the [startTime] and [duration] into [0, 1], when this subset is
         * valid.
         *
         * Will return a [StateToValue], which encompasses the calculated value as well as the
         * transitionState that is associated with it.
         */
        fun sharedFlowWithState(
            duration: Duration,
            onStep: (Float) -> Float,
            startTime: Duration = 0.milliseconds,
            onStart: (() -> Unit)? = null,
            onCancel: (() -> Float)? = null,
            onFinish: (() -> Float)? = null,
            interpolator: Interpolator = LINEAR,
            name: String? = null
        ): Flow<StateToValue> {
            if (!duration.isPositive()) {
                throw IllegalArgumentException("duration must be a positive number: $duration")
            }
@@ -164,7 +196,6 @@ constructor(
                        .also { logger.logTransitionStep(name, step, it.value) }
                }
                .distinctUntilChanged()
                .mapNotNull { stateToValue -> stateToValue.value }
        }

        /**
@@ -174,9 +205,9 @@ constructor(
            return sharedFlow(duration = 1.milliseconds, onStep = { value }, onFinish = { value })
        }
    }
}

data class StateToValue(
        val transitionState: TransitionState,
        val value: Float?,
    val transitionState: TransitionState = TransitionState.FINISHED,
    val value: Float? = 0f,
)
}
+6 −0
Original line number Diff line number Diff line
@@ -311,6 +311,12 @@ object KeyguardRootViewBinder {
            }
        }

        if (KeyguardShadeMigrationNssl.isEnabled) {
            burnInParams.update { current ->
                current.copy(translationY = { childViews[burnInLayerId]?.translationY })
            }
        }

        onLayoutChangeListener = OnLayoutChange(viewModel, burnInParams)
        view.addOnLayoutChangeListener(onLayoutChangeListener)

Loading