1 /*
2  * Copyright (C) 2020 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.controls.dagger
18 
19 import com.android.internal.widget.LockPatternUtils
20 import com.android.internal.widget.LockPatternUtils.StrongAuthTracker.STRONG_AUTH_REQUIRED_AFTER_BOOT
21 import com.android.systemui.controls.controller.ControlsController
22 import com.android.systemui.controls.controller.ControlsTileResourceConfiguration
23 import com.android.systemui.controls.controller.ControlsTileResourceConfigurationImpl
24 import com.android.systemui.controls.management.ControlsListingController
25 import com.android.systemui.controls.settings.ControlsSettingsRepository
26 import com.android.systemui.controls.ui.ControlsUiController
27 import com.android.systemui.dagger.SysUISingleton
28 import com.android.systemui.settings.UserTracker
29 import com.android.systemui.statusbar.policy.KeyguardStateController
30 import dagger.Lazy
31 import java.util.Optional
32 import javax.inject.Inject
33 import kotlinx.coroutines.flow.StateFlow
34 
35 /**
36  * Pseudo-component to inject into classes outside `com.android.systemui.controls`.
37  *
38  * If `featureEnabled` is false, all the optionals should be empty. The controllers will only be
39  * instantiated if `featureEnabled` is true. Can also be queried for the availability of controls.
40  */
41 @SysUISingleton
42 class ControlsComponent
43 @Inject
44 constructor(
45     @ControlsFeatureEnabled private val featureEnabled: Boolean,
46     lazyControlsController: Lazy<ControlsController>,
47     lazyControlsUiController: Lazy<ControlsUiController>,
48     lazyControlsListingController: Lazy<ControlsListingController>,
49     private val lockPatternUtils: LockPatternUtils,
50     private val keyguardStateController: KeyguardStateController,
51     private val userTracker: UserTracker,
52     controlsSettingsRepository: ControlsSettingsRepository,
53     optionalControlsTileResourceConfiguration: Optional<ControlsTileResourceConfiguration>
54 ) {
55 
56     private val controlsController: Optional<ControlsController> =
57         optionalIf(isEnabled(), lazyControlsController)
58     private val controlsUiController: Optional<ControlsUiController> =
59         optionalIf(isEnabled(), lazyControlsUiController)
60     private val controlsListingController: Optional<ControlsListingController> =
61         optionalIf(isEnabled(), lazyControlsListingController)
62 
63     val canShowWhileLockedSetting: StateFlow<Boolean> =
64         controlsSettingsRepository.canShowControlsInLockscreen
65 
66     private val controlsTileResourceConfiguration: ControlsTileResourceConfiguration =
67         optionalControlsTileResourceConfiguration.orElse(ControlsTileResourceConfigurationImpl())
68 
getControlsControllernull69     fun getControlsController(): Optional<ControlsController> = controlsController
70 
71     fun getControlsUiController(): Optional<ControlsUiController> = controlsUiController
72 
73     fun getControlsListingController(): Optional<ControlsListingController> =
74         controlsListingController
75 
76     /** @return true if controls are feature-enabled and the user has the setting enabled */
77     fun isEnabled() = featureEnabled
78 
79     /**
80      * Returns one of 3 states:
81      * * AVAILABLE - Controls can be made visible
82      * * AVAILABLE_AFTER_UNLOCK - Controls can be made visible only after device unlock
83      * * UNAVAILABLE - Controls are not enabled
84      */
85     fun getVisibility(): Visibility {
86         if (!isEnabled()) return Visibility.UNAVAILABLE
87         if (
88             lockPatternUtils.getStrongAuthForUser(userTracker.userHandle.identifier) ==
89                 STRONG_AUTH_REQUIRED_AFTER_BOOT
90         ) {
91             return Visibility.AVAILABLE_AFTER_UNLOCK
92         }
93         if (!canShowWhileLockedSetting.value && !keyguardStateController.isUnlocked()) {
94             return Visibility.AVAILABLE_AFTER_UNLOCK
95         }
96 
97         return Visibility.AVAILABLE
98     }
99 
100     enum class Visibility {
101         AVAILABLE,
102         AVAILABLE_AFTER_UNLOCK,
103         UNAVAILABLE
104     }
105 
getPackageNamenull106     fun getPackageName(): String? {
107         return controlsTileResourceConfiguration.getPackageName()
108     }
109 
getTileTitleIdnull110     fun getTileTitleId(): Int {
111         return controlsTileResourceConfiguration.getTileTitleId()
112     }
113 
getTileImageIdnull114     fun getTileImageId(): Int {
115         return controlsTileResourceConfiguration.getTileImageId()
116     }
117 
optionalIfnull118     private fun <T : Any> optionalIf(condition: Boolean, provider: Lazy<T>): Optional<T> =
119         if (condition) {
120             Optional.of(provider.get())
121         } else {
122             Optional.empty()
123         }
124 }
125