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)
|
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)
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.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()
|
||||||
|
|||||||
@@ -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) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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 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)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|||||||
@@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user