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