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:
@@ -228,7 +228,7 @@ open class ClockEventController @Inject constructor(
|
||||
listenForDozing(this)
|
||||
if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
|
||||
listenForDozeAmountTransition(this)
|
||||
listenForGoneToAodTransition(this)
|
||||
listenForAnyStateToAodTransition(this)
|
||||
} else {
|
||||
listenForDozeAmount(this)
|
||||
}
|
||||
@@ -286,10 +286,10 @@ open class ClockEventController @Inject constructor(
|
||||
* dozing.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
internal fun listenForGoneToAodTransition(scope: CoroutineScope): Job {
|
||||
internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
|
||||
return scope.launch {
|
||||
keyguardTransitionInteractor.goneToAodTransition.filter {
|
||||
it.transitionState == TransitionState.STARTED
|
||||
keyguardTransitionInteractor.anyStateToAodTransition.filter {
|
||||
it.transitionState == TransitionState.FINISHED
|
||||
}.collect {
|
||||
dozeAmount = 1f
|
||||
clock?.animations?.doze(dozeAmount)
|
||||
|
||||
@@ -106,8 +106,9 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
static final int USER_TYPE_WORK_PROFILE = 2;
|
||||
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 {}
|
||||
static final int MODE_UNINITIALIZED = -1;
|
||||
static final int MODE_DEFAULT = 0;
|
||||
static final int MODE_ONE_HANDED = 1;
|
||||
static final int MODE_USER_SWITCHER = 2;
|
||||
@@ -154,7 +155,11 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
private boolean mDisappearAnimRunning;
|
||||
private SwipeListener mSwipeListener;
|
||||
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 final WindowInsetsAnimation.Callback mWindowInsetsAnimationCallback =
|
||||
@@ -347,6 +352,8 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
||||
|
||||
private String modeToString(@Mode int mode) {
|
||||
switch (mode) {
|
||||
case MODE_UNINITIALIZED:
|
||||
return "Uninitialized";
|
||||
case MODE_DEFAULT:
|
||||
return "Default";
|
||||
case MODE_ONE_HANDED:
|
||||
|
||||
@@ -318,6 +318,7 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
||||
@Override
|
||||
public void onInit() {
|
||||
mSecurityViewFlipperController.init();
|
||||
configureMode();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -23,9 +23,12 @@ import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.doze.DozeHost
|
||||
import com.android.systemui.keyguard.WakefulnessLifecycle
|
||||
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.WakefulnessModel
|
||||
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 javax.inject.Inject
|
||||
import kotlinx.coroutines.channels.awaitClose
|
||||
@@ -65,6 +68,9 @@ interface KeyguardRepository {
|
||||
*/
|
||||
val isKeyguardShowing: Flow<Boolean>
|
||||
|
||||
/** Observable for whether the bouncer is showing. */
|
||||
val isBouncerShowing: Flow<Boolean>
|
||||
|
||||
/**
|
||||
* Observable for whether we are in doze state.
|
||||
*
|
||||
@@ -95,6 +101,9 @@ interface KeyguardRepository {
|
||||
/** Observable for device wake/sleep state */
|
||||
val wakefulnessState: Flow<WakefulnessModel>
|
||||
|
||||
/** Observable for biometric unlock modes */
|
||||
val biometricUnlockState: Flow<BiometricUnlockModel>
|
||||
|
||||
/**
|
||||
* Returns `true` if the keyguard is showing; `false` otherwise.
|
||||
*
|
||||
@@ -125,6 +134,7 @@ constructor(
|
||||
private val keyguardStateController: KeyguardStateController,
|
||||
dozeHost: DozeHost,
|
||||
wakefulnessLifecycle: WakefulnessLifecycle,
|
||||
biometricUnlockController: BiometricUnlockController,
|
||||
) : KeyguardRepository {
|
||||
private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
|
||||
override val animateBottomAreaDozingTransitions =
|
||||
@@ -159,6 +169,29 @@ constructor(
|
||||
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> =
|
||||
conflatedCallbackFlow {
|
||||
val callback =
|
||||
@@ -248,6 +281,24 @@ constructor(
|
||||
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) {
|
||||
_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 {
|
||||
private const val TAG = "KeyguardRepositoryImpl"
|
||||
}
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ package com.android.systemui.keyguard.domain.interactor
|
||||
|
||||
import com.android.systemui.dagger.SysUISingleton
|
||||
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 javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -39,10 +41,19 @@ constructor(
|
||||
val dozeAmount: Flow<Float> = repository.dozeAmount
|
||||
/** Whether the system is in doze mode. */
|
||||
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
|
||||
/** Whether the bouncer is showing or not. */
|
||||
val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
|
||||
/** The device wake/sleep state */
|
||||
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 {
|
||||
return repository.isKeyguardShowing()
|
||||
|
||||
@@ -41,11 +41,13 @@ constructor(
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
interactor.finishedKeyguardState.collect { logger.i("Finished transition to", it) }
|
||||
interactor.finishedKeyguardTransitionStep.collect {
|
||||
logger.i("Finished transition", it)
|
||||
}
|
||||
}
|
||||
|
||||
scope.launch {
|
||||
interactor.startedKeyguardState.collect { logger.i("Started transition to", it) }
|
||||
interactor.startedKeyguardTransitionStep.collect { logger.i("Started transition", it) }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ constructor(
|
||||
is AodLockscreenTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is GoneAodTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is LockscreenGoneTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
is AodToGoneTransitionInteractor -> Log.d(TAG, "Started $it")
|
||||
}
|
||||
it.start()
|
||||
}
|
||||
|
||||
@@ -21,7 +21,6 @@ import com.android.systemui.dagger.SysUISingleton
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
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.GONE
|
||||
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
|
||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||
@@ -44,8 +43,9 @@ constructor(
|
||||
/** LOCKSCREEN->AOD transition information. */
|
||||
val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
|
||||
|
||||
/** GONE->AOD information. */
|
||||
val goneToAodTransition: Flow<TransitionStep> = repository.transition(GONE, AOD)
|
||||
/** (any)->AOD transition information */
|
||||
val anyStateToAodTransition: Flow<TransitionStep> =
|
||||
repository.transitions.filter { step -> step.to == KeyguardState.AOD }
|
||||
|
||||
/**
|
||||
* AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
|
||||
@@ -57,15 +57,15 @@ constructor(
|
||||
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 */
|
||||
val finishedKeyguardState: Flow<KeyguardState> =
|
||||
repository.transitions
|
||||
.filter { step -> step.transitionState == TransitionState.FINISHED }
|
||||
.map { step -> step.to }
|
||||
finishedKeyguardTransitionStep.map { step -> step.to }
|
||||
|
||||
/* The last started [KeyguardState] transition */
|
||||
val startedKeyguardState: Flow<KeyguardState> =
|
||||
repository.transitions
|
||||
.filter { step -> step.transitionState == TransitionState.STARTED }
|
||||
.map { step -> step.to }
|
||||
/* The last [TransitionStep] with a [TransitionState] of STARTED */
|
||||
val startedKeyguardTransitionStep: Flow<TransitionStep> =
|
||||
repository.transitions.filter { step -> step.transitionState == TransitionState.STARTED }
|
||||
}
|
||||
|
||||
@@ -16,14 +16,16 @@
|
||||
|
||||
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.KeyguardRepository
|
||||
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||
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.TransitionInfo
|
||||
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.util.kotlin.sample
|
||||
import java.util.UUID
|
||||
@@ -38,7 +40,7 @@ class LockscreenBouncerTransitionInteractor
|
||||
@Inject
|
||||
constructor(
|
||||
@Application private val scope: CoroutineScope,
|
||||
private val keyguardRepository: KeyguardRepository,
|
||||
private val keyguardInteractor: KeyguardInteractor,
|
||||
private val shadeRepository: ShadeRepository,
|
||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||
@@ -47,12 +49,47 @@ constructor(
|
||||
private var transitionId: UUID? = null
|
||||
|
||||
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 {
|
||||
shadeRepository.shadeModel
|
||||
.sample(
|
||||
combine(
|
||||
keyguardTransitionInteractor.finishedKeyguardState,
|
||||
keyguardRepository.statusBarState,
|
||||
keyguardInteractor.statusBarState,
|
||||
) { 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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,8 @@ abstract class StartKeyguardTransitionModule {
|
||||
|
||||
@Binds @IntoSet abstract fun goneAod(impl: GoneAodTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds @IntoSet abstract fun aodGone(impl: AodToGoneTransitionInteractor): TransitionInteractor
|
||||
|
||||
@Binds
|
||||
@IntoSet
|
||||
abstract fun lockscreenGone(impl: LockscreenGoneTransitionInteractor): TransitionInteractor
|
||||
|
||||
@@ -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,
|
||||
}
|
||||
@@ -21,10 +21,11 @@ data class TransitionStep(
|
||||
val to: KeyguardState = KeyguardState.NONE,
|
||||
val value: Float = 0f, // constrained [0.0, 1.0]
|
||||
val transitionState: TransitionState = TransitionState.FINISHED,
|
||||
val ownerName: String = "",
|
||||
) {
|
||||
constructor(
|
||||
info: TransitionInfo,
|
||||
value: Float,
|
||||
transitionState: TransitionState,
|
||||
) : this(info.from, info.to, value, transitionState)
|
||||
) : this(info.from, info.to, value, transitionState, info.ownerName)
|
||||
}
|
||||
|
||||
@@ -67,8 +67,10 @@ import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||
import java.io.PrintWriter;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@@ -167,7 +169,7 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
private PendingAuthenticated mPendingAuthenticated = null;
|
||||
private boolean mHasScreenTurnedOnSinceAuthenticating;
|
||||
private boolean mFadedAwayAfterWakeAndUnlock;
|
||||
private BiometricModeListener mBiometricModeListener;
|
||||
private Set<BiometricModeListener> mBiometricModeListeners = new HashSet<>();
|
||||
|
||||
private final MetricsLogger mMetricsLogger;
|
||||
private final AuthController mAuthController;
|
||||
@@ -314,9 +316,14 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
mKeyguardViewController = keyguardViewController;
|
||||
}
|
||||
|
||||
/** Sets a {@link BiometricModeListener}. */
|
||||
public void setBiometricModeListener(BiometricModeListener biometricModeListener) {
|
||||
mBiometricModeListener = biometricModeListener;
|
||||
/** Adds a {@link BiometricModeListener}. */
|
||||
public void addBiometricModeListener(BiometricModeListener listener) {
|
||||
mBiometricModeListeners.add(listener);
|
||||
}
|
||||
|
||||
/** Removes a {@link BiometricModeListener}. */
|
||||
public void removeBiometricModeListener(BiometricModeListener listener) {
|
||||
mBiometricModeListeners.remove(listener);
|
||||
}
|
||||
|
||||
private final Runnable mReleaseBiometricWakeLockRunnable = new Runnable() {
|
||||
@@ -499,15 +506,12 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
break;
|
||||
}
|
||||
onModeChanged(mMode);
|
||||
if (mBiometricModeListener != null) {
|
||||
mBiometricModeListener.notifyBiometricAuthModeChanged();
|
||||
}
|
||||
Trace.endSection();
|
||||
}
|
||||
|
||||
private void onModeChanged(@WakeAndUnlockMode int mode) {
|
||||
if (mBiometricModeListener != null) {
|
||||
mBiometricModeListener.onModeChanged(mode);
|
||||
for (BiometricModeListener listener : mBiometricModeListeners) {
|
||||
listener.onModeChanged(mode);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,9 +718,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
mMode = MODE_NONE;
|
||||
mBiometricType = null;
|
||||
mNotificationShadeWindowController.setForceDozeBrightness(false);
|
||||
if (mBiometricModeListener != null) {
|
||||
mBiometricModeListener.onResetMode();
|
||||
mBiometricModeListener.notifyBiometricAuthModeChanged();
|
||||
for (BiometricModeListener listener : mBiometricModeListeners) {
|
||||
listener.onResetMode();
|
||||
}
|
||||
mNumConsecutiveFpFailures = 0;
|
||||
mLastFpFailureUptimeMillis = 0;
|
||||
@@ -825,10 +828,8 @@ public class BiometricUnlockController extends KeyguardUpdateMonitorCallback imp
|
||||
/** An interface to interact with the {@link BiometricUnlockController}. */
|
||||
public interface BiometricModeListener {
|
||||
/** 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)}. */
|
||||
void onModeChanged(@WakeAndUnlockMode int mode);
|
||||
/** Called after processing {@link #onModeChanged(int)}. */
|
||||
void notifyBiometricAuthModeChanged();
|
||||
default void onModeChanged(@WakeAndUnlockMode int mode) {}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1527,11 +1527,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
|
||||
protected void startKeyguard() {
|
||||
Trace.beginSection("CentralSurfaces#startKeyguard");
|
||||
mBiometricUnlockController = mBiometricUnlockControllerLazy.get();
|
||||
mBiometricUnlockController.setBiometricModeListener(
|
||||
mBiometricUnlockController.addBiometricModeListener(
|
||||
new BiometricUnlockController.BiometricModeListener() {
|
||||
@Override
|
||||
public void onResetMode() {
|
||||
setWakeAndUnlocking(false);
|
||||
notifyBiometricAuthModeChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1542,11 +1543,7 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
|
||||
case BiometricUnlockController.MODE_WAKE_AND_UNLOCK:
|
||||
setWakeAndUnlocking(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void notifyBiometricAuthModeChanged() {
|
||||
CentralSurfacesImpl.this.notifyBiometricAuthModeChanged();
|
||||
notifyBiometricAuthModeChanged();
|
||||
}
|
||||
|
||||
private void setWakeAndUnlocking(boolean wakeAndUnlocking) {
|
||||
|
||||
@@ -193,6 +193,15 @@ public class KeyguardSecurityContainerControllerTest extends SysuiTestCase {
|
||||
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
|
||||
public void showSecurityScreen_canInflateAllModes() {
|
||||
SecurityMode[] modes = SecurityMode.values();
|
||||
|
||||
@@ -21,8 +21,10 @@ import com.android.systemui.SysuiTestCase
|
||||
import com.android.systemui.common.shared.model.Position
|
||||
import com.android.systemui.doze.DozeHost
|
||||
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.plugins.statusbar.StatusBarStateController
|
||||
import com.android.systemui.statusbar.phone.BiometricUnlockController
|
||||
import com.android.systemui.statusbar.policy.KeyguardStateController
|
||||
import com.android.systemui.util.mockito.argumentCaptor
|
||||
import com.android.systemui.util.mockito.whenever
|
||||
@@ -46,6 +48,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
@Mock private lateinit var dozeHost: DozeHost
|
||||
@Mock private lateinit var keyguardStateController: KeyguardStateController
|
||||
@Mock private lateinit var wakefulnessLifecycle: WakefulnessLifecycle
|
||||
@Mock private lateinit var biometricUnlockController: BiometricUnlockController
|
||||
|
||||
private lateinit var underTest: KeyguardRepositoryImpl
|
||||
|
||||
@@ -59,6 +62,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
keyguardStateController,
|
||||
dozeHost,
|
||||
wakefulnessLifecycle,
|
||||
biometricUnlockController,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -190,7 +194,7 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
@Test
|
||||
fun wakefullness() = runBlockingTest {
|
||||
fun wakefulness() = runBlockingTest {
|
||||
val values = mutableListOf<WakefulnessModel>()
|
||||
val job = underTest.wakefulnessState.onEach(values::add).launchIn(this)
|
||||
|
||||
@@ -217,4 +221,63 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
||||
job.cancel()
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,11 +128,15 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
|
||||
|
||||
assertThat(steps.size).isEqualTo(3)
|
||||
assertThat(steps[0])
|
||||
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED))
|
||||
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0f, TransitionState.STARTED, OWNER_NAME))
|
||||
assertThat(steps[1])
|
||||
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING))
|
||||
.isEqualTo(
|
||||
TransitionStep(AOD, LOCKSCREEN, 0.5f, TransitionState.RUNNING, OWNER_NAME)
|
||||
)
|
||||
assertThat(steps[2])
|
||||
.isEqualTo(TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED))
|
||||
.isEqualTo(
|
||||
TransitionStep(AOD, LOCKSCREEN, 1f, TransitionState.FINISHED, OWNER_NAME)
|
||||
)
|
||||
job.cancel()
|
||||
}
|
||||
|
||||
@@ -174,15 +178,22 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
|
||||
}
|
||||
|
||||
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 ->
|
||||
assertThat(steps[index + 1])
|
||||
.isEqualTo(
|
||||
TransitionStep(AOD, LOCKSCREEN, fraction.toFloat(), TransitionState.RUNNING)
|
||||
TransitionStep(
|
||||
AOD,
|
||||
LOCKSCREEN,
|
||||
fraction.toFloat(),
|
||||
TransitionState.RUNNING,
|
||||
OWNER_NAME
|
||||
)
|
||||
)
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
@@ -54,9 +54,11 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
|
||||
@Test
|
||||
fun `transition collectors receives only appropriate events`() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var goneToAodSteps = mutableListOf<TransitionStep>()
|
||||
var lockscreenToAodSteps = mutableListOf<TransitionStep>()
|
||||
val job1 =
|
||||
underTest.goneToAodTransition.onEach { goneToAodSteps.add(it) }.launchIn(this)
|
||||
underTest.lockscreenToAodTransition
|
||||
.onEach { lockscreenToAodSteps.add(it) }
|
||||
.launchIn(this)
|
||||
|
||||
var aodToLockscreenSteps = mutableListOf<TransitionStep>()
|
||||
val job2 =
|
||||
@@ -70,14 +72,14 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
|
||||
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(GONE, AOD, 0f, STARTED))
|
||||
steps.add(TransitionStep(GONE, AOD, 0.1f, RUNNING))
|
||||
steps.add(TransitionStep(GONE, AOD, 0.2f, RUNNING))
|
||||
steps.add(TransitionStep(LOCKSCREEN, AOD, 0f, STARTED))
|
||||
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.1f, RUNNING))
|
||||
steps.add(TransitionStep(LOCKSCREEN, AOD, 0.2f, RUNNING))
|
||||
|
||||
steps.forEach { repository.sendTransitionStep(it) }
|
||||
|
||||
assertThat(aodToLockscreenSteps).isEqualTo(steps.subList(2, 5))
|
||||
assertThat(goneToAodSteps).isEqualTo(steps.subList(5, 8))
|
||||
assertThat(lockscreenToAodSteps).isEqualTo(steps.subList(5, 8))
|
||||
|
||||
job1.cancel()
|
||||
job2.cancel()
|
||||
@@ -119,10 +121,8 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
|
||||
fun keyguardStateTests() =
|
||||
runBlocking(IMMEDIATE) {
|
||||
var finishedSteps = mutableListOf<KeyguardState>()
|
||||
val job1 =
|
||||
val job =
|
||||
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>()
|
||||
|
||||
@@ -137,10 +137,60 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() {
|
||||
steps.forEach { repository.sendTransitionStep(it) }
|
||||
|
||||
assertThat(finishedSteps).isEqualTo(listOf(LOCKSCREEN, AOD))
|
||||
assertThat(startedSteps).isEqualTo(listOf(LOCKSCREEN, AOD, GONE))
|
||||
|
||||
job1.cancel()
|
||||
job2.cancel()
|
||||
job.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 {
|
||||
|
||||
@@ -143,7 +143,7 @@ public class BiometricsUnlockControllerTest extends SysuiTestCase {
|
||||
mAuthController, mStatusBarStateController, mKeyguardUnlockAnimationController,
|
||||
mSessionTracker, mLatencyTracker, mScreenOffAnimationController, mVibratorHelper);
|
||||
mBiometricUnlockController.setKeyguardViewController(mStatusBarKeyguardViewManager);
|
||||
mBiometricUnlockController.setBiometricModeListener(mBiometricModeListener);
|
||||
mBiometricUnlockController.addBiometricModeListener(mBiometricModeListener);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package com.android.systemui.keyguard.data.repository
|
||||
|
||||
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.WakefulnessModel
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
@@ -52,6 +53,12 @@ class FakeKeyguardRepository : KeyguardRepository {
|
||||
private val _wakefulnessState = MutableStateFlow(WakefulnessModel.ASLEEP)
|
||||
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 {
|
||||
return _isKeyguardShowing.value
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user