Merge changes Iaef3c67b,I983277fd into tm-qpr-dev

* changes:
  Bouncer - Fix default alignment
  Transitions - Add more source data, refine existing transitions
This commit is contained in:
Matt Pietal
2022-11-03 11:42:13 +00:00
committed by Android (Google) Code Review
21 changed files with 473 additions and 66 deletions

View File

@@ -228,7 +228,7 @@ open class ClockEventController @Inject constructor(
listenForDozing(this) listenForDozing(this)
if (featureFlags.isEnabled(DOZING_MIGRATION_1)) { if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
listenForDozeAmountTransition(this) listenForDozeAmountTransition(this)
listenForGoneToAodTransition(this) listenForAnyStateToAodTransition(this)
} else { } else {
listenForDozeAmount(this) listenForDozeAmount(this)
} }
@@ -286,10 +286,10 @@ open class ClockEventController @Inject constructor(
* dozing. * dozing.
*/ */
@VisibleForTesting @VisibleForTesting
internal fun listenForGoneToAodTransition(scope: CoroutineScope): Job { internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
return scope.launch { return scope.launch {
keyguardTransitionInteractor.goneToAodTransition.filter { keyguardTransitionInteractor.anyStateToAodTransition.filter {
it.transitionState == TransitionState.STARTED it.transitionState == TransitionState.FINISHED
}.collect { }.collect {
dozeAmount = 1f dozeAmount = 1f
clock?.animations?.doze(dozeAmount) clock?.animations?.doze(dozeAmount)

View File

@@ -106,8 +106,9 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
static final int USER_TYPE_WORK_PROFILE = 2; static final int USER_TYPE_WORK_PROFILE = 2;
static final int USER_TYPE_SECONDARY_USER = 3; static final int USER_TYPE_SECONDARY_USER = 3;
@IntDef({MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER}) @IntDef({MODE_UNINITIALIZED, MODE_DEFAULT, MODE_ONE_HANDED, MODE_USER_SWITCHER})
public @interface Mode {} public @interface Mode {}
static final int MODE_UNINITIALIZED = -1;
static final int MODE_DEFAULT = 0; static final int MODE_DEFAULT = 0;
static final int MODE_ONE_HANDED = 1; static final int MODE_ONE_HANDED = 1;
static final int MODE_USER_SWITCHER = 2; static final int MODE_USER_SWITCHER = 2;
@@ -154,7 +155,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private boolean mDisappearAnimRunning; private boolean mDisappearAnimRunning;
private SwipeListener mSwipeListener; private SwipeListener mSwipeListener;
private ViewMode mViewMode = new DefaultViewMode(); private ViewMode mViewMode = new DefaultViewMode();
private @Mode int mCurrentMode = MODE_DEFAULT; /*
* Using MODE_UNINITIALIZED to mean the view mode is set to DefaultViewMode, but init() has not
* yet been called on it. This will happen when the ViewController is initialized.
*/
private @Mode int mCurrentMode = MODE_UNINITIALIZED;
private int mWidth = -1; private int mWidth = -1;
private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback = private final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
@@ -347,6 +352,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
private String modeToString(@Mode int mode) { private String modeToString(@Mode int mode) {
switch (mode) { switch (mode) {
case MODE_UNINITIALIZED:
return "Uninitialized";
case MODE_DEFAULT: case MODE_DEFAULT:
return "Default"; return "Default";
case MODE_ONE_HANDED: case MODE_ONE_HANDED:

View File

@@ -318,6 +318,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
@Override @Override
public void onInit() { public void onInit() {
mSecurityViewFlipperController.init(); mSecurityViewFlipperController.init();
configureMode();
} }
@Override @Override

View File

@@ -23,9 +23,12 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost import com.android.systemui.doze.DozeHost
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose import kotlinx.coroutines.channels.awaitClose
@@ -65,6 +68,9 @@ interface KeyguardRepository {
*/ */
val isKeyguardShowing: Flow<Boolean> val isKeyguardShowing: Flow<Boolean>
/** Observable for whether the bouncer is showing. */
val isBouncerShowing: Flow<Boolean>
/** /**
* Observable for whether we are in doze state. * Observable for whether we are in doze state.
* *
@@ -95,6 +101,9 @@ interface KeyguardRepository {
/** Observable for device wake/sleep state */ /** Observable for device wake/sleep state */
val wakefulnessState: Flow<WakefulnessModel> val wakefulnessState: Flow<WakefulnessModel>
/** Observable for biometric unlock modes */
val biometricUnlockState: Flow<BiometricUnlockModel>
/** /**
* Returns `true` if the keyguard is showing; `false` otherwise. * Returns `true` if the keyguard is showing; `false` otherwise.
* *
@@ -125,6 +134,7 @@ constructor(
private val keyguardStateController: KeyguardStateController, private val keyguardStateController: KeyguardStateController,
dozeHost: DozeHost, dozeHost: DozeHost,
wakefulnessLifecycle: WakefulnessLifecycle, wakefulnessLifecycle: WakefulnessLifecycle,
biometricUnlockController: BiometricUnlockController,
) : KeyguardRepository { ) : KeyguardRepository {
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false) private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
override val animateBottomAreaDozingTransitions = override val animateBottomAreaDozingTransitions =
@@ -159,6 +169,29 @@ constructor(
awaitClose { keyguardStateController.removeCallback(callback) } awaitClose { keyguardStateController.removeCallback(callback) }
} }
override val isBouncerShowing: Flow<Boolean> = conflatedCallbackFlow {
val callback =
object : KeyguardStateController.Callback {
override fun onBouncerShowingChanged() {
trySendWithFailureLogging(
keyguardStateController.isBouncerShowing,
TAG,
"updated isBouncerShowing"
)
}
}
keyguardStateController.addCallback(callback)
// Adding the callback does not send an initial update.
trySendWithFailureLogging(
keyguardStateController.isBouncerShowing,
TAG,
"initial isBouncerShowing"
)
awaitClose { keyguardStateController.removeCallback(callback) }
}
override val isDozing: Flow<Boolean> = override val isDozing: Flow<Boolean> =
conflatedCallbackFlow { conflatedCallbackFlow {
val callback = val callback =
@@ -248,6 +281,24 @@ constructor(
awaitClose { wakefulnessLifecycle.removeObserver(callback) } awaitClose { wakefulnessLifecycle.removeObserver(callback) }
} }
override val biometricUnlockState: Flow<BiometricUnlockModel> = conflatedCallbackFlow {
val callback =
object : BiometricUnlockController.BiometricModeListener {
override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
trySendWithFailureLogging(biometricModeIntToObject(mode), TAG, "biometric mode")
}
}
biometricUnlockController.addBiometricModeListener(callback)
trySendWithFailureLogging(
biometricModeIntToObject(biometricUnlockController.getMode()),
TAG,
"initial biometric mode"
)
awaitClose { biometricUnlockController.removeBiometricModeListener(callback) }
}
override fun setAnimateDozingTransitions(animate: Boolean) { override fun setAnimateDozingTransitions(animate: Boolean) {
_animateBottomAreaDozingTransitions.value = animate _animateBottomAreaDozingTransitions.value = animate
} }
@@ -279,6 +330,20 @@ constructor(
} }
} }
private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel {
return when (value) {
0 -> BiometricUnlockModel.NONE
1 -> BiometricUnlockModel.WAKE_AND_UNLOCK
2 -> BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
3 -> BiometricUnlockModel.SHOW_BOUNCER
4 -> BiometricUnlockModel.ONLY_WAKE
5 -> BiometricUnlockModel.UNLOCK_COLLAPSING
6 -> BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
7 -> BiometricUnlockModel.DISMISS_BOUNCER
else -> throw IllegalArgumentException("Invalid BiometricUnlockModel value: $value")
}
}
companion object { companion object {
private const val TAG = "KeyguardRepositoryImpl" private const val TAG = "KeyguardRepositoryImpl"
} }

View File

@@ -0,0 +1,81 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch
@SysUISingleton
class AodToGoneTransitionInteractor
@Inject
constructor(
@Application private val scope: CoroutineScope,
private val keyguardInteractor: KeyguardInteractor,
private val keyguardTransitionRepository: KeyguardTransitionRepository,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor("AOD->GONE") {
private val wakeAndUnlockModes =
setOf(WAKE_AND_UNLOCK, WAKE_AND_UNLOCK_FROM_DREAM, WAKE_AND_UNLOCK_PULSING)
override fun start() {
scope.launch {
keyguardInteractor.biometricUnlockState
.sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
.collect { pair ->
val (biometricUnlockState, keyguardState) = pair
if (
keyguardState == KeyguardState.AOD &&
wakeAndUnlockModes.contains(biometricUnlockState)
) {
keyguardTransitionRepository.startTransition(
TransitionInfo(
name,
KeyguardState.AOD,
KeyguardState.GONE,
getAnimator(),
)
)
}
}
}
}
private fun getAnimator(): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
setDuration(TRANSITION_DURATION_MS)
}
}
companion object {
private const val TRANSITION_DURATION_MS = 500L
}
}

View File

@@ -19,6 +19,8 @@ package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.keyguard.shared.model.WakefulnessModel
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -39,10 +41,19 @@ constructor(
val dozeAmount: Flow<Float> = repository.dozeAmount val dozeAmount: Flow<Float> = repository.dozeAmount
/** Whether the system is in doze mode. */ /** Whether the system is in doze mode. */
val isDozing: Flow<Boolean> = repository.isDozing val isDozing: Flow<Boolean> = repository.isDozing
/** Whether the keyguard is showing to not. */ /** Whether the keyguard is showing or not. */
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
/** Whether the bouncer is showing or not. */
val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
/** The device wake/sleep state */ /** The device wake/sleep state */
val wakefulnessState: Flow<WakefulnessModel> = repository.wakefulnessState val wakefulnessState: Flow<WakefulnessModel> = repository.wakefulnessState
/** Observable for the [StatusBarState] */
val statusBarState: Flow<StatusBarState> = repository.statusBarState
/**
* Observable for [BiometricUnlockModel] when biometrics like face or any fingerprint (rear,
* side, under display) is used to unlock the device.
*/
val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState
fun isKeyguardShowing(): Boolean { fun isKeyguardShowing(): Boolean {
return repository.isKeyguardShowing() return repository.isKeyguardShowing()

View File

@@ -41,11 +41,13 @@ constructor(
} }
scope.launch { scope.launch {
interactor.finishedKeyguardState.collect { logger.i("Finished transition to", it) } interactor.finishedKeyguardTransitionStep.collect {
logger.i("Finished transition", it)
}
} }
scope.launch { scope.launch {
interactor.startedKeyguardState.collect { logger.i("Started transition to", it) } interactor.startedKeyguardTransitionStep.collect { logger.i("Started transition", it) }
} }
} }
} }

View File

@@ -41,6 +41,7 @@ constructor(
is AodLockscreenTransitionInteractor -> Log.d(TAG, "Started $it") is AodLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
is GoneAodTransitionInteractor -> Log.d(TAG, "Started $it") is GoneAodTransitionInteractor -> Log.d(TAG, "Started $it")
is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it") is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it")
is AodToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
} }
it.start() it.start()
} }

View File

@@ -21,7 +21,6 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.GONE
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep import com.android.systemui.keyguard.shared.model.TransitionStep
@@ -44,8 +43,9 @@ constructor(
/** LOCKSCREEN->AOD transition information. */ /** LOCKSCREEN->AOD transition information. */
val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD) val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
/** GONE->AOD information. */ /** (any)->AOD transition information */
val goneToAodTransition: Flow<TransitionStep> = repository.transition(GONE, AOD) val anyStateToAodTransition: Flow<TransitionStep> =
repository.transitions.filter { step -> step.to == KeyguardState.AOD }
/** /**
* AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <-> * AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
@@ -57,15 +57,15 @@ constructor(
lockscreenToAodTransition, lockscreenToAodTransition,
) )
/* The last [TransitionStep] with a [TransitionState] of FINISHED */
val finishedKeyguardTransitionStep: Flow<TransitionStep> =
repository.transitions.filter { step -> step.transitionState == TransitionState.FINISHED }
/* The last completed [KeyguardState] transition */ /* The last completed [KeyguardState] transition */
val finishedKeyguardState: Flow<KeyguardState> = val finishedKeyguardState: Flow<KeyguardState> =
repository.transitions finishedKeyguardTransitionStep.map { step -> step.to }
.filter { step -> step.transitionState == TransitionState.FINISHED }
.map { step -> step.to }
/* The last started [KeyguardState] transition */ /* The last [TransitionStep] with a [TransitionState] of STARTED */
val startedKeyguardState: Flow<KeyguardState> = val startedKeyguardTransitionStep: Flow<TransitionStep> =
repository.transitions repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
.filter { step -> step.transitionState == TransitionState.STARTED }
.map { step -> step.to }
} }

View File

@@ -16,14 +16,16 @@
package com.android.systemui.keyguard.domain.interactor package com.android.systemui.keyguard.domain.interactor
import android.animation.ValueAnimator
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED import com.android.systemui.keyguard.shared.model.StatusBarState.SHADE_LOCKED
import com.android.systemui.keyguard.shared.model.TransitionInfo import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.TransitionState import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.shade.data.repository.ShadeRepository import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.util.kotlin.sample import com.android.systemui.util.kotlin.sample
import java.util.UUID import java.util.UUID
@@ -38,7 +40,7 @@ class LockscreenBouncerTransitionInteractor
@Inject @Inject
constructor( constructor(
@Application private val scope: CoroutineScope, @Application private val scope: CoroutineScope,
private val keyguardRepository: KeyguardRepository, private val keyguardInteractor: KeyguardInteractor,
private val shadeRepository: ShadeRepository, private val shadeRepository: ShadeRepository,
private val keyguardTransitionRepository: KeyguardTransitionRepository, private val keyguardTransitionRepository: KeyguardTransitionRepository,
private val keyguardTransitionInteractor: KeyguardTransitionInteractor private val keyguardTransitionInteractor: KeyguardTransitionInteractor
@@ -47,12 +49,47 @@ constructor(
private var transitionId: UUID? = null private var transitionId: UUID? = null
override fun start() { override fun start() {
listenForDraggingUpToBouncer()
listenForBouncerHiding()
}
private fun listenForBouncerHiding() {
scope.launch {
keyguardInteractor.isBouncerShowing
.sample(keyguardInteractor.wakefulnessState, { a, b -> Pair(a, b) })
.collect { pair ->
val (isBouncerShowing, wakefulnessState) = pair
if (!isBouncerShowing) {
val to =
if (
wakefulnessState == WakefulnessModel.STARTING_TO_SLEEP ||
wakefulnessState == WakefulnessModel.ASLEEP
) {
KeyguardState.AOD
} else {
KeyguardState.LOCKSCREEN
}
keyguardTransitionRepository.startTransition(
TransitionInfo(
ownerName = name,
from = KeyguardState.BOUNCER,
to = to,
animator = getAnimator(),
)
)
}
}
}
}
/* Starts transitions when manually dragging up the bouncer from the lockscreen. */
private fun listenForDraggingUpToBouncer() {
scope.launch { scope.launch {
shadeRepository.shadeModel shadeRepository.shadeModel
.sample( .sample(
combine( combine(
keyguardTransitionInteractor.finishedKeyguardState, keyguardTransitionInteractor.finishedKeyguardState,
keyguardRepository.statusBarState, keyguardInteractor.statusBarState,
) { keyguardState, statusBarState -> ) { keyguardState, statusBarState ->
Pair(keyguardState, statusBarState) Pair(keyguardState, statusBarState)
}, },
@@ -100,4 +137,15 @@ constructor(
} }
} }
} }
private fun getAnimator(): ValueAnimator {
return ValueAnimator().apply {
setInterpolator(Interpolators.LINEAR)
setDuration(TRANSITION_DURATION_MS)
}
}
companion object {
private const val TRANSITION_DURATION_MS = 300L
}
} }

View File

@@ -42,6 +42,8 @@ abstract class StartKeyguardTransitionModule {
@Binds @IntoSet abstract fun goneAod(impl: GoneAodTransitionInteractor): TransitionInteractor @Binds @IntoSet abstract fun goneAod(impl: GoneAodTransitionInteractor): TransitionInteractor
@Binds @IntoSet abstract fun aodGone(impl: AodToGoneTransitionInteractor): TransitionInteractor
@Binds @Binds
@IntoSet @IntoSet
abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor

View File

@@ -0,0 +1,50 @@
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.systemui.keyguard.shared.model
/** Model device wakefulness states. */
enum class BiometricUnlockModel {
/** Mode in which we don't need to wake up the device when we authenticate. */
NONE,
/**
* Mode in which we wake up the device, and directly dismiss Keyguard. Active when we acquire a
* fingerprint while the screen is off and the device was sleeping.
*/
WAKE_AND_UNLOCK,
/**
* Mode in which we wake the device up, and fade out the Keyguard contents because they were
* already visible while pulsing in doze mode.
*/
WAKE_AND_UNLOCK_PULSING,
/**
* Mode in which we wake up the device, but play the normal dismiss animation. Active when we
* acquire a fingerprint pulsing in doze mode.
*/
SHOW_BOUNCER,
/**
* Mode in which we only wake up the device, and keyguard was not showing when we authenticated.
*/
ONLY_WAKE,
/**
* Mode in which fingerprint unlocks the device or passive auth (ie face auth) unlocks the
* device while being requested when keyguard is occluded or showing.
*/
UNLOCK_COLLAPSING,
/** When bouncer is visible and will be dismissed. */
DISMISS_BOUNCER,
/** Mode in which fingerprint wakes and unlocks the device from a dream. */
WAKE_AND_UNLOCK_FROM_DREAM,
}

View File

@@ -21,10 +21,11 @@ data class TransitionStep(
val to: KeyguardState = KeyguardState.NONE, val to: KeyguardState = KeyguardState.NONE,
val value: Float = 0f, // constrained [0.0, 1.0] val value: Float = 0f, // constrained [0.0, 1.0]
val transitionState: TransitionState = TransitionState.FINISHED, val transitionState: TransitionState = TransitionState.FINISHED,
val ownerName: String = "",
) { ) {
constructor( constructor(
info: TransitionInfo, info: TransitionInfo,
value: Float, value: Float,
transitionState: TransitionState, transitionState: TransitionState,
) : this(info.from, info.to, value, transitionState) ) : this(info.from, info.to, value, transitionState, info.ownerName)
} }

View File

@@ -67,8 +67,10 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.HashSet;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
@@ -167,7 +169,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
private PendingAuthenticated mPendingAuthenticated = null; private PendingAuthenticated mPendingAuthenticated = null;
private boolean mHasScreenTurnedOnSinceAuthenticating; private boolean mHasScreenTurnedOnSinceAuthenticating;
private boolean mFadedAwayAfterWakeAndUnlock; private boolean mFadedAwayAfterWakeAndUnlock;
private BiometricModeListener mBiometricModeListener; private Set<BiometricModeListener> mBiometricModeListeners = new HashSet<>();
private final MetricsLogger mMetricsLogger; private final MetricsLogger mMetricsLogger;
private final AuthController mAuthController; private final AuthController mAuthController;
@@ -314,9 +316,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mKeyguardViewController = keyguardViewController; mKeyguardViewController = keyguardViewController;
} }
/** Sets a {@link BiometricModeListener}. */ /** Adds a {@link BiometricModeListener}. */
public void setBiometricModeListener(BiometricModeListener biometricModeListener) { public void addBiometricModeListener(BiometricModeListener listener) {
mBiometricModeListener = biometricModeListener; mBiometricModeListeners.add(listener);
}
/** Removes a {@link BiometricModeListener}. */
public void removeBiometricModeListener(BiometricModeListener listener) {
mBiometricModeListeners.remove(listener);
} }
private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() { private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
@@ -499,15 +506,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
break; break;
} }
onModeChanged(mMode); onModeChanged(mMode);
if (mBiometricModeListener != null) {
mBiometricModeListener.notifyBiometricAuthModeChanged();
}
Trace.endSection(); Trace.endSection();
} }
private void onModeChanged(@WakeAndUnlockMode int mode) { private void onModeChanged(@WakeAndUnlockMode int mode) {
if (mBiometricModeListener != null) { for (BiometricModeListener listener : mBiometricModeListeners) {
mBiometricModeListener.onModeChanged(mode); listener.onModeChanged(mode);
} }
} }
@@ -714,9 +718,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
mMode = MODE_NONE; mMode = MODE_NONE;
mBiometricType = null; mBiometricType = null;
mNotificationShadeWindowController.setForceDozeBrightness(false); mNotificationShadeWindowController.setForceDozeBrightness(false);
if (mBiometricModeListener != null) { for (BiometricModeListener listener : mBiometricModeListeners) {
mBiometricModeListener.onResetMode(); listener.onResetMode();
mBiometricModeListener.notifyBiometricAuthModeChanged();
} }
mNumConsecutiveFpFailures = 0; mNumConsecutiveFpFailures = 0;
mLastFpFailureUptimeMillis = 0; mLastFpFailureUptimeMillis = 0;
@@ -825,10 +828,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
/** An interface to interact with the {@link BiometricUnlockController}. */ /** An interface to interact with the {@link BiometricUnlockController}. */
public interface BiometricModeListener { public interface BiometricModeListener {
/** Called when {@code mMode} is reset to {@link #MODE_NONE}. */ /** Called when {@code mMode} is reset to {@link #MODE_NONE}. */
void onResetMode(); default void onResetMode() {}
/** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */ /** Called when {@code mMode} has changed in {@link #startWakeAndUnlock(int)}. */
void onModeChanged(@WakeAndUnlockMode int mode); default void onModeChanged(@WakeAndUnlockMode int mode) {}
/** Called after processing {@link #onModeChanged(int)}. */
void notifyBiometricAuthModeChanged();
} }
} }

View File

@@ -1527,11 +1527,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
protected void startKeyguard() { protected void startKeyguard() {
Trace.beginSection("CentralSurfaces#startKeyguard"); Trace.beginSection("CentralSurfaces#startKeyguard");
mBiometricUnlockController = mBiometricUnlockControllerLazy.get(); mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
mBiometricUnlockController.setBiometricModeListener( mBiometricUnlockController.addBiometricModeListener(
new BiometricUnlockController.BiometricModeListener() { new BiometricUnlockController.BiometricModeListener() {
@Override @Override
public void onResetMode() { public void onResetMode() {
setWakeAndUnlocking(false); setWakeAndUnlocking(false);
notifyBiometricAuthModeChanged();
} }
@Override @Override
@@ -1542,11 +1543,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
case BiometricUnlockController.MODE_WAKE_AND_UNLOCK: case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
setWakeAndUnlocking(true); setWakeAndUnlocking(true);
} }
} notifyBiometricAuthModeChanged();
@Override
public void notifyBiometricAuthModeChanged() {
CentralSurfacesImpl.this.notifyBiometricAuthModeChanged();
} }
private void setWakeAndUnlocking(boolean wakeAndUnlocking) { private void setWakeAndUnlocking(boolean wakeAndUnlocking) {

View File

@@ -193,6 +193,15 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
mSecurityCallback); mSecurityCallback);
} }
@Test
public void onInitConfiguresViewMode() {
mKeyguardSecurityContainerController.onInit();
verify(mView).initMode(eq(MODE_DEFAULT), eq(mGlobalSettings), eq(mFalsingManager),
eq(mUserSwitcherController),
any(KeyguardSecurityContainer.UserSwitcherViewMode.UserSwitcherCallback.class),
eq(mFalsingA11yDelegate));
}
@Test @Test
public void showSecurityScreen_canInflateAllModes() { public void showSecurityScreen_canInflateAllModes() {
SecurityMode[] modes = SecurityMode.values(); SecurityMode[] modes = SecurityMode.values();

View File

@@ -21,8 +21,10 @@ import com.android.systemui.SysuiTestCase
import com.android.systemui.common.shared.model.Position import com.android.systemui.common.shared.model.Position
import com.android.systemui.doze.DozeHost import com.android.systemui.doze.DozeHost
import com.android.systemui.keyguard.WakefulnessLifecycle import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.plugins.statusbar.StatusBarStateController import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.policy.KeyguardStateController import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.argumentCaptor import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.whenever import com.android.systemui.util.mockito.whenever
@@ -46,6 +48,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
@Mock private lateinit var dozeHost: DozeHost @Mock private lateinit var dozeHost: DozeHost
@Mock private lateinit var keyguardStateController: KeyguardStateController @Mock private lateinit var keyguardStateController: KeyguardStateController
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle @Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
private lateinit var underTest: KeyguardRepositoryImpl private lateinit var underTest: KeyguardRepositoryImpl
@@ -59,6 +62,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
keyguardStateController, keyguardStateController,
dozeHost, dozeHost,
wakefulnessLifecycle, wakefulnessLifecycle,
biometricUnlockController,
) )
} }
@@ -190,7 +194,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
} }
@Test @Test
fun wakefullness() = runBlockingTest { fun wakefulness() = runBlockingTest {
val values = mutableListOf<WakefulnessModel>() val values = mutableListOf<WakefulnessModel>()
val job = underTest.wakefulnessState.onEach(values::add).launchIn(this) val job = underTest.wakefulnessState.onEach(values::add).launchIn(this)
@@ -217,4 +221,63 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
job.cancel() job.cancel()
verify(wakefulnessLifecycle).removeObserver(captor.value) verify(wakefulnessLifecycle).removeObserver(captor.value)
} }
@Test
fun isBouncerShowing() = runBlockingTest {
whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
var latest: Boolean? = null
val job = underTest.isBouncerShowing.onEach { latest = it }.launchIn(this)
assertThat(latest).isFalse()
val captor = argumentCaptor<KeyguardStateController.Callback>()
verify(keyguardStateController).addCallback(captor.capture())
whenever(keyguardStateController.isBouncerShowing).thenReturn(true)
captor.value.onBouncerShowingChanged()
assertThat(latest).isTrue()
whenever(keyguardStateController.isBouncerShowing).thenReturn(false)
captor.value.onBouncerShowingChanged()
assertThat(latest).isFalse()
job.cancel()
}
@Test
fun biometricUnlockState() = runBlockingTest {
val values = mutableListOf<BiometricUnlockModel>()
val job = underTest.biometricUnlockState.onEach(values::add).launchIn(this)
val captor = argumentCaptor<BiometricUnlockController.BiometricModeListener>()
verify(biometricUnlockController).addBiometricModeListener(captor.capture())
captor.value.onModeChanged(BiometricUnlockController.MODE_NONE)
captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK)
captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_PULSING)
captor.value.onModeChanged(BiometricUnlockController.MODE_SHOW_BOUNCER)
captor.value.onModeChanged(BiometricUnlockController.MODE_ONLY_WAKE)
captor.value.onModeChanged(BiometricUnlockController.MODE_UNLOCK_COLLAPSING)
captor.value.onModeChanged(BiometricUnlockController.MODE_DISMISS_BOUNCER)
captor.value.onModeChanged(BiometricUnlockController.MODE_WAKE_AND_UNLOCK_FROM_DREAM)
assertThat(values)
.isEqualTo(
listOf(
// Initial value will be NONE, followed by onModeChanged() call
BiometricUnlockModel.NONE,
BiometricUnlockModel.NONE,
BiometricUnlockModel.WAKE_AND_UNLOCK,
BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING,
BiometricUnlockModel.SHOW_BOUNCER,
BiometricUnlockModel.ONLY_WAKE,
BiometricUnlockModel.UNLOCK_COLLAPSING,
BiometricUnlockModel.DISMISS_BOUNCER,
BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM,
)
)
job.cancel()
verify(biometricUnlockController).removeBiometricModeListener(captor.value)
}
} }

View File

@@ -128,11 +128,15 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
assertThat(steps.size).isEqualTo(3) assertThat(steps.size).isEqualTo(3)
assertThat(steps[0]) assertThat(steps[0])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED)) .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED, OWNER_NAME))
assertThat(steps[1]) assertThat(steps[1])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING)) .isEqualTo(
TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING, OWNER_NAME)
)
assertThat(steps[2]) assertThat(steps[2])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED)) .isEqualTo(
TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED, OWNER_NAME)
)
job.cancel() job.cancel()
} }
@@ -174,15 +178,22 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
} }
private fun assertSteps(steps: List<TransitionStep>, fractions: List<BigDecimal>) { private fun assertSteps(steps: List<TransitionStep>, fractions: List<BigDecimal>) {
assertThat(steps[0]).isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED)) assertThat(steps[0])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED, OWNER_NAME))
fractions.forEachIndexed { index, fraction -> fractions.forEachIndexed { index, fraction ->
assertThat(steps[index + 1]) assertThat(steps[index + 1])
.isEqualTo( .isEqualTo(
TransitionStep(AOD, LOCKSCREEN, fraction.toFloat(), TransitionState.RUNNING) TransitionStep(
AOD,
LOCKSCREEN,
fraction.toFloat(),
TransitionState.RUNNING,
OWNER_NAME
)
) )
} }
assertThat(steps[steps.size - 1]) assertThat(steps[steps.size - 1])
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED)) .isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED, OWNER_NAME))
assertThat(wtfHandler.failed).isFalse() assertThat(wtfHandler.failed).isFalse()
} }

View File

@@ -54,9 +54,11 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
@Test @Test
fun `transition collectors receives only appropriate events`() = fun `transition collectors receives only appropriate events`() =
runBlocking(IMMEDIATE) { runBlocking(IMMEDIATE) {
var goneToAodSteps = mutableListOf<TransitionStep>() var lockscreenToAodSteps = mutableListOf<TransitionStep>()
val job1 = val job1 =
underTest.goneToAodTransition.onEach { goneToAodSteps.add(it) }.launchIn(this) underTest.lockscreenToAodTransition
.onEach { lockscreenToAodSteps.add(it) }
.launchIn(this)
var aodToLockscreenSteps = mutableListOf<TransitionStep>() var aodToLockscreenSteps = mutableListOf<TransitionStep>()
val job2 = val job2 =
@@ -70,14 +72,14 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED)) steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING)) steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED)) steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
steps.add(TransitionStep(GONE, AOD, 0f, STARTED)) steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
steps.add(TransitionStep(GONE, AOD, 0.1f, RUNNING)) steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING))
steps.add(TransitionStep(GONE, AOD, 0.2f, RUNNING)) steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING))
steps.forEach { repository.sendTransitionStep(it) } steps.forEach { repository.sendTransitionStep(it) }
assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5)) assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5))
assertThat(goneToAodSteps).isEqualTo(steps.subList(5, 8)) assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8))
job1.cancel() job1.cancel()
job2.cancel() job2.cancel()
@@ -119,10 +121,8 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
fun keyguardStateTests() = fun keyguardStateTests() =
runBlocking(IMMEDIATE) { runBlocking(IMMEDIATE) {
var finishedSteps = mutableListOf<KeyguardState>() var finishedSteps = mutableListOf<KeyguardState>()
val job1 = val job =
underTest.finishedKeyguardState.onEach { finishedSteps.add(it) }.launchIn(this) underTest.finishedKeyguardState.onEach { finishedSteps.add(it) }.launchIn(this)
var startedSteps = mutableListOf<KeyguardState>()
val job2 = underTest.startedKeyguardState.onEach { startedSteps.add(it) }.launchIn(this)
val steps = mutableListOf<TransitionStep>() val steps = mutableListOf<TransitionStep>()
@@ -137,10 +137,60 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
steps.forEach { repository.sendTransitionStep(it) } steps.forEach { repository.sendTransitionStep(it) }
assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, AOD)) assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, AOD))
assertThat(startedSteps).isEqualTo(listOf(LOCKSCREEN, AOD, GONE))
job1.cancel() job.cancel()
job2.cancel() }
@Test
fun finishedKeyguardTransitionStepTests() =
runBlocking(IMMEDIATE) {
var finishedSteps = mutableListOf<TransitionStep>()
val job =
underTest.finishedKeyguardTransitionStep
.onEach { finishedSteps.add(it) }
.launchIn(this)
val steps = mutableListOf<TransitionStep>()
steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
steps.forEach { repository.sendTransitionStep(it) }
assertThat(finishedSteps).isEqualTo(listOf(steps[2], steps[5]))
job.cancel()
}
@Test
fun startedKeyguardTransitionStepTests() =
runBlocking(IMMEDIATE) {
var startedSteps = mutableListOf<TransitionStep>()
val job =
underTest.startedKeyguardTransitionStep
.onEach { startedSteps.add(it) }
.launchIn(this)
val steps = mutableListOf<TransitionStep>()
steps.add(TransitionStep(AOD, LOCKSCREEN, 0f, STARTED))
steps.add(TransitionStep(AOD, LOCKSCREEN, 0.5f, RUNNING))
steps.add(TransitionStep(AOD, LOCKSCREEN, 1f, FINISHED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.9f, RUNNING))
steps.add(TransitionStep(LOCKSCREEN, AOD, 1f, FINISHED))
steps.add(TransitionStep(AOD, GONE, 1f, STARTED))
steps.forEach { repository.sendTransitionStep(it) }
assertThat(startedSteps).isEqualTo(listOf(steps[0], steps[3], steps[6]))
job.cancel()
} }
companion object { companion object {

View File

@@ -143,7 +143,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController, mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController,
mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper); mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper);
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager); mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener); mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener);
} }
@Test @Test

View File

@@ -18,6 +18,7 @@
package com.android.systemui.keyguard.data.repository package com.android.systemui.keyguard.data.repository
import com.android.systemui.common.shared.model.Position import com.android.systemui.common.shared.model.Position
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel import com.android.systemui.keyguard.shared.model.WakefulnessModel
import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow
@@ -52,6 +53,12 @@ class FakeKeyguardRepository : KeyguardRepository {
private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP) private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP)
override val wakefulnessState: Flow<WakefulnessModel> = _wakefulnessState override val wakefulnessState: Flow<WakefulnessModel> = _wakefulnessState
private val _isBouncerShowing = MutableStateFlow(false)
override val isBouncerShowing: Flow<Boolean> = _isBouncerShowing
private val _biometricUnlockState = MutableStateFlow(BiometricUnlockModel.NONE)
override val biometricUnlockState: Flow<BiometricUnlockModel> = _biometricUnlockState
override fun isKeyguardShowing(): Boolean { override fun isKeyguardShowing(): Boolean {
return _isKeyguardShowing.value return _isKeyguardShowing.value
} }