1 /* 2 * 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.domain.interactor 18 19 import android.animation.ValueAnimator 20 import com.android.app.animation.Interpolators 21 import com.android.systemui.dagger.SysUISingleton 22 import com.android.systemui.dagger.qualifiers.Application 23 import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository 24 import com.android.systemui.keyguard.shared.model.KeyguardState 25 import com.android.systemui.keyguard.shared.model.WakefulnessState 26 import com.android.systemui.util.kotlin.Utils.Companion.toTriple 27 import com.android.systemui.util.kotlin.sample 28 import javax.inject.Inject 29 import kotlin.time.Duration.Companion.milliseconds 30 import kotlinx.coroutines.CoroutineScope 31 import kotlinx.coroutines.flow.combine 32 import kotlinx.coroutines.launch 33 34 @SysUISingleton 35 class FromGoneTransitionInteractor 36 @Inject 37 constructor( 38 override val transitionRepository: KeyguardTransitionRepository, 39 override val transitionInteractor: KeyguardTransitionInteractor, 40 @Application private val scope: CoroutineScope, 41 private val keyguardInteractor: KeyguardInteractor, 42 ) : 43 TransitionInteractor( 44 fromState = KeyguardState.GONE, 45 ) { 46 47 override fun start() { 48 listenForGoneToAodOrDozing() 49 listenForGoneToDreaming() 50 listenForGoneToLockscreen() 51 listenForGoneToDreamingLockscreenHosted() 52 } 53 54 // Primarily for when the user chooses to lock down the device 55 private fun listenForGoneToLockscreen() { 56 scope.launch { 57 keyguardInteractor.isKeyguardShowing 58 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair) 59 .collect { (isKeyguardShowing, lastStartedStep) -> 60 if (isKeyguardShowing && lastStartedStep.to == KeyguardState.GONE) { 61 startTransitionTo(KeyguardState.LOCKSCREEN) 62 } 63 } 64 } 65 } 66 67 private fun listenForGoneToDreamingLockscreenHosted() { 68 scope.launch { 69 keyguardInteractor.isActiveDreamLockscreenHosted 70 .sample(transitionInteractor.startedKeyguardTransitionStep, ::Pair) 71 .collect { (isActiveDreamLockscreenHosted, lastStartedStep) -> 72 if (isActiveDreamLockscreenHosted && lastStartedStep.to == KeyguardState.GONE) { 73 startTransitionTo(KeyguardState.DREAMING_LOCKSCREEN_HOSTED) 74 } 75 } 76 } 77 } 78 79 private fun listenForGoneToDreaming() { 80 scope.launch { 81 keyguardInteractor.isAbleToDream 82 .sample( 83 combine( 84 transitionInteractor.startedKeyguardTransitionStep, 85 keyguardInteractor.isActiveDreamLockscreenHosted, 86 ::Pair 87 ), 88 ::toTriple 89 ) 90 .collect { (isAbleToDream, lastStartedStep, isActiveDreamLockscreenHosted) -> 91 if ( 92 isAbleToDream && 93 lastStartedStep.to == KeyguardState.GONE && 94 !isActiveDreamLockscreenHosted 95 ) { 96 startTransitionTo(KeyguardState.DREAMING) 97 } 98 } 99 } 100 } 101 102 private fun listenForGoneToAodOrDozing() { 103 scope.launch { 104 keyguardInteractor.wakefulnessModel 105 .sample( 106 combine( 107 transitionInteractor.startedKeyguardTransitionStep, 108 keyguardInteractor.isAodAvailable, 109 ::Pair 110 ), 111 ::toTriple 112 ) 113 .collect { (wakefulnessState, lastStartedStep, isAodAvailable) -> 114 if ( 115 lastStartedStep.to == KeyguardState.GONE && 116 wakefulnessState.state == WakefulnessState.STARTING_TO_SLEEP 117 ) { 118 startTransitionTo( 119 if (isAodAvailable) KeyguardState.AOD else KeyguardState.DOZING 120 ) 121 } 122 } 123 } 124 } 125 126 override fun getDefaultAnimatorForTransitionsToState(toState: KeyguardState): ValueAnimator { 127 return ValueAnimator().apply { 128 interpolator = Interpolators.LINEAR 129 duration = 130 when (toState) { 131 KeyguardState.DREAMING -> TO_DREAMING_DURATION 132 else -> DEFAULT_DURATION 133 }.inWholeMilliseconds 134 } 135 } 136 companion object { 137 private val DEFAULT_DURATION = 500.milliseconds 138 val TO_DREAMING_DURATION = 933.milliseconds 139 } 140 } 141