1 /*
2  * Copyright (C) 2022 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.data.repository
18 
19 import android.graphics.Point
20 import android.hardware.biometrics.BiometricSourceType
21 import com.android.keyguard.KeyguardUpdateMonitor
22 import com.android.keyguard.KeyguardUpdateMonitorCallback
23 import com.android.systemui.biometrics.AuthController
24 import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
25 import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
26 import com.android.systemui.common.shared.model.Position
27 import com.android.systemui.dagger.SysUISingleton
28 import com.android.systemui.dagger.qualifiers.Application
29 import com.android.systemui.dagger.qualifiers.Main
30 import com.android.systemui.doze.DozeMachine
31 import com.android.systemui.doze.DozeTransitionCallback
32 import com.android.systemui.doze.DozeTransitionListener
33 import com.android.systemui.dreams.DreamOverlayCallbackController
34 import com.android.systemui.keyguard.ScreenLifecycle
35 import com.android.systemui.keyguard.WakefulnessLifecycle
36 import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
37 import com.android.systemui.keyguard.shared.model.BiometricUnlockSource
38 import com.android.systemui.keyguard.shared.model.DozeStateModel
39 import com.android.systemui.keyguard.shared.model.DozeTransitionModel
40 import com.android.systemui.keyguard.shared.model.KeyguardRootViewVisibilityState
41 import com.android.systemui.keyguard.shared.model.ScreenModel
42 import com.android.systemui.keyguard.shared.model.StatusBarState
43 import com.android.systemui.keyguard.shared.model.WakefulnessModel
44 import com.android.systemui.plugins.statusbar.StatusBarStateController
45 import com.android.systemui.statusbar.phone.BiometricUnlockController
46 import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
47 import com.android.systemui.statusbar.phone.DozeParameters
48 import com.android.systemui.statusbar.phone.KeyguardBypassController
49 import com.android.systemui.statusbar.policy.KeyguardStateController
50 import com.android.systemui.util.time.SystemClock
51 import javax.inject.Inject
52 import kotlinx.coroutines.CoroutineDispatcher
53 import kotlinx.coroutines.CoroutineScope
54 import kotlinx.coroutines.channels.awaitClose
55 import kotlinx.coroutines.flow.Flow
56 import kotlinx.coroutines.flow.MutableStateFlow
57 import kotlinx.coroutines.flow.SharingStarted
58 import kotlinx.coroutines.flow.StateFlow
59 import kotlinx.coroutines.flow.asStateFlow
60 import kotlinx.coroutines.flow.distinctUntilChanged
61 import kotlinx.coroutines.flow.flowOn
62 import kotlinx.coroutines.flow.stateIn
63 
64 /** Defines interface for classes that encapsulate application state for the keyguard. */
65 interface KeyguardRepository {
66     /**
67      * Observable for whether the bottom area UI should animate the transition out of doze state.
68      *
69      * To learn more about doze state, please see [isDozing].
70      */
71     val animateBottomAreaDozingTransitions: StateFlow<Boolean>
72 
73     /**
74      * Observable for the current amount of alpha that should be used for rendering the bottom area.
75      * UI.
76      */
77     val bottomAreaAlpha: StateFlow<Float>
78 
79     val keyguardAlpha: StateFlow<Float>
80 
81     /**
82      * Observable of the relative offset of the lock-screen clock from its natural position on the
83      * screen.
84      */
85     val clockPosition: StateFlow<Position>
86 
87     /**
88      * Observable for whether the keyguard is showing.
89      *
90      * Note: this is also `true` when the lock-screen is occluded with an `Activity` "above" it in
91      * the z-order (which is not really above the system UI window, but rather - the lock-screen
92      * becomes invisible to reveal the "occluding activity").
93      */
94     val isKeyguardShowing: Flow<Boolean>
95 
96     /** Is the keyguard in a unlocked state? */
97     val isKeyguardUnlocked: StateFlow<Boolean>
98 
99     /** Is an activity showing over the keyguard? */
100     val isKeyguardOccluded: Flow<Boolean>
101 
102     /**
103      * Observable for the signal that keyguard is about to go away.
104      *
105      * TODO(b/278086361): Remove once KEYGUARD_WM_STATE_REFACTOR flag is removed.
106      */
107     @Deprecated(
108         "Use KeyguardTransitionInteractor flows instead. The closest match for 'going " +
109             "away' is isInTransitionToState(GONE), but consider using more specific flows " +
110             "whenever possible."
111     )
112     val isKeyguardGoingAway: Flow<Boolean>
113 
114     /** Is the always-on display available to be used? */
115     val isAodAvailable: Flow<Boolean>
116 
117     /**
118      * Observable for whether we are in doze state.
119      *
120      * Doze state is the same as "Always on Display" or "AOD". It is the state that the device can
121      * enter to conserve battery when the device is locked and inactive.
122      *
123      * Note that it is possible for the system to be transitioning into doze while this flow still
124      * returns `false`. In order to account for that, observers should also use the
125      * [linearDozeAmount] flow to check if it's greater than `0`
126      */
127     val isDozing: StateFlow<Boolean>
128 
129     /**
130      * Observable for whether the device is dreaming.
131      *
132      * Dozing/AOD is a specific type of dream, but it is also possible for other non-systemui dreams
133      * to be active, such as screensavers.
134      */
135     val isDreaming: Flow<Boolean>
136 
137     /** Observable for whether the device is dreaming with an overlay, see [DreamOverlayService] */
138     val isDreamingWithOverlay: Flow<Boolean>
139 
140     /** Observable for device dreaming state and the active dream is hosted in lockscreen */
141     val isActiveDreamLockscreenHosted: StateFlow<Boolean>
142 
143     /**
144      * Observable for the amount of doze we are currently in.
145      *
146      * While in doze state, this amount can change - driving a cycle of animations designed to avoid
147      * pixel burn-in, etc.
148      *
149      * Also note that the value here may be greater than `0` while [isDozing] is still `false`, this
150      * happens during an animation/transition into doze mode. An observer would be wise to account
151      * for both flows if needed.
152      */
153     val linearDozeAmount: Flow<Float>
154 
155     /** Doze state information, as it transitions */
156     val dozeTransitionModel: Flow<DozeTransitionModel>
157 
158     val lastDozeTapToWakePosition: StateFlow<Point?>
159 
160     /** Observable for the [StatusBarState] */
161     val statusBarState: Flow<StatusBarState>
162 
163     /** Observable for device wake/sleep state */
164     val wakefulness: StateFlow<WakefulnessModel>
165 
166     /** Observable for device screen state */
167     val screenModel: StateFlow<ScreenModel>
168 
169     /** Observable for biometric unlock modes */
170     val biometricUnlockState: Flow<BiometricUnlockModel>
171 
172     /** Approximate location on the screen of the fingerprint sensor. */
173     val fingerprintSensorLocation: Flow<Point?>
174 
175     /** Approximate location on the screen of the face unlock sensor/front facing camera. */
176     val faceSensorLocation: Flow<Point?>
177 
178     /** Source of the most recent biometric unlock, such as fingerprint or face. */
179     val biometricUnlockSource: Flow<BiometricUnlockSource?>
180 
181     /** Whether quick settings or quick-quick settings is visible. */
182     val isQuickSettingsVisible: Flow<Boolean>
183 
184     /** Represents the current state of the KeyguardRootView visibility */
185     val keyguardRootViewVisibility: Flow<KeyguardRootViewVisibilityState>
186 
187     /** Receive an event for doze time tick */
188     val dozeTimeTick: Flow<Long>
189 
190     /**
191      * Returns `true` if the keyguard is showing; `false` otherwise.
192      *
193      * Note: this is also `true` when the lock-screen is occluded with an `Activity` "above" it in
194      * the z-order (which is not really above the system UI window, but rather - the lock-screen
195      * becomes invisible to reveal the "occluding activity").
196      */
197     fun isKeyguardShowing(): Boolean
198 
199     /**
200      * Whether lock screen bypass is enabled. When enabled, the lock screen will be automatically
201      * dismissed once the authentication challenge is completed. For example, completing a biometric
202      * authentication challenge via face unlock or fingerprint sensor can automatically bypass the
203      * lock screen.
204      */
205     fun isBypassEnabled(): Boolean
206 
207     /** Sets whether the bottom area UI should animate the transition out of doze state. */
208     fun setAnimateDozingTransitions(animate: Boolean)
209 
210     /** Sets the current amount of alpha that should be used for rendering the bottom area. */
211     @Deprecated("Deprecated as part of b/278057014") fun setBottomAreaAlpha(alpha: Float)
212 
213     /** Sets the current amount of alpha that should be used for rendering the keyguard. */
214     fun setKeyguardAlpha(alpha: Float)
215 
216     fun setKeyguardVisibility(
217         statusBarState: Int,
218         goingToFullShade: Boolean,
219         occlusionTransitionRunning: Boolean
220     )
221 
222     /**
223      * Sets the relative offset of the lock-screen clock from its natural position on the screen.
224      */
225     fun setClockPosition(x: Int, y: Int)
226 
227     /**
228      * Returns whether the keyguard bottom area should be constrained to the top of the lock icon
229      */
230     fun isUdfpsSupported(): Boolean
231 
232     /** Sets whether quick settings or quick-quick settings is visible. */
233     fun setQuickSettingsVisible(isVisible: Boolean)
234 
235     fun setLastDozeTapToWakePosition(position: Point)
236 
237     fun setIsDozing(isDozing: Boolean)
238 
239     fun setIsActiveDreamLockscreenHosted(isLockscreenHosted: Boolean)
240 
241     fun dozeTimeTick()
242 }
243 
244 /** Encapsulates application state for the keyguard. */
245 @SysUISingleton
246 class KeyguardRepositoryImpl
247 @Inject
248 constructor(
249     statusBarStateController: StatusBarStateController,
250     wakefulnessLifecycle: WakefulnessLifecycle,
251     screenLifecycle: ScreenLifecycle,
252     biometricUnlockController: BiometricUnlockController,
253     private val keyguardStateController: KeyguardStateController,
254     private val keyguardBypassController: KeyguardBypassController,
255     private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
256     private val dozeTransitionListener: DozeTransitionListener,
257     private val dozeParameters: DozeParameters,
258     private val authController: AuthController,
259     private val dreamOverlayCallbackController: DreamOverlayCallbackController,
260     @Main private val mainDispatcher: CoroutineDispatcher,
261     @Application private val scope: CoroutineScope,
262     private val systemClock: SystemClock,
263 ) : KeyguardRepository {
264     private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
265     override val animateBottomAreaDozingTransitions =
266         _animateBottomAreaDozingTransitions.asStateFlow()
267 
268     private val _bottomAreaAlpha = MutableStateFlow(1f)
269     override val bottomAreaAlpha = _bottomAreaAlpha.asStateFlow()
270 
271     private val _keyguardAlpha = MutableStateFlow(1f)
272     override val keyguardAlpha = _keyguardAlpha.asStateFlow()
273 
274     private val _clockPosition = MutableStateFlow(Position(0, 0))
275     override val clockPosition = _clockPosition.asStateFlow()
276 
277     override val isKeyguardShowing: Flow<Boolean> =
278         conflatedCallbackFlow {
279                 val callback =
280                     object : KeyguardStateController.Callback {
281                         override fun onKeyguardShowingChanged() {
282                             trySendWithFailureLogging(
283                                 keyguardStateController.isShowing,
284                                 TAG,
285                                 "updated isKeyguardShowing"
286                             )
287                         }
288                     }
289 
290                 keyguardStateController.addCallback(callback)
291                 // Adding the callback does not send an initial update.
292                 trySendWithFailureLogging(
293                     keyguardStateController.isShowing,
294                     TAG,
295                     "initial isKeyguardShowing"
296                 )
297 
298                 awaitClose { keyguardStateController.removeCallback(callback) }
299             }
300             .distinctUntilChanged()
301 
302     override val isAodAvailable: Flow<Boolean> =
303         conflatedCallbackFlow {
304                 val callback =
305                     DozeParameters.Callback {
306                         trySendWithFailureLogging(
307                             dozeParameters.alwaysOn,
308                             TAG,
309                             "updated isAodAvailable"
310                         )
311                     }
312 
313                 dozeParameters.addCallback(callback)
314                 // Adding the callback does not send an initial update.
315                 trySendWithFailureLogging(dozeParameters.alwaysOn, TAG, "initial isAodAvailable")
316 
317                 awaitClose { dozeParameters.removeCallback(callback) }
318             }
319             .distinctUntilChanged()
320 
321     override val isKeyguardOccluded: Flow<Boolean> =
322         conflatedCallbackFlow {
323                 val callback =
324                     object : KeyguardStateController.Callback {
325                         override fun onKeyguardShowingChanged() {
326                             trySendWithFailureLogging(
327                                 keyguardStateController.isOccluded,
328                                 TAG,
329                                 "updated isKeyguardOccluded"
330                             )
331                         }
332                     }
333 
334                 keyguardStateController.addCallback(callback)
335                 // Adding the callback does not send an initial update.
336                 trySendWithFailureLogging(
337                     keyguardStateController.isOccluded,
338                     TAG,
339                     "initial isKeyguardOccluded"
340                 )
341 
342                 awaitClose { keyguardStateController.removeCallback(callback) }
343             }
344             .distinctUntilChanged()
345 
346     override val isKeyguardUnlocked: StateFlow<Boolean> =
347         conflatedCallbackFlow {
348                 val callback =
349                     object : KeyguardStateController.Callback {
350                         override fun onUnlockedChanged() {
351                             trySendWithFailureLogging(
352                                 keyguardStateController.isUnlocked,
353                                 TAG,
354                                 "updated isKeyguardUnlocked due to onUnlockedChanged"
355                             )
356                         }
357 
358                         override fun onKeyguardShowingChanged() {
359                             trySendWithFailureLogging(
360                                 keyguardStateController.isUnlocked,
361                                 TAG,
362                                 "updated isKeyguardUnlocked due to onKeyguardShowingChanged"
363                             )
364                         }
365                     }
366 
367                 keyguardStateController.addCallback(callback)
368                 // Adding the callback does not send an initial update.
369                 trySendWithFailureLogging(
370                     keyguardStateController.isUnlocked,
371                     TAG,
372                     "initial isKeyguardUnlocked"
373                 )
374 
375                 awaitClose { keyguardStateController.removeCallback(callback) }
376             }
377             .distinctUntilChanged()
378             .stateIn(
379                 scope,
380                 SharingStarted.Eagerly,
381                 initialValue = false,
382             )
383 
384     override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
385         val callback =
386             object : KeyguardStateController.Callback {
387                 override fun onKeyguardGoingAwayChanged() {
388                     trySendWithFailureLogging(
389                         keyguardStateController.isKeyguardGoingAway,
390                         TAG,
391                         "updated isKeyguardGoingAway"
392                     )
393                 }
394             }
395 
396         keyguardStateController.addCallback(callback)
397         // Adding the callback does not send an initial update.
398         trySendWithFailureLogging(
399             keyguardStateController.isKeyguardGoingAway,
400             TAG,
401             "initial isKeyguardGoingAway"
402         )
403 
404         awaitClose { keyguardStateController.removeCallback(callback) }
405     }
406 
407     private val _isDozing = MutableStateFlow(statusBarStateController.isDozing)
408     override val isDozing: StateFlow<Boolean> = _isDozing.asStateFlow()
409 
410     override fun setIsDozing(isDozing: Boolean) {
411         _isDozing.value = isDozing
412     }
413 
414     private val _dozeTimeTick = MutableStateFlow<Long>(0)
415     override val dozeTimeTick = _dozeTimeTick.asStateFlow()
416 
417     override fun dozeTimeTick() {
418         _dozeTimeTick.value = systemClock.uptimeMillis()
419     }
420 
421     private val _lastDozeTapToWakePosition = MutableStateFlow<Point?>(null)
422     override val lastDozeTapToWakePosition = _lastDozeTapToWakePosition.asStateFlow()
423 
424     override fun setLastDozeTapToWakePosition(position: Point) {
425         _lastDozeTapToWakePosition.value = position
426     }
427 
428     override val isDreamingWithOverlay: Flow<Boolean> =
429         conflatedCallbackFlow {
430                 val callback =
431                     object : DreamOverlayCallbackController.Callback {
432                         override fun onStartDream() {
433                             trySendWithFailureLogging(true, TAG, "updated isDreamingWithOverlay")
434                         }
435                         override fun onWakeUp() {
436                             trySendWithFailureLogging(false, TAG, "updated isDreamingWithOverlay")
437                         }
438                     }
439                 dreamOverlayCallbackController.addCallback(callback)
440                 trySendWithFailureLogging(
441                     dreamOverlayCallbackController.isDreaming,
442                     TAG,
443                     "initial isDreamingWithOverlay",
444                 )
445 
446                 awaitClose { dreamOverlayCallbackController.removeCallback(callback) }
447             }
448             .distinctUntilChanged()
449 
450     override val isDreaming: Flow<Boolean> =
451         conflatedCallbackFlow {
452                 val callback =
453                     object : KeyguardUpdateMonitorCallback() {
454                         override fun onDreamingStateChanged(isDreaming: Boolean) {
455                             trySendWithFailureLogging(isDreaming, TAG, "updated isDreaming")
456                         }
457                     }
458                 keyguardUpdateMonitor.registerCallback(callback)
459                 trySendWithFailureLogging(
460                     keyguardUpdateMonitor.isDreaming,
461                     TAG,
462                     "initial isDreaming",
463                 )
464 
465                 awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
466             }
467             .flowOn(mainDispatcher)
468             .distinctUntilChanged()
469 
470     override val linearDozeAmount: Flow<Float> = conflatedCallbackFlow {
471         val callback =
472             object : StatusBarStateController.StateListener {
473                 override fun onDozeAmountChanged(linear: Float, eased: Float) {
474                     trySendWithFailureLogging(linear, TAG, "updated dozeAmount")
475                 }
476             }
477 
478         statusBarStateController.addCallback(callback)
479         trySendWithFailureLogging(statusBarStateController.dozeAmount, TAG, "initial dozeAmount")
480 
481         awaitClose { statusBarStateController.removeCallback(callback) }
482     }
483 
484     override val dozeTransitionModel: Flow<DozeTransitionModel> = conflatedCallbackFlow {
485         val callback =
486             object : DozeTransitionCallback {
487                 override fun onDozeTransition(
488                     oldState: DozeMachine.State,
489                     newState: DozeMachine.State
490                 ) {
491                     trySendWithFailureLogging(
492                         DozeTransitionModel(
493                             from = dozeMachineStateToModel(oldState),
494                             to = dozeMachineStateToModel(newState),
495                         ),
496                         TAG,
497                         "doze transition model"
498                     )
499                 }
500             }
501 
502         dozeTransitionListener.addCallback(callback)
503         trySendWithFailureLogging(
504             DozeTransitionModel(
505                 from = dozeMachineStateToModel(dozeTransitionListener.oldState),
506                 to = dozeMachineStateToModel(dozeTransitionListener.newState),
507             ),
508             TAG,
509             "initial doze transition model"
510         )
511 
512         awaitClose { dozeTransitionListener.removeCallback(callback) }
513     }
514 
515     override fun isKeyguardShowing(): Boolean {
516         return keyguardStateController.isShowing
517     }
518 
519     override fun isBypassEnabled(): Boolean {
520         return keyguardBypassController.bypassEnabled
521     }
522 
523     override val statusBarState: Flow<StatusBarState> = conflatedCallbackFlow {
524         val callback =
525             object : StatusBarStateController.StateListener {
526                 override fun onStateChanged(state: Int) {
527                     trySendWithFailureLogging(statusBarStateIntToObject(state), TAG, "state")
528                 }
529             }
530 
531         statusBarStateController.addCallback(callback)
532         trySendWithFailureLogging(
533             statusBarStateIntToObject(statusBarStateController.getState()),
534             TAG,
535             "initial state"
536         )
537 
538         awaitClose { statusBarStateController.removeCallback(callback) }
539     }
540 
541     override val biometricUnlockState: Flow<BiometricUnlockModel> = conflatedCallbackFlow {
542         fun dispatchUpdate() {
543             trySendWithFailureLogging(
544                 biometricModeIntToObject(biometricUnlockController.mode),
545                 TAG,
546                 "biometric mode"
547             )
548         }
549 
550         val callback =
551             object : BiometricUnlockController.BiometricUnlockEventsListener {
552                 override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
553                     dispatchUpdate()
554                 }
555 
556                 override fun onResetMode() {
557                     dispatchUpdate()
558                 }
559             }
560 
561         biometricUnlockController.addListener(callback)
562         dispatchUpdate()
563 
564         awaitClose { biometricUnlockController.removeListener(callback) }
565     }
566 
567     override val wakefulness: StateFlow<WakefulnessModel> =
568         conflatedCallbackFlow {
569                 val observer =
570                     object : WakefulnessLifecycle.Observer {
571                         override fun onStartedWakingUp() {
572                             dispatchNewState()
573                         }
574 
575                         override fun onFinishedWakingUp() {
576                             dispatchNewState()
577                         }
578 
579                         override fun onPostFinishedWakingUp() {
580                             dispatchNewState()
581                         }
582 
583                         override fun onStartedGoingToSleep() {
584                             dispatchNewState()
585                         }
586 
587                         override fun onFinishedGoingToSleep() {
588                             dispatchNewState()
589                         }
590 
591                         private fun dispatchNewState() {
592                             trySendWithFailureLogging(
593                                 WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
594                                 TAG,
595                                 "updated wakefulness state",
596                             )
597                         }
598                     }
599 
600                 wakefulnessLifecycle.addObserver(observer)
601                 awaitClose { wakefulnessLifecycle.removeObserver(observer) }
602             }
603             .stateIn(
604                 scope,
605                 // Use Eagerly so that we're always listening and never miss an event.
606                 SharingStarted.Eagerly,
607                 initialValue = WakefulnessModel.fromWakefulnessLifecycle(wakefulnessLifecycle),
608             )
609 
610     override val screenModel: StateFlow<ScreenModel> =
611         conflatedCallbackFlow {
612                 val observer =
613                     object : ScreenLifecycle.Observer {
614                         override fun onScreenTurningOn() {
615                             dispatchNewState()
616                         }
617                         override fun onScreenTurnedOn() {
618                             dispatchNewState()
619                         }
620                         override fun onScreenTurningOff() {
621                             dispatchNewState()
622                         }
623                         override fun onScreenTurnedOff() {
624                             dispatchNewState()
625                         }
626 
627                         private fun dispatchNewState() {
628                             trySendWithFailureLogging(
629                                 ScreenModel.fromScreenLifecycle(screenLifecycle),
630                                 TAG,
631                                 "updated screen state",
632                             )
633                         }
634                     }
635 
636                 screenLifecycle.addObserver(observer)
637                 awaitClose { screenLifecycle.removeObserver(observer) }
638             }
639             .stateIn(
640                 scope,
641                 // Use Eagerly so that we're always listening and never miss an event.
642                 SharingStarted.Eagerly,
643                 initialValue = ScreenModel.fromScreenLifecycle(screenLifecycle),
644             )
645 
646     override val fingerprintSensorLocation: Flow<Point?> = conflatedCallbackFlow {
647         fun sendFpLocation() {
648             trySendWithFailureLogging(
649                 authController.fingerprintSensorLocation,
650                 TAG,
651                 "AuthController.Callback#onFingerprintLocationChanged"
652             )
653         }
654 
655         val callback =
656             object : AuthController.Callback {
657                 override fun onFingerprintLocationChanged() {
658                     sendFpLocation()
659                 }
660             }
661 
662         authController.addCallback(callback)
663         sendFpLocation()
664 
665         awaitClose { authController.removeCallback(callback) }
666     }
667 
668     override val faceSensorLocation: Flow<Point?> = conflatedCallbackFlow {
669         fun sendSensorLocation() {
670             trySendWithFailureLogging(
671                 authController.faceSensorLocation,
672                 TAG,
673                 "AuthController.Callback#onFingerprintLocationChanged"
674             )
675         }
676 
677         val callback =
678             object : AuthController.Callback {
679                 override fun onFaceSensorLocationChanged() {
680                     sendSensorLocation()
681                 }
682             }
683 
684         authController.addCallback(callback)
685         sendSensorLocation()
686 
687         awaitClose { authController.removeCallback(callback) }
688     }
689 
690     override val biometricUnlockSource: Flow<BiometricUnlockSource?> = conflatedCallbackFlow {
691         val callback =
692             object : KeyguardUpdateMonitorCallback() {
693                 override fun onBiometricAuthenticated(
694                     userId: Int,
695                     biometricSourceType: BiometricSourceType?,
696                     isStrongBiometric: Boolean
697                 ) {
698                     trySendWithFailureLogging(
699                         BiometricUnlockSource.fromBiometricSourceType(biometricSourceType),
700                         TAG,
701                         "onBiometricAuthenticated"
702                     )
703                 }
704             }
705 
706         keyguardUpdateMonitor.registerCallback(callback)
707         trySendWithFailureLogging(null, TAG, "initial value")
708         awaitClose { keyguardUpdateMonitor.removeCallback(callback) }
709     }
710 
711     private val _isQuickSettingsVisible = MutableStateFlow(false)
712     override val isQuickSettingsVisible: Flow<Boolean> = _isQuickSettingsVisible.asStateFlow()
713 
714     private val _isActiveDreamLockscreenHosted = MutableStateFlow(false)
715     override val isActiveDreamLockscreenHosted = _isActiveDreamLockscreenHosted.asStateFlow()
716 
717     private val _keyguardRootViewVisibility =
718         MutableStateFlow(
719             KeyguardRootViewVisibilityState(
720                 com.android.systemui.statusbar.StatusBarState.SHADE,
721                 goingToFullShade = false,
722                 occlusionTransitionRunning = false,
723             )
724         )
725     override val keyguardRootViewVisibility: Flow<KeyguardRootViewVisibilityState> =
726         _keyguardRootViewVisibility.asStateFlow()
727 
728     override fun setAnimateDozingTransitions(animate: Boolean) {
729         _animateBottomAreaDozingTransitions.value = animate
730     }
731 
732     override fun setBottomAreaAlpha(alpha: Float) {
733         _bottomAreaAlpha.value = alpha
734     }
735 
736     override fun setKeyguardAlpha(alpha: Float) {
737         _keyguardAlpha.value = alpha
738     }
739 
740     override fun setKeyguardVisibility(
741         statusBarState: Int,
742         goingToFullShade: Boolean,
743         occlusionTransitionRunning: Boolean
744     ) {
745         _keyguardRootViewVisibility.value =
746             KeyguardRootViewVisibilityState(
747                 statusBarState,
748                 goingToFullShade,
749                 occlusionTransitionRunning
750             )
751     }
752 
753     override fun setClockPosition(x: Int, y: Int) {
754         _clockPosition.value = Position(x, y)
755     }
756 
757     override fun isUdfpsSupported(): Boolean = keyguardUpdateMonitor.isUdfpsSupported
758 
759     override fun setQuickSettingsVisible(isVisible: Boolean) {
760         _isQuickSettingsVisible.value = isVisible
761     }
762 
763     override fun setIsActiveDreamLockscreenHosted(isLockscreenHosted: Boolean) {
764         _isActiveDreamLockscreenHosted.value = isLockscreenHosted
765     }
766 
767     private fun statusBarStateIntToObject(value: Int): StatusBarState {
768         return when (value) {
769             0 -> StatusBarState.SHADE
770             1 -> StatusBarState.KEYGUARD
771             2 -> StatusBarState.SHADE_LOCKED
772             else -> throw IllegalArgumentException("Invalid StatusBarState value: $value")
773         }
774     }
775 
776     private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel {
777         return when (value) {
778             0 -> BiometricUnlockModel.NONE
779             1 -> BiometricUnlockModel.WAKE_AND_UNLOCK
780             2 -> BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
781             3 -> BiometricUnlockModel.SHOW_BOUNCER
782             4 -> BiometricUnlockModel.ONLY_WAKE
783             5 -> BiometricUnlockModel.UNLOCK_COLLAPSING
784             6 -> BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
785             7 -> BiometricUnlockModel.DISMISS_BOUNCER
786             else -> throw IllegalArgumentException("Invalid BiometricUnlockModel value: $value")
787         }
788     }
789 
790     private fun dozeMachineStateToModel(state: DozeMachine.State): DozeStateModel {
791         return when (state) {
792             DozeMachine.State.UNINITIALIZED -> DozeStateModel.UNINITIALIZED
793             DozeMachine.State.INITIALIZED -> DozeStateModel.INITIALIZED
794             DozeMachine.State.DOZE -> DozeStateModel.DOZE
795             DozeMachine.State.DOZE_SUSPEND_TRIGGERS -> DozeStateModel.DOZE_SUSPEND_TRIGGERS
796             DozeMachine.State.DOZE_AOD -> DozeStateModel.DOZE_AOD
797             DozeMachine.State.DOZE_REQUEST_PULSE -> DozeStateModel.DOZE_REQUEST_PULSE
798             DozeMachine.State.DOZE_PULSING -> DozeStateModel.DOZE_PULSING
799             DozeMachine.State.DOZE_PULSING_BRIGHT -> DozeStateModel.DOZE_PULSING_BRIGHT
800             DozeMachine.State.DOZE_PULSE_DONE -> DozeStateModel.DOZE_PULSE_DONE
801             DozeMachine.State.FINISH -> DozeStateModel.FINISH
802             DozeMachine.State.DOZE_AOD_PAUSED -> DozeStateModel.DOZE_AOD_PAUSED
803             DozeMachine.State.DOZE_AOD_PAUSING -> DozeStateModel.DOZE_AOD_PAUSING
804             DozeMachine.State.DOZE_AOD_DOCKED -> DozeStateModel.DOZE_AOD_DOCKED
805             else -> throw IllegalArgumentException("Invalid DozeMachine.State: state")
806         }
807     }
808 
809     companion object {
810         private const val TAG = "KeyguardRepositoryImpl"
811     }
812 }
813