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.shade.domain.interactor 18 19 import com.android.systemui.dagger.SysUISingleton 20 import com.android.systemui.dagger.qualifiers.Application 21 import com.android.systemui.keyguard.data.repository.KeyguardRepository 22 import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor 23 import com.android.systemui.keyguard.shared.model.DozeStateModel 24 import com.android.systemui.keyguard.shared.model.Edge 25 import com.android.systemui.keyguard.shared.model.KeyguardState 26 import com.android.systemui.power.domain.interactor.PowerInteractor 27 import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository 28 import com.android.systemui.statusbar.phone.DozeParameters 29 import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository 30 import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor 31 import com.android.systemui.user.domain.interactor.UserSwitcherInteractor 32 import javax.inject.Inject 33 import kotlinx.coroutines.CoroutineScope 34 import kotlinx.coroutines.flow.Flow 35 import kotlinx.coroutines.flow.SharingStarted 36 import kotlinx.coroutines.flow.StateFlow 37 import kotlinx.coroutines.flow.combine 38 import kotlinx.coroutines.flow.distinctUntilChanged 39 import kotlinx.coroutines.flow.map 40 import kotlinx.coroutines.flow.stateIn 41 42 /** The non-empty SceneInteractor implementation. */ 43 @SysUISingleton 44 class ShadeInteractorImpl 45 @Inject 46 constructor( 47 @Application val scope: CoroutineScope, 48 deviceProvisioningInteractor: DeviceProvisioningInteractor, 49 disableFlagsRepository: DisableFlagsRepository, 50 dozeParams: DozeParameters, 51 keyguardRepository: KeyguardRepository, 52 keyguardTransitionInteractor: KeyguardTransitionInteractor, 53 powerInteractor: PowerInteractor, 54 userSetupRepository: UserSetupRepository, 55 userSwitcherInteractor: UserSwitcherInteractor, 56 private val baseShadeInteractor: BaseShadeInteractor, 57 ) : ShadeInteractor, BaseShadeInteractor by baseShadeInteractor { 58 override val isShadeEnabled: StateFlow<Boolean> = 59 disableFlagsRepository.disableFlags 60 .map { isDisabledByFlags -> isDisabledByFlags.isShadeEnabled() } 61 .distinctUntilChanged() 62 .stateIn(scope, SharingStarted.Eagerly, initialValue = false) 63 64 override val isQsEnabled: StateFlow<Boolean> = 65 disableFlagsRepository.disableFlags 66 .map { it.isQuickSettingsEnabled() } 67 .stateIn(scope, SharingStarted.Eagerly, initialValue = false) 68 69 override val isAnyFullyExpanded: StateFlow<Boolean> = 70 anyExpansion 71 .map { it >= 1f } 72 .distinctUntilChanged() 73 .stateIn(scope, SharingStarted.Eagerly, initialValue = false) 74 75 override val isShadeFullyExpanded: Flow<Boolean> = 76 baseShadeInteractor.shadeExpansion.map { it >= 1f }.distinctUntilChanged() 77 78 override val isShadeFullyCollapsed: Flow<Boolean> = 79 baseShadeInteractor.shadeExpansion.map { it <= 0f }.distinctUntilChanged() 80 81 override val isUserInteracting: StateFlow<Boolean> = 82 combine(isUserInteractingWithShade, isUserInteractingWithQs) { shade, qs -> shade || qs } 83 .distinctUntilChanged() 84 .stateIn(scope, SharingStarted.Eagerly, false) 85 86 override val isShadeTouchable: Flow<Boolean> = 87 combine( 88 powerInteractor.isAsleep, 89 keyguardTransitionInteractor.isInTransition(Edge.create(to = KeyguardState.AOD)), 90 keyguardRepository.dozeTransitionModel.map { it.to == DozeStateModel.DOZE_PULSING }, 91 ) { isAsleep, goingToSleep, isPulsing -> 92 when { 93 // If the device is going to sleep, only accept touches if we're still 94 // animating 95 goingToSleep -> dozeParams.shouldControlScreenOff() 96 // If the device is asleep, only accept touches if there's a pulse 97 isAsleep -> isPulsing 98 else -> true 99 } 100 } 101 102 override val isExpandToQsEnabled: Flow<Boolean> = 103 combine( 104 disableFlagsRepository.disableFlags, 105 isShadeEnabled, 106 keyguardRepository.isDozing, 107 userSetupRepository.isUserSetUp, 108 deviceProvisioningInteractor.isDeviceProvisioned, 109 ) { disableFlags, isShadeEnabled, isDozing, isUserSetup, isDeviceProvisioned -> 110 isDeviceProvisioned && 111 // Disallow QS during setup if it's a simple user switcher. (The user intends to 112 // use the lock screen user switcher, QS is not needed.) 113 (isUserSetup || !userSwitcherInteractor.isSimpleUserSwitcher) && 114 isShadeEnabled && 115 disableFlags.isQuickSettingsEnabled() && 116 !isDozing 117 } 118 } 119