1 /* <lambda>null2 * Copyright (C) 2023 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.domain.interactor 18 19 import android.animation.ValueAnimator 20 import com.android.systemui.dagger.SysUISingleton 21 import com.android.systemui.dagger.qualifiers.Application 22 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository 23 import com.android.systemui.keyguard.shared.model.KeyguardState 24 import com.android.systemui.keyguard.shared.model.WakefulnessState 25 import com.android.systemui.util.kotlin.Utils.Companion.toQuad 26 import com.android.systemui.util.kotlin.Utils.Companion.toQuint 27 import com.android.systemui.util.kotlin.sample 28 import com.android.wm.shell.animation.Interpolators 29 import javax.inject.Inject 30 import kotlinx.coroutines.CoroutineScope 31 import kotlinx.coroutines.delay 32 import kotlinx.coroutines.flow.combine 33 import kotlinx.coroutines.flow.onEach 34 import kotlinx.coroutines.launch 35 36 @SysUISingleton 37 class FromAlternateBouncerTransitionInteractor 38 @Inject 39 constructor( 40 override val transitionRepository: KeyguardTransitionRepository, 41 override val transitionInteractor: KeyguardTransitionInteractor, 42 @Application private val scope: CoroutineScope, 43 private val keyguardInteractor: KeyguardInteractor, 44 ) : 45 TransitionInteractor( 46 fromState = KeyguardState.ALTERNATE_BOUNCER, 47 ) { 48 49 override fun start() { 50 listenForAlternateBouncerToGone() 51 listenForAlternateBouncerToLockscreenAodOrDozing() 52 listenForAlternateBouncerToPrimaryBouncer() 53 } 54 55 private fun listenForAlternateBouncerToLockscreenAodOrDozing() { 56 scope.launch { 57 keyguardInteractor.alternateBouncerShowing 58 // Add a slight delay, as alternateBouncer and primaryBouncer showing event changes 59 // will arrive with a small gap in time. This prevents a transition to LOCKSCREEN 60 // happening prematurely. 61 .onEach { delay(50) } 62 .sample( 63 combine( 64 keyguardInteractor.primaryBouncerShowing, 65 transitionInteractor.startedKeyguardTransitionStep, 66 keyguardInteractor.wakefulnessModel, 67 keyguardInteractor.isAodAvailable, 68 ::toQuad 69 ), 70 ::toQuint 71 ) 72 .collect { 73 ( 74 isAlternateBouncerShowing, 75 isPrimaryBouncerShowing, 76 lastStartedTransitionStep, 77 wakefulnessState, 78 isAodAvailable) -> 79 if ( 80 !isAlternateBouncerShowing && 81 !isPrimaryBouncerShowing && 82 lastStartedTransitionStep.to == KeyguardState.ALTERNATE_BOUNCER 83 ) { 84 val to = 85 if ( 86 wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP || 87 wakefulnessState.state == WakefulnessState.ASLEEP 88 ) { 89 if (isAodAvailable) { 90 KeyguardState.AOD 91 } else { 92 KeyguardState.DOZING 93 } 94 } else { 95 KeyguardState.LOCKSCREEN 96 } 97 startTransitionTo(to) 98 } 99 } 100 } 101 } 102 103 private fun listenForAlternateBouncerToGone() { 104 scope.launch { 105 keyguardInteractor.isKeyguardGoingAway 106 .sample(transitionInteractor.finishedKeyguardState, ::Pair) 107 .collect { (isKeyguardGoingAway, keyguardState) -> 108 if (isKeyguardGoingAway && keyguardState == KeyguardState.ALTERNATE_BOUNCER) { 109 startTransitionTo(KeyguardState.GONE) 110 } 111 } 112 } 113 } 114 115 private fun listenForAlternateBouncerToPrimaryBouncer() { 116 scope.launch { 117 keyguardInteractor.primaryBouncerShowing 118 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair) 119 .collect { (isPrimaryBouncerShowing, startedKeyguardState) -> 120 if ( 121 isPrimaryBouncerShowing && 122 startedKeyguardState.to == KeyguardState.ALTERNATE_BOUNCER 123 ) { 124 startTransitionTo(KeyguardState.PRIMARY_BOUNCER) 125 } 126 } 127 } 128 } 129 130 override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { 131 return ValueAnimator().apply { 132 interpolator = Interpolators.LINEAR 133 duration = TRANSITION_DURATION_MS 134 } 135 } 136 137 companion object { 138 private const val TRANSITION_DURATION_MS = 300L 139 } 140 } 141