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.statusbar.ui.viewmodel 18 19 import com.android.systemui.utils.coroutines.flow.conflatedCallbackFlow 20 import com.android.systemui.dagger.SysUISingleton 21 import com.android.systemui.dagger.qualifiers.Application 22 import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor 23 import com.android.systemui.scene.domain.interactor.SceneInteractor 24 import com.android.systemui.scene.shared.flag.SceneContainerFlag 25 import com.android.systemui.scene.shared.model.Overlays 26 import com.android.systemui.scene.shared.model.Scenes 27 import com.android.systemui.statusbar.domain.interactor.KeyguardStatusBarInteractor 28 import com.android.systemui.statusbar.headsup.shared.StatusBarNoHunBehavior 29 import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationInteractor 30 import com.android.systemui.statusbar.policy.BatteryController 31 import com.android.systemui.statusbar.policy.BatteryController.BatteryStateChangeCallback 32 import javax.inject.Inject 33 import kotlinx.coroutines.CoroutineScope 34 import kotlinx.coroutines.channels.awaitClose 35 import kotlinx.coroutines.flow.Flow 36 import kotlinx.coroutines.flow.SharingStarted 37 import kotlinx.coroutines.flow.StateFlow 38 import kotlinx.coroutines.flow.combine 39 import kotlinx.coroutines.flow.flowOf 40 import kotlinx.coroutines.flow.map 41 import kotlinx.coroutines.flow.stateIn 42 43 /** 44 * A view model for the status bar displayed on keyguard (lockscreen). 45 * 46 * Note: This view model is for the status bar view as a whole. Certain icons may have their own 47 * individual view models, such as 48 * [com.android.systemui.statusbar.pipeline.wifi.ui.viewmodel.WifiViewModel] or 49 * [com.android.systemui.statusbar.pipeline.mobile.ui.viewmodel.MobileIconsViewModel]. 50 */ 51 @SysUISingleton 52 class KeyguardStatusBarViewModel 53 @Inject 54 constructor( 55 @Application scope: CoroutineScope, 56 headsUpNotificationInteractor: HeadsUpNotificationInteractor, 57 sceneInteractor: SceneInteractor, 58 keyguardInteractor: KeyguardInteractor, 59 keyguardStatusBarInteractor: KeyguardStatusBarInteractor, 60 batteryController: BatteryController, 61 ) { 62 63 private val showingHeadsUpStatusBar: Flow<Boolean> = 64 if (SceneContainerFlag.isEnabled && !StatusBarNoHunBehavior.isEnabled) { 65 headsUpNotificationInteractor.statusBarHeadsUpStatus.map { it.isPinned } 66 } else { 67 flowOf(false) 68 } 69 70 /** True if this view should be visible and false otherwise. */ 71 val isVisible: StateFlow<Boolean> = 72 combine( 73 sceneInteractor.currentScene, 74 sceneInteractor.currentOverlays, 75 keyguardInteractor.isDozing, 76 showingHeadsUpStatusBar, 77 ) { currentScene, currentOverlays, isDozing, showHeadsUpStatusBar -> 78 currentScene == Scenes.Lockscreen && 79 Overlays.NotificationsShade !in currentOverlays && 80 Overlays.QuickSettingsShade !in currentOverlays && 81 Overlays.Bouncer !in currentOverlays && 82 !isDozing && 83 !showHeadsUpStatusBar 84 } 85 .stateIn(scope, SharingStarted.WhileSubscribed(), false) 86 87 /** True if the device's battery is currently charging and false otherwise. */ 88 // Note: Never make this an eagerly-started state flow so that the callback is removed when the 89 // keyguard status bar view isn't attached. 90 val isBatteryCharging: Flow<Boolean> = conflatedCallbackFlow { 91 val callback = 92 object : BatteryStateChangeCallback { 93 override fun onBatteryLevelChanged( 94 level: Int, 95 pluggedIn: Boolean, 96 charging: Boolean, 97 ) { 98 trySend(charging) 99 } 100 } 101 batteryController.addCallback(callback) 102 awaitClose { batteryController.removeCallback(callback) } 103 } 104 105 /** True if we can show the user switcher on keyguard and false otherwise. */ 106 val isKeyguardUserSwitcherEnabled: Flow<Boolean> = 107 keyguardStatusBarInteractor.isKeyguardUserSwitcherEnabled 108 } 109