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

Commit 238ab377 authored by Matt Pietal's avatar Matt Pietal
Browse files

Swipe to unlock - Fix alpha continuity

Many transitions should start from the last value used in the UI
layer, such as alpha, translationX, translationY. In the case of swipe
to unlock, as the user is swiping up, elements are fading out until a
certain point is reached which then triggers a LOCKSCREEN->GONE
transition. This transition should begin from the current alpha value
rather than some other arbitrary point.

Fixes: 322198222
Test: atest KeyguardRootViewModelTest
SharedNotificationContainerViewModelTest
LockscreenToGoneTransitionViewModelTest
Test: manual - slowly swipe to unlock
Test: manual - fling swipe to unlock
Flag: ACONFIG com.android.systemui.keyguard_shade_migration_nssl
DEVELOPMENT
Flag: ACONFIG com.android.systemui.keyguard_bottom_area_refactor
STAGING

Change-Id: Ida64adfbde26654548f80426cb4050b4aedfa52e
parent e9d40b30
Loading
Loading
Loading
Loading
+5 −3
Original line number Diff line number Diff line
@@ -74,6 +74,8 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
    private val dozeParameters = kosmos.dozeParameters
    private val underTest by lazy { kosmos.keyguardRootViewModel }

    private val viewState = ViewStateAccessor()

    @Before
    fun setUp() {
        mSetFlagsRule.enableFlags(AConfigFlags.FLAG_KEYGUARD_BOTTOM_AREA_REFACTOR)
@@ -251,7 +253,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
    @Test
    fun alpha_idleOnHub_isZero() =
        testScope.runTest {
            val alpha by collectLastValue(underTest.alpha)
            val alpha by collectLastValue(underTest.alpha(viewState))

            // Hub transition state is idle with hub open.
            communalRepository.setTransitionState(
@@ -269,7 +271,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
    @Test
    fun alpha_transitionToHub_isZero() =
        testScope.runTest {
            val alpha by collectLastValue(underTest.alpha)
            val alpha by collectLastValue(underTest.alpha(viewState))

            keyguardTransitionRepository.sendTransitionSteps(
                from = KeyguardState.LOCKSCREEN,
@@ -283,7 +285,7 @@ class KeyguardRootViewModelTest : SysuiTestCase() {
    @Test
    fun alpha_transitionFromHubToLockscreen_isOne() =
        testScope.runTest {
            val alpha by collectLastValue(underTest.alpha)
            val alpha by collectLastValue(underTest.alpha(viewState))

            // Transition to the glanceable hub and back.
            keyguardTransitionRepository.sendTransitionSteps(
+6 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.BurnInParameters
import com.android.systemui.keyguard.ui.viewmodel.KeyguardRootViewModel
import com.android.systemui.keyguard.ui.viewmodel.OccludingAppDeviceEntryMessageViewModel
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.plugins.FalsingManager
import com.android.systemui.plugins.clocks.ClockController
@@ -112,6 +113,10 @@ object KeyguardRootViewBinder {
        }

        val burnInParams = MutableStateFlow(BurnInParameters())
        val viewState =
            ViewStateAccessor(
                alpha = { view.alpha },
            )

        val disposableHandle =
            view.repeatWhenAttached {
@@ -134,7 +139,7 @@ object KeyguardRootViewBinder {

                    if (keyguardBottomAreaRefactor()) {
                        launch {
                            viewModel.alpha.collect { alpha ->
                            viewModel.alpha(viewState).collect { alpha ->
                                view.alpha = alpha
                                childViews[statusViewId]?.alpha = alpha
                            }
+16 −12
Original line number Diff line number Diff line
@@ -60,18 +60,21 @@ constructor(
    private val deviceEntryInteractor: DeviceEntryInteractor,
    private val dozeParameters: DozeParameters,
    private val keyguardInteractor: KeyguardInteractor,
    communalInteractor: CommunalInteractor,
    private val communalInteractor: CommunalInteractor,
    keyguardTransitionInteractor: KeyguardTransitionInteractor,
    private val notificationsKeyguardInteractor: NotificationsKeyguardInteractor,
    aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
    lockscreenToGoneTransitionViewModel: LockscreenToGoneTransitionViewModel,
    alternateBouncerToGoneTransitionViewModel: AlternateBouncerToGoneTransitionViewModel,
    primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
    lockscreenToGlanceableHubTransitionViewModel: LockscreenToGlanceableHubTransitionViewModel,
    glanceableHubToLockscreenTransitionViewModel: GlanceableHubToLockscreenTransitionViewModel,
    screenOffAnimationController: ScreenOffAnimationController,
    private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
    private val lockscreenToGoneTransitionViewModel: LockscreenToGoneTransitionViewModel,
    private val alternateBouncerToGoneTransitionViewModel:
        AlternateBouncerToGoneTransitionViewModel,
    private val primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
    private val lockscreenToGlanceableHubTransitionViewModel:
        LockscreenToGlanceableHubTransitionViewModel,
    private val glanceableHubToLockscreenTransitionViewModel:
        GlanceableHubToLockscreenTransitionViewModel,
    private val screenOffAnimationController: ScreenOffAnimationController,
    private val aodBurnInViewModel: AodBurnInViewModel,
    aodAlphaViewModel: AodAlphaViewModel,
    private val aodAlphaViewModel: AodAlphaViewModel,
) {

    val burnInLayerVisibility: Flow<Int> =
@@ -101,8 +104,8 @@ constructor(
    val topClippingBounds: Flow<Int?> = keyguardInteractor.topClippingBounds

    /** An observable for the alpha level for the entire keyguard root view. */
    val alpha: Flow<Float> =
        combine(
    fun alpha(viewState: ViewStateAccessor): Flow<Float> {
        return combine(
                communalInteractor.isIdleOnCommunal,
                // The transitions are mutually exclusive, so they are safe to merge to get the last
                // value emitted by any of them. Do not add flows that cannot make this guarantee.
@@ -110,7 +113,7 @@ constructor(
                    aodAlphaViewModel.alpha,
                    lockscreenToGlanceableHubTransitionViewModel.keyguardAlpha,
                    glanceableHubToLockscreenTransitionViewModel.keyguardAlpha,
                    lockscreenToGoneTransitionViewModel.lockscreenAlpha,
                    lockscreenToGoneTransitionViewModel.lockscreenAlpha(viewState),
                    primaryBouncerToGoneTransitionViewModel.lockscreenAlpha,
                    alternateBouncerToGoneTransitionViewModel.lockscreenAlpha,
                )
@@ -125,6 +128,7 @@ constructor(
                }
            }
            .distinctUntilChanged()
    }

    /** Specific alpha value for elements visible during [KeyguardState.LOCKSCREEN] */
    val lockscreenStateAlpha: Flow<Float> = aodToLockscreenTransitionViewModel.lockscreenAlpha
+23 −2
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package com.android.systemui.keyguard.ui.viewmodel

import android.util.MathUtils
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow.FlowBuilder
import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
import javax.inject.Inject
import kotlin.time.Duration.Companion.milliseconds
@@ -37,7 +39,7 @@ constructor(
    animationFlow: KeyguardTransitionAnimationFlow,
) : DeviceEntryIconTransition {

    private val transitionAnimation =
    private val transitionAnimation: FlowBuilder =
        animationFlow.setup(
            duration = FromLockscreenTransitionInteractor.TO_GONE_DURATION,
            from = KeyguardState.LOCKSCREEN,
@@ -52,7 +54,26 @@ constructor(
            onCancel = { 1f },
        )

    val lockscreenAlpha: Flow<Float> = shortcutsAlpha
    fun lockscreenAlpha(viewState: ViewStateAccessor): Flow<Float> {
        var startAlpha: Float? = null
        return transitionAnimation.sharedFlow(
            duration = 200.milliseconds,
            onStep = {
                if (startAlpha == null) {
                    startAlpha = viewState.alpha()
                }
                MathUtils.lerp(startAlpha!!, 0f, it)
            },
            onFinish = {
                startAlpha = null
                0f
            },
            onCancel = {
                startAlpha = null
                1f
            },
        )
    }

    override val deviceEntryParentViewAlpha: Flow<Float> =
        transitionAnimation.immediatelyTransitionTo(0f)
+24 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.systemui.keyguard.ui.viewmodel

/** View-level state information to be shared between ui and viewmodel. */
data class ViewStateAccessor(
    val alpha: () -> Float = { 0f },
    val translationY: () -> Int = { 0 },
    val translationX: () -> Int = { 0 },
)
Loading