1 /* 2 * 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 18 package com.android.systemui.keyguard.domain.interactor 19 20 import android.animation.FloatEvaluator 21 import android.animation.IntEvaluator 22 import com.android.systemui.common.ui.data.repository.ConfigurationRepository 23 import com.android.systemui.dagger.SysUISingleton 24 import com.android.systemui.keyguard.shared.model.StatusBarState 25 import com.android.systemui.shade.data.repository.ShadeRepository 26 import com.android.systemui.statusbar.phone.SystemUIDialogManager 27 import com.android.systemui.statusbar.phone.hideAffordancesRequest 28 import javax.inject.Inject 29 import kotlinx.coroutines.ExperimentalCoroutinesApi 30 import kotlinx.coroutines.flow.Flow 31 import kotlinx.coroutines.flow.combine 32 import kotlinx.coroutines.flow.map 33 import kotlinx.coroutines.flow.onStart 34 35 /** Encapsulates business logic for transitions between UDFPS states on the keyguard. */ 36 @ExperimentalCoroutinesApi 37 @SysUISingleton 38 class UdfpsKeyguardInteractor 39 @Inject 40 constructor( 41 configRepo: ConfigurationRepository, 42 burnInInteractor: BurnInInteractor, 43 keyguardInteractor: KeyguardInteractor, 44 shadeRepository: ShadeRepository, 45 dialogManager: SystemUIDialogManager, 46 ) { 47 private val intEvaluator = IntEvaluator() 48 private val floatEvaluator = FloatEvaluator() 49 50 val dozeAmount = keyguardInteractor.dozeAmount 51 val scaleForResolution = configRepo.scaleForResolution 52 53 /** Burn-in offsets for the UDFPS view to mitigate burn-in on AOD. */ 54 val burnInOffsets: Flow<BurnInOffsets> = 55 combine( 56 keyguardInteractor.dozeAmount, 57 burnInInteractor.udfpsBurnInXOffset, 58 burnInInteractor.udfpsBurnInYOffset, 59 burnInInteractor.udfpsBurnInProgress 60 ) { dozeAmount, fullyDozingBurnInX, fullyDozingBurnInY, fullyDozingBurnInProgress -> 61 BurnInOffsets( 62 intEvaluator.evaluate(dozeAmount, 0, fullyDozingBurnInX), 63 intEvaluator.evaluate(dozeAmount, 0, fullyDozingBurnInY), 64 floatEvaluator.evaluate(dozeAmount, 0, fullyDozingBurnInProgress), 65 ) 66 } 67 68 val dialogHideAffordancesRequest: Flow<Boolean> = dialogManager.hideAffordancesRequest 69 70 val qsProgress: Flow<Float> = 71 shadeRepository.qsExpansion // swipe from top of LS 72 .map { (it * 2).coerceIn(0f, 1f) } 73 .onStart { emit(0f) } 74 75 val shadeExpansion: Flow<Float> = 76 combine( 77 shadeRepository.udfpsTransitionToFullShadeProgress, // swipe from middle of LS 78 keyguardInteractor.statusBarState, // quick swipe from middle of LS 79 ) { shadeProgress, statusBarState -> 80 if (statusBarState == StatusBarState.SHADE_LOCKED) { 81 1f 82 } else { 83 shadeProgress 84 } 85 } 86 .onStart { emit(0f) } 87 } 88 89 data class BurnInOffsets( 90 val burnInXOffset: Int, // current x burn in offset based on the aodTransitionAmount 91 val burnInYOffset: Int, // current y burn in offset based on the aodTransitionAmount 92 val burnInProgress: Float, // current progress based on the aodTransitionAmount 93 ) 94