• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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