• 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.keyguard.ui.viewmodel
18 
19 import android.content.Context
20 import com.android.settingslib.Utils
21 import com.android.systemui.accessibility.domain.interactor.AccessibilityInteractor
22 import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor
23 import com.android.systemui.biometrics.domain.interactor.UdfpsOverlayInteractor
24 import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
25 import com.android.systemui.deviceentry.domain.interactor.DeviceEntryUdfpsInteractor
26 import com.android.systemui.keyguard.ui.view.DeviceEntryIconView
27 import com.android.systemui.scene.shared.flag.SceneContainerFlag
28 import com.android.systemui.shade.ShadeDisplayAware
29 import com.android.systemui.shared.recents.utilities.Utilities.clamp
30 import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager
31 import javax.inject.Inject
32 import kotlinx.coroutines.flow.Flow
33 import kotlinx.coroutines.flow.combine
34 import kotlinx.coroutines.flow.emptyFlow
35 import kotlinx.coroutines.flow.flatMapLatest
36 import kotlinx.coroutines.flow.flowOf
37 import kotlinx.coroutines.flow.map
38 import kotlinx.coroutines.flow.onStart
39 
40 /** Models the UI state for the UDFPS icon view in the alternate bouncer view. */
41 class AlternateBouncerUdfpsIconViewModel
42 @Inject
43 constructor(
44     @ShadeDisplayAware val context: Context,
45     @ShadeDisplayAware configurationInteractor: ConfigurationInteractor,
46     deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
47     deviceEntryBackgroundViewModel: DeviceEntryBackgroundViewModel,
48     fingerprintPropertyInteractor: FingerprintPropertyInteractor,
49     udfpsOverlayInteractor: UdfpsOverlayInteractor,
50     alternateBouncerViewModel: AlternateBouncerViewModel,
51     private val statusBarKeyguardViewManager: StatusBarKeyguardViewManager,
52     private val accessibilityInteractor: AccessibilityInteractor,
53 ) {
54     private val isSupported: Flow<Boolean> = deviceEntryUdfpsInteractor.isUdfpsSupported
55     val alpha: Flow<Float> =
56         alternateBouncerViewModel.transitionToAlternateBouncerProgress.map {
57             SceneContainerFlag.assertInLegacyMode()
58             clamp(it * 2f, 0f, 1f)
59         }
60 
61     /**
62      * UDFPS icon location in pixels for the current display and screen resolution, in natural
63      * orientation.
64      */
65     val iconLocation: Flow<IconLocation> =
66         isSupported.flatMapLatest { supportsUI ->
67             if (supportsUI) {
68                 fingerprintPropertyInteractor.udfpsSensorBounds.map { bounds ->
69                     IconLocation(
70                         left = bounds.left,
71                         top = bounds.top,
72                         right = bounds.right,
73                         bottom = bounds.bottom,
74                     )
75                 }
76             } else {
77                 emptyFlow()
78             }
79         }
80     val accessibilityDelegateHint: Flow<DeviceEntryIconView.AccessibilityHintType> =
81         accessibilityInteractor.isEnabled.flatMapLatest { touchExplorationEnabled ->
82             flowOf(
83                 if (touchExplorationEnabled) {
84                     DeviceEntryIconView.AccessibilityHintType.BOUNCER
85                 } else {
86                     DeviceEntryIconView.AccessibilityHintType.NONE
87                 }
88             )
89         }
90 
91     private val fgIconColor: Flow<Int> =
92         configurationInteractor.onAnyConfigurationChange
93             .map { Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary) }
94             .onStart {
95                 emit(Utils.getColorAttrDefaultColor(context, android.R.attr.textColorPrimary))
96             }
97     private val fgIconPadding: Flow<Int> = udfpsOverlayInteractor.iconPadding
98     val fgViewModel: Flow<DeviceEntryForegroundViewModel.ForegroundIconViewModel> =
99         combine(fgIconColor, fgIconPadding) { color, padding ->
100             DeviceEntryForegroundViewModel.ForegroundIconViewModel(
101                 type = DeviceEntryIconView.IconType.FINGERPRINT,
102                 useAodVariant = false,
103                 tint = color,
104                 padding = padding,
105             )
106         }
107 
108     fun onTapped() {
109         statusBarKeyguardViewManager.showPrimaryBouncer(
110             /* scrimmed */ true,
111             "AlternateBouncerUdfpsIconViewModel#onTapped",
112         )
113     }
114 
115     val bgColor: Flow<Int> = deviceEntryBackgroundViewModel.color
116     val bgAlpha: Flow<Float> = flowOf(1f)
117 
118     data class IconLocation(val left: Int, val top: Int, val right: Int, val bottom: Int) {
119         val width = right - left
120         val height = bottom - top
121     }
122 }
123