• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.systemui.keyguard.ui.viewmodel
18 
19 import com.android.app.animation.Interpolators.EMPHASIZED_DECELERATE
20 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
21 import com.android.systemui.dagger.SysUISingleton
22 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
23 import com.android.systemui.keyguard.domain.interactor.FromOccludedTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
24 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
25 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
26 import com.android.systemui.keyguard.shared.model.Edge
27 import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
28 import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
29 import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
30 import com.android.systemui.keyguard.ui.transitions.DeviceEntryIconTransition
31 import com.android.systemui.res.R
32 import com.android.systemui.shade.ShadeDisplayAware
33 import com.android.systemui.util.kotlin.pairwise
34 import javax.inject.Inject
35 import kotlin.time.Duration.Companion.milliseconds
36 import kotlinx.coroutines.flow.Flow
37 import kotlinx.coroutines.flow.filter
38 import kotlinx.coroutines.flow.flatMapLatest
39 import kotlinx.coroutines.flow.map
40 import kotlinx.coroutines.flow.merge
41 
42 /**
43  * Breaks down OCCLUDED->LOCKSCREEN transition into discrete steps for corresponding views to
44  * consume.
45  */
46 @SysUISingleton
47 class OccludedToLockscreenTransitionViewModel
48 @Inject
49 constructor(
50     deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
51     @ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
52     animationFlow: KeyguardTransitionAnimationFlow,
53     keyguardInteractor: KeyguardInteractor,
54     keyguardTransitionInteractor: KeyguardTransitionInteractor,
55 ) : DeviceEntryIconTransition {
56 
57     private val transitionAnimation =
58         animationFlow.setup(
59             duration = TO_LOCKSCREEN_DURATION,
60             edge = Edge.create(from = OCCLUDED, to = LOCKSCREEN),
61         )
62 
63     /** Lockscreen views y-translation */
64     val lockscreenTranslationY: Flow<Float> =
65         configurationInteractor
66             .dimensionPixelSize(R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y)
67             .flatMapLatest { translatePx ->
68                 transitionAnimation.sharedFlow(
69                     duration = TO_LOCKSCREEN_DURATION,
70                     onStep = { value -> -translatePx + value * translatePx },
71                     interpolator = EMPHASIZED_DECELERATE,
72                     onCancel = { 0f },
73                 )
74             }
75 
76     val shortcutsAlpha: Flow<Float> =
77         transitionAnimation.sharedFlow(
78             duration = 250.milliseconds,
79             onStep = { it },
80             onCancel = { 0f },
81         )
82 
83     /** Lockscreen views alpha */
84     val lockscreenAlpha: Flow<Float> =
85         merge(
86             transitionAnimation.sharedFlow(
87                 startTime = 233.milliseconds,
88                 duration = 250.milliseconds,
89                 onStep = { it },
90                 name = "OCCLUDED->LOCKSCREEN: lockscreenAlpha",
91             ),
92             // Required to fix a bug where the shade expands while lockscreenAlpha=1f, due to a call
93             // to setOccluded(false) triggering a reset() call in KeyguardViewMediator. The
94             // permanent solution is to only expand the shade once the keyguard transition from
95             // OCCLUDED starts, but that requires more refactoring of expansion amounts. For now,
96             // emit alpha = 0f for OCCLUDED -> LOCKSCREEN whenever isOccluded flips from true to
97             // false while currentState == OCCLUDED, so that alpha = 0f when that expansion occurs.
98             // TODO(b/332946323): Remove this once it's no longer needed.
99             keyguardInteractor.isKeyguardOccluded
100                 .pairwise()
101                 .filter { (wasOccluded, isOccluded) ->
102                     wasOccluded &&
103                         !isOccluded &&
104                         keyguardTransitionInteractor.getCurrentState() == OCCLUDED
105                 }
106                 .map { 0f },
107         )
108 
109     val deviceEntryBackgroundViewAlpha: Flow<Float> =
110         transitionAnimation.immediatelyTransitionTo(1f)
111 
112     override val deviceEntryParentViewAlpha: Flow<Float> =
113         transitionAnimation.sharedFlow(
114             startTime = 233.milliseconds,
115             duration = 250.milliseconds,
116             onStep = { it },
117             onCancel = { 1f },
118         )
119 }
120