Merge "[DO NOT MERGE] Transitions: PRIMARY_BOUNCER -> GONE" into tm-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
ec3511caf5
@@ -78,7 +78,7 @@
|
|||||||
<!-- The vertical margin between the date and the owner info. -->
|
<!-- The vertical margin between the date and the owner info. -->
|
||||||
|
|
||||||
<!-- The translation for disappearing security views after having solved them. -->
|
<!-- The translation for disappearing security views after having solved them. -->
|
||||||
<dimen name="disappear_y_translation">-32dp</dimen>
|
<dimen name="disappear_y_translation">-50dp</dimen>
|
||||||
|
|
||||||
<!-- Dimens for animation for the Bouncer PIN view -->
|
<!-- Dimens for animation for the Bouncer PIN view -->
|
||||||
<dimen name="pin_view_trans_y_entry">120dp</dimen>
|
<dimen name="pin_view_trans_y_entry">120dp</dimen>
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import static java.lang.Integer.max;
|
|||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
import android.animation.AnimatorListenerAdapter;
|
import android.animation.AnimatorListenerAdapter;
|
||||||
import android.animation.AnimatorSet;
|
|
||||||
import android.animation.ObjectAnimator;
|
import android.animation.ObjectAnimator;
|
||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
@@ -1068,13 +1067,10 @@ public class KeyguardSecurityContainer extends ConstraintLayout {
|
|||||||
|
|
||||||
int yTranslation = mResources.getDimensionPixelSize(R.dimen.disappear_y_translation);
|
int yTranslation = mResources.getDimensionPixelSize(R.dimen.disappear_y_translation);
|
||||||
|
|
||||||
AnimatorSet anims = new AnimatorSet();
|
|
||||||
ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
|
ObjectAnimator yAnim = ObjectAnimator.ofFloat(mView, View.TRANSLATION_Y, yTranslation);
|
||||||
ObjectAnimator alphaAnim = ObjectAnimator.ofFloat(mView, View.ALPHA, 0f);
|
yAnim.setInterpolator(Interpolators.STANDARD_ACCELERATE);
|
||||||
|
yAnim.setDuration(500);
|
||||||
anims.setInterpolator(Interpolators.STANDARD_ACCELERATE);
|
yAnim.start();
|
||||||
anims.playTogether(alphaAnim, yAnim);
|
|
||||||
anims.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setupUserSwitcher() {
|
private void setupUserSwitcher() {
|
||||||
|
|||||||
@@ -636,12 +636,17 @@ public class KeyguardSecurityContainerController extends ViewController<Keyguard
|
|||||||
|
|
||||||
public void startAppearAnimation() {
|
public void startAppearAnimation() {
|
||||||
if (mCurrentSecurityMode != SecurityMode.None) {
|
if (mCurrentSecurityMode != SecurityMode.None) {
|
||||||
mView.setAlpha(1f);
|
setAlpha(1f);
|
||||||
mView.startAppearAnimation(mCurrentSecurityMode);
|
mView.startAppearAnimation(mCurrentSecurityMode);
|
||||||
getCurrentSecurityController().startAppearAnimation();
|
getCurrentSecurityController().startAppearAnimation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Set the alpha of the security container view */
|
||||||
|
public void setAlpha(float alpha) {
|
||||||
|
mView.setAlpha(alpha);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
|
public boolean startDisappearAnimation(Runnable onFinishRunnable) {
|
||||||
boolean didRunAnimation = false;
|
boolean didRunAnimation = false;
|
||||||
|
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ interface KeyguardRepository {
|
|||||||
*/
|
*/
|
||||||
val isKeyguardShowing: Flow<Boolean>
|
val isKeyguardShowing: Flow<Boolean>
|
||||||
|
|
||||||
|
/** Is the keyguard in a unlocked state? */
|
||||||
|
val isKeyguardUnlocked: Flow<Boolean>
|
||||||
|
|
||||||
/** Is an activity showing over the keyguard? */
|
/** Is an activity showing over the keyguard? */
|
||||||
val isKeyguardOccluded: Flow<Boolean>
|
val isKeyguardOccluded: Flow<Boolean>
|
||||||
|
|
||||||
@@ -278,6 +281,31 @@ constructor(
|
|||||||
}
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
|
|
||||||
|
override val isKeyguardUnlocked: Flow<Boolean> =
|
||||||
|
conflatedCallbackFlow {
|
||||||
|
val callback =
|
||||||
|
object : KeyguardStateController.Callback {
|
||||||
|
override fun onUnlockedChanged() {
|
||||||
|
trySendWithFailureLogging(
|
||||||
|
keyguardStateController.isUnlocked,
|
||||||
|
TAG,
|
||||||
|
"updated isKeyguardUnlocked"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
keyguardStateController.addCallback(callback)
|
||||||
|
// Adding the callback does not send an initial update.
|
||||||
|
trySendWithFailureLogging(
|
||||||
|
keyguardStateController.isUnlocked,
|
||||||
|
TAG,
|
||||||
|
"initial isKeyguardUnlocked"
|
||||||
|
)
|
||||||
|
|
||||||
|
awaitClose { keyguardStateController.removeCallback(callback) }
|
||||||
|
}
|
||||||
|
.distinctUntilChanged()
|
||||||
|
|
||||||
override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
|
override val isKeyguardGoingAway: Flow<Boolean> = conflatedCallbackFlow {
|
||||||
val callback =
|
val callback =
|
||||||
object : KeyguardStateController.Callback {
|
object : KeyguardStateController.Callback {
|
||||||
|
|||||||
@@ -68,8 +68,11 @@ interface KeyguardTransitionRepository {
|
|||||||
/**
|
/**
|
||||||
* Begin a transition from one state to another. Transitions are interruptible, and will issue a
|
* Begin a transition from one state to another. Transitions are interruptible, and will issue a
|
||||||
* [TransitionStep] with state = [TransitionState.CANCELED] before beginning the next one.
|
* [TransitionStep] with state = [TransitionState.CANCELED] before beginning the next one.
|
||||||
|
*
|
||||||
|
* When canceled, there are two options: to continue from the current position of the prior
|
||||||
|
* transition, or to reset the position. When [resetIfCanceled] == true, it will do the latter.
|
||||||
*/
|
*/
|
||||||
fun startTransition(info: TransitionInfo): UUID?
|
fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean = false): UUID?
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows manual control of a transition. When calling [startTransition], the consumer must pass
|
* Allows manual control of a transition. When calling [startTransition], the consumer must pass
|
||||||
@@ -130,7 +133,10 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startTransition(info: TransitionInfo): UUID? {
|
override fun startTransition(
|
||||||
|
info: TransitionInfo,
|
||||||
|
resetIfCanceled: Boolean,
|
||||||
|
): UUID? {
|
||||||
if (lastStep.from == info.from && lastStep.to == info.to) {
|
if (lastStep.from == info.from && lastStep.to == info.to) {
|
||||||
Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
|
Log.i(TAG, "Duplicate call to start the transition, rejecting: $info")
|
||||||
return null
|
return null
|
||||||
@@ -138,7 +144,11 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
|
|||||||
val startingValue =
|
val startingValue =
|
||||||
if (lastStep.transitionState != TransitionState.FINISHED) {
|
if (lastStep.transitionState != TransitionState.FINISHED) {
|
||||||
Log.i(TAG, "Transition still active: $lastStep, canceling")
|
Log.i(TAG, "Transition still active: $lastStep, canceling")
|
||||||
|
if (resetIfCanceled) {
|
||||||
|
0f
|
||||||
|
} else {
|
||||||
lastStep.value
|
lastStep.value
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
0f
|
0f
|
||||||
}
|
}
|
||||||
@@ -227,10 +237,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun trace(step: TransitionStep, isManual: Boolean) {
|
private fun trace(step: TransitionStep, isManual: Boolean) {
|
||||||
if (
|
if (step.transitionState == TransitionState.RUNNING) {
|
||||||
step.transitionState != TransitionState.STARTED &&
|
|
||||||
step.transitionState != TransitionState.FINISHED
|
|
||||||
) {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val traceName =
|
val traceName =
|
||||||
@@ -243,7 +250,10 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
|
|||||||
val traceCookie = traceName.hashCode()
|
val traceCookie = traceName.hashCode()
|
||||||
if (step.transitionState == TransitionState.STARTED) {
|
if (step.transitionState == TransitionState.STARTED) {
|
||||||
Trace.beginAsyncSection(traceName, traceCookie)
|
Trace.beginAsyncSection(traceName, traceCookie)
|
||||||
} else if (step.transitionState == TransitionState.FINISHED) {
|
} else if (
|
||||||
|
step.transitionState == TransitionState.FINISHED ||
|
||||||
|
step.transitionState == TransitionState.CANCELED
|
||||||
|
) {
|
||||||
Trace.endAsyncSection(traceName, traceCookie)
|
Trace.endAsyncSection(traceName, traceCookie)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,6 @@ import kotlinx.coroutines.CoroutineScope
|
|||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
import kotlinx.coroutines.flow.collect
|
import kotlinx.coroutines.flow.collect
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
|
||||||
import kotlinx.coroutines.flow.onEach
|
import kotlinx.coroutines.flow.onEach
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
|
|
||||||
@@ -57,14 +56,7 @@ constructor(
|
|||||||
|
|
||||||
private fun listenForDreamingToLockscreen() {
|
private fun listenForDreamingToLockscreen() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
// Dependending on the dream, either dream state or occluded change will change first,
|
keyguardInteractor.isAbleToDream
|
||||||
// so listen for both
|
|
||||||
combine(keyguardInteractor.isAbleToDream, keyguardInteractor.isKeyguardOccluded) {
|
|
||||||
isAbleToDream,
|
|
||||||
isKeyguardOccluded ->
|
|
||||||
isAbleToDream && isKeyguardOccluded
|
|
||||||
}
|
|
||||||
.distinctUntilChanged()
|
|
||||||
.sample(
|
.sample(
|
||||||
combine(
|
combine(
|
||||||
keyguardInteractor.dozeTransitionModel,
|
keyguardInteractor.dozeTransitionModel,
|
||||||
|
|||||||
@@ -130,15 +130,17 @@ constructor(
|
|||||||
shadeRepository.shadeModel
|
shadeRepository.shadeModel
|
||||||
.sample(
|
.sample(
|
||||||
combine(
|
combine(
|
||||||
keyguardTransitionInteractor.finishedKeyguardState,
|
keyguardTransitionInteractor.startedKeyguardTransitionStep,
|
||||||
keyguardInteractor.statusBarState,
|
keyguardInteractor.statusBarState,
|
||||||
::Pair
|
keyguardInteractor.isKeyguardUnlocked,
|
||||||
),
|
|
||||||
::toTriple
|
::toTriple
|
||||||
|
),
|
||||||
|
::toQuad
|
||||||
)
|
)
|
||||||
.collect { (shadeModel, keyguardState, statusBarState) ->
|
.collect { (shadeModel, keyguardState, statusBarState, isKeyguardUnlocked) ->
|
||||||
val id = transitionId
|
val id = transitionId
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
|
if (keyguardState.to == KeyguardState.PRIMARY_BOUNCER) {
|
||||||
// An existing `id` means a transition is started, and calls to
|
// An existing `id` means a transition is started, and calls to
|
||||||
// `updateTransition` will control it until FINISHED or CANCELED
|
// `updateTransition` will control it until FINISHED or CANCELED
|
||||||
var nextState =
|
var nextState =
|
||||||
@@ -173,12 +175,14 @@ constructor(
|
|||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO (b/251849525): Remove statusbarstate check when that state is
|
// TODO (b/251849525): Remove statusbarstate check when that state is
|
||||||
// integrated into KeyguardTransitionRepository
|
// integrated into KeyguardTransitionRepository
|
||||||
if (
|
if (
|
||||||
keyguardState == KeyguardState.LOCKSCREEN &&
|
keyguardState.to == KeyguardState.LOCKSCREEN &&
|
||||||
shadeModel.isUserDragging &&
|
shadeModel.isUserDragging &&
|
||||||
|
!isKeyguardUnlocked &&
|
||||||
statusBarState == KEYGUARD
|
statusBarState == KEYGUARD
|
||||||
) {
|
) {
|
||||||
transitionId =
|
transitionId =
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
package com.android.systemui.keyguard.domain.interactor
|
package com.android.systemui.keyguard.domain.interactor
|
||||||
|
|
||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.Password
|
||||||
|
import com.android.keyguard.KeyguardUpdateMonitor
|
||||||
import com.android.systemui.animation.Interpolators
|
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
|
||||||
@@ -26,6 +29,8 @@ import com.android.systemui.keyguard.shared.model.TransitionInfo
|
|||||||
import com.android.systemui.keyguard.shared.model.WakefulnessState
|
import com.android.systemui.keyguard.shared.model.WakefulnessState
|
||||||
import com.android.systemui.util.kotlin.sample
|
import com.android.systemui.util.kotlin.sample
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.time.Duration
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlinx.coroutines.CoroutineScope
|
import kotlinx.coroutines.CoroutineScope
|
||||||
import kotlinx.coroutines.flow.combine
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
@@ -37,7 +42,8 @@ constructor(
|
|||||||
@Application private val scope: CoroutineScope,
|
@Application private val scope: CoroutineScope,
|
||||||
private val keyguardInteractor: KeyguardInteractor,
|
private val keyguardInteractor: KeyguardInteractor,
|
||||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||||
private val keyguardTransitionInteractor: KeyguardTransitionInteractor
|
private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
|
||||||
|
private val keyguardSecurityModel: KeyguardSecurityModel,
|
||||||
) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
|
) : TransitionInteractor(FromPrimaryBouncerTransitionInteractor::class.simpleName!!) {
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
@@ -93,31 +99,47 @@ constructor(
|
|||||||
private fun listenForPrimaryBouncerToGone() {
|
private fun listenForPrimaryBouncerToGone() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
keyguardInteractor.isKeyguardGoingAway
|
keyguardInteractor.isKeyguardGoingAway
|
||||||
.sample(keyguardTransitionInteractor.finishedKeyguardState) { a, b -> Pair(a, b) }
|
.sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
|
||||||
.collect { pair ->
|
.collect { (isKeyguardGoingAway, lastStartedTransitionStep) ->
|
||||||
val (isKeyguardGoingAway, keyguardState) = pair
|
if (
|
||||||
if (isKeyguardGoingAway && keyguardState == KeyguardState.PRIMARY_BOUNCER) {
|
isKeyguardGoingAway &&
|
||||||
|
lastStartedTransitionStep.to == KeyguardState.PRIMARY_BOUNCER
|
||||||
|
) {
|
||||||
|
val securityMode =
|
||||||
|
keyguardSecurityModel.getSecurityMode(
|
||||||
|
KeyguardUpdateMonitor.getCurrentUser()
|
||||||
|
)
|
||||||
|
// IME for password requires a slightly faster animation
|
||||||
|
val duration =
|
||||||
|
if (securityMode == Password) {
|
||||||
|
TO_GONE_SHORT_DURATION
|
||||||
|
} else {
|
||||||
|
TO_GONE_DURATION
|
||||||
|
}
|
||||||
keyguardTransitionRepository.startTransition(
|
keyguardTransitionRepository.startTransition(
|
||||||
TransitionInfo(
|
TransitionInfo(
|
||||||
ownerName = name,
|
ownerName = name,
|
||||||
from = KeyguardState.PRIMARY_BOUNCER,
|
from = KeyguardState.PRIMARY_BOUNCER,
|
||||||
to = KeyguardState.GONE,
|
to = KeyguardState.GONE,
|
||||||
animator = getAnimator(),
|
animator = getAnimator(duration),
|
||||||
)
|
),
|
||||||
|
resetIfCanceled = true,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAnimator(): ValueAnimator {
|
private fun getAnimator(duration: Duration = DEFAULT_DURATION): ValueAnimator {
|
||||||
return ValueAnimator().apply {
|
return ValueAnimator().apply {
|
||||||
setInterpolator(Interpolators.LINEAR)
|
setInterpolator(Interpolators.LINEAR)
|
||||||
setDuration(TRANSITION_DURATION_MS)
|
setDuration(duration.inWholeMilliseconds)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TRANSITION_DURATION_MS = 300L
|
private val DEFAULT_DURATION = 300.milliseconds
|
||||||
|
val TO_GONE_DURATION = 250.milliseconds
|
||||||
|
val TO_GONE_SHORT_DURATION = 200.milliseconds
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,9 @@ import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDoz
|
|||||||
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
|
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
|
||||||
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.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
|
||||||
import com.android.systemui.statusbar.CommandQueue
|
import com.android.systemui.statusbar.CommandQueue
|
||||||
|
import com.android.systemui.util.kotlin.sample
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlinx.coroutines.channels.awaitClose
|
import kotlinx.coroutines.channels.awaitClose
|
||||||
import kotlinx.coroutines.delay
|
import kotlinx.coroutines.delay
|
||||||
@@ -95,6 +97,9 @@ constructor(
|
|||||||
awaitClose { commandQueue.removeCallback(callback) }
|
awaitClose { commandQueue.removeCallback(callback) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** The device wake/sleep state */
|
||||||
|
val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
|
* Dozing and dreaming have overlapping events. If the doze state remains in FINISH, it means
|
||||||
* that doze mode is not running and DREAMING is ok to commence.
|
* that doze mode is not running and DREAMING is ok to commence.
|
||||||
@@ -109,6 +114,12 @@ constructor(
|
|||||||
isDreaming && isDozeOff(dozeTransitionModel.to)
|
isDreaming && isDozeOff(dozeTransitionModel.to)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.sample(
|
||||||
|
wakefulnessModel,
|
||||||
|
{ isAbleToDream, wakefulnessModel ->
|
||||||
|
isAbleToDream && isWakingOrStartingToWake(wakefulnessModel)
|
||||||
|
}
|
||||||
|
)
|
||||||
.flatMapLatest { isAbleToDream ->
|
.flatMapLatest { isAbleToDream ->
|
||||||
flow {
|
flow {
|
||||||
delay(50)
|
delay(50)
|
||||||
@@ -119,6 +130,8 @@ constructor(
|
|||||||
|
|
||||||
/** Whether the keyguard is showing or not. */
|
/** Whether the keyguard is showing or not. */
|
||||||
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
|
val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
|
||||||
|
/** Whether the keyguard is unlocked or not. */
|
||||||
|
val isKeyguardUnlocked: Flow<Boolean> = repository.isKeyguardUnlocked
|
||||||
/** Whether the keyguard is occluded (covered by an activity). */
|
/** Whether the keyguard is occluded (covered by an activity). */
|
||||||
val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
|
val isKeyguardOccluded: Flow<Boolean> = repository.isKeyguardOccluded
|
||||||
/** Whether the keyguard is going away. */
|
/** Whether the keyguard is going away. */
|
||||||
@@ -127,8 +140,6 @@ constructor(
|
|||||||
val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
|
val primaryBouncerShowing: Flow<Boolean> = bouncerRepository.primaryBouncerVisible
|
||||||
/** Whether the alternate bouncer is showing or not. */
|
/** Whether the alternate bouncer is showing or not. */
|
||||||
val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
|
val alternateBouncerShowing: Flow<Boolean> = bouncerRepository.alternateBouncerVisible
|
||||||
/** The device wake/sleep state */
|
|
||||||
val wakefulnessModel: Flow<WakefulnessModel> = repository.wakefulness
|
|
||||||
/** Observable for the [StatusBarState] */
|
/** Observable for the [StatusBarState] */
|
||||||
val statusBarState: Flow<StatusBarState> = repository.statusBarState
|
val statusBarState: Flow<StatusBarState> = repository.statusBarState
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -61,7 +61,15 @@ constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
keyguardInteractor.isDreaming.collect { logger.log(TAG, VERBOSE, "isDreaming", it) }
|
keyguardInteractor.isAbleToDream.collect {
|
||||||
|
logger.log(TAG, VERBOSE, "isAbleToDream", it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scope.launch {
|
||||||
|
keyguardInteractor.isKeyguardOccluded.collect {
|
||||||
|
logger.log(TAG, VERBOSE, "isOccluded", it)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
scope.launch {
|
scope.launch {
|
||||||
|
|||||||
@@ -78,6 +78,10 @@ constructor(
|
|||||||
val occludedToLockscreenTransition: Flow<TransitionStep> =
|
val occludedToLockscreenTransition: Flow<TransitionStep> =
|
||||||
repository.transition(OCCLUDED, LOCKSCREEN)
|
repository.transition(OCCLUDED, LOCKSCREEN)
|
||||||
|
|
||||||
|
/** PRIMARY_BOUNCER->GONE transition information. */
|
||||||
|
val primaryBouncerToGoneTransition: Flow<TransitionStep> =
|
||||||
|
repository.transition(PRIMARY_BOUNCER, GONE)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
|
* AOD<->LOCKSCREEN transition information, mapped to dozeAmount range of AOD (1f) <->
|
||||||
* Lockscreen (0f).
|
* Lockscreen (0f).
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ class KeyguardTransitionAnimationFlow(
|
|||||||
duration: Duration,
|
duration: Duration,
|
||||||
onStep: (Float) -> Float,
|
onStep: (Float) -> Float,
|
||||||
startTime: Duration = 0.milliseconds,
|
startTime: Duration = 0.milliseconds,
|
||||||
|
onStart: (() -> Unit)? = null,
|
||||||
onCancel: (() -> Float)? = null,
|
onCancel: (() -> Float)? = null,
|
||||||
onFinish: (() -> Float)? = null,
|
onFinish: (() -> Float)? = null,
|
||||||
interpolator: Interpolator = LINEAR,
|
interpolator: Interpolator = LINEAR,
|
||||||
@@ -73,6 +74,7 @@ class KeyguardTransitionAnimationFlow(
|
|||||||
// the ViewModels of the last update
|
// the ViewModels of the last update
|
||||||
STARTED -> {
|
STARTED -> {
|
||||||
isComplete = false
|
isComplete = false
|
||||||
|
onStart?.invoke()
|
||||||
max(0f, min(1f, value))
|
max(0f, min(1f, value))
|
||||||
}
|
}
|
||||||
// Always send a final value of 1. Because of rounding, [value] may never be
|
// Always send a final value of 1. Because of rounding, [value] may never be
|
||||||
|
|||||||
@@ -31,6 +31,7 @@ import com.android.settingslib.Utils
|
|||||||
import com.android.systemui.keyguard.data.BouncerViewDelegate
|
import com.android.systemui.keyguard.data.BouncerViewDelegate
|
||||||
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
|
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants.EXPANSION_VISIBLE
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
|
||||||
import com.android.systemui.lifecycle.repeatWhenAttached
|
import com.android.systemui.lifecycle.repeatWhenAttached
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import kotlinx.coroutines.awaitCancellation
|
import kotlinx.coroutines.awaitCancellation
|
||||||
@@ -44,6 +45,7 @@ object KeyguardBouncerViewBinder {
|
|||||||
fun bind(
|
fun bind(
|
||||||
view: ViewGroup,
|
view: ViewGroup,
|
||||||
viewModel: KeyguardBouncerViewModel,
|
viewModel: KeyguardBouncerViewModel,
|
||||||
|
primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel,
|
||||||
componentFactory: KeyguardBouncerComponent.Factory
|
componentFactory: KeyguardBouncerComponent.Factory
|
||||||
) {
|
) {
|
||||||
// Builds the KeyguardSecurityContainerController from bouncer view group.
|
// Builds the KeyguardSecurityContainerController from bouncer view group.
|
||||||
@@ -144,6 +146,12 @@ object KeyguardBouncerViewBinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
launch {
|
||||||
|
primaryBouncerToGoneTransitionViewModel.bouncerAlpha.collect { alpha ->
|
||||||
|
securityContainerController.setAlpha(alpha)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
launch {
|
launch {
|
||||||
viewModel.bouncerExpansionAmount
|
viewModel.bouncerExpansionAmount
|
||||||
.filter { it == EXPANSION_VISIBLE }
|
.filter { it == EXPANSION_VISIBLE }
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.ui.viewmodel
|
||||||
|
|
||||||
|
import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
|
||||||
|
import com.android.systemui.dagger.SysUISingleton
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.FromPrimaryBouncerTransitionInteractor.Companion.TO_GONE_DURATION
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
|
import com.android.systemui.keyguard.ui.KeyguardTransitionAnimationFlow
|
||||||
|
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Breaks down PRIMARY_BOUNCER->GONE transition into discrete steps for corresponding views to
|
||||||
|
* consume.
|
||||||
|
*/
|
||||||
|
@SysUISingleton
|
||||||
|
class PrimaryBouncerToGoneTransitionViewModel
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val interactor: KeyguardTransitionInteractor,
|
||||||
|
private val statusBarStateController: SysuiStatusBarStateController,
|
||||||
|
) {
|
||||||
|
private val transitionAnimation =
|
||||||
|
KeyguardTransitionAnimationFlow(
|
||||||
|
transitionDuration = TO_GONE_DURATION,
|
||||||
|
transitionFlow = interactor.primaryBouncerToGoneTransition,
|
||||||
|
)
|
||||||
|
|
||||||
|
private var leaveShadeOpen: Boolean = false
|
||||||
|
|
||||||
|
/** Bouncer container alpha */
|
||||||
|
val bouncerAlpha: Flow<Float> =
|
||||||
|
transitionAnimation.createFlow(
|
||||||
|
duration = 200.milliseconds,
|
||||||
|
onStep = { 1f - it },
|
||||||
|
)
|
||||||
|
|
||||||
|
/** Scrim behind alpha */
|
||||||
|
val scrimBehindAlpha: Flow<Float> =
|
||||||
|
transitionAnimation.createFlow(
|
||||||
|
duration = TO_GONE_DURATION,
|
||||||
|
interpolator = EMPHASIZED_ACCELERATE,
|
||||||
|
onStart = { leaveShadeOpen = statusBarStateController.leaveOpenOnKeyguardHide() },
|
||||||
|
onStep = {
|
||||||
|
if (leaveShadeOpen) {
|
||||||
|
1f
|
||||||
|
} else {
|
||||||
|
1f - it
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -45,6 +45,7 @@ import com.android.systemui.keyguard.shared.model.TransitionState;
|
|||||||
import com.android.systemui.keyguard.shared.model.TransitionStep;
|
import com.android.systemui.keyguard.shared.model.TransitionStep;
|
||||||
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
|
import com.android.systemui.keyguard.ui.binder.KeyguardBouncerViewBinder;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
|
||||||
import com.android.systemui.statusbar.DragDownHelper;
|
import com.android.systemui.statusbar.DragDownHelper;
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationInsetsController;
|
import com.android.systemui.statusbar.NotificationInsetsController;
|
||||||
@@ -133,7 +134,8 @@ public class NotificationShadeWindowViewController {
|
|||||||
KeyguardBouncerViewModel keyguardBouncerViewModel,
|
KeyguardBouncerViewModel keyguardBouncerViewModel,
|
||||||
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
|
KeyguardBouncerComponent.Factory keyguardBouncerComponentFactory,
|
||||||
AlternateBouncerInteractor alternateBouncerInteractor,
|
AlternateBouncerInteractor alternateBouncerInteractor,
|
||||||
KeyguardTransitionInteractor keyguardTransitionInteractor
|
KeyguardTransitionInteractor keyguardTransitionInteractor,
|
||||||
|
PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel
|
||||||
) {
|
) {
|
||||||
mLockscreenShadeTransitionController = transitionController;
|
mLockscreenShadeTransitionController = transitionController;
|
||||||
mFalsingCollector = falsingCollector;
|
mFalsingCollector = falsingCollector;
|
||||||
@@ -160,6 +162,7 @@ public class NotificationShadeWindowViewController {
|
|||||||
KeyguardBouncerViewBinder.bind(
|
KeyguardBouncerViewBinder.bind(
|
||||||
mView.findViewById(R.id.keyguard_bouncer_container),
|
mView.findViewById(R.id.keyguard_bouncer_container),
|
||||||
keyguardBouncerViewModel,
|
keyguardBouncerViewModel,
|
||||||
|
primaryBouncerToGoneTransitionViewModel,
|
||||||
keyguardBouncerComponentFactory);
|
keyguardBouncerComponentFactory);
|
||||||
|
|
||||||
collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
|
collectFlow(mView, keyguardTransitionInteractor.getLockscreenToDreamingTransition(),
|
||||||
|
|||||||
@@ -3695,6 +3695,12 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
|
|||||||
@Override
|
@Override
|
||||||
public void notifyBiometricAuthModeChanged() {
|
public void notifyBiometricAuthModeChanged() {
|
||||||
mDozeServiceHost.updateDozing();
|
mDozeServiceHost.updateDozing();
|
||||||
|
if (mBiometricUnlockController.getMode()
|
||||||
|
== BiometricUnlockController.MODE_DISMISS_BOUNCER) {
|
||||||
|
// Don't update the scrim controller at this time, in favor of the transition repository
|
||||||
|
// updating the scrim
|
||||||
|
return;
|
||||||
|
}
|
||||||
updateScrimController();
|
updateScrimController();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
package com.android.systemui.statusbar.phone;
|
package com.android.systemui.statusbar.phone;
|
||||||
|
|
||||||
|
import static com.android.systemui.util.kotlin.JavaAdapterKt.collectFlow;
|
||||||
|
|
||||||
import static java.lang.Float.isNaN;
|
import static java.lang.Float.isNaN;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
@@ -53,9 +55,14 @@ import com.android.systemui.dagger.SysUISingleton;
|
|||||||
import com.android.systemui.dagger.qualifiers.Main;
|
import com.android.systemui.dagger.qualifiers.Main;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||||
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
|
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState;
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionStep;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
|
||||||
import com.android.systemui.scrim.ScrimView;
|
import com.android.systemui.scrim.ScrimView;
|
||||||
import com.android.systemui.shade.NotificationPanelViewController;
|
import com.android.systemui.shade.NotificationPanelViewController;
|
||||||
|
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||||
import com.android.systemui.statusbar.notification.stack.ViewState;
|
import com.android.systemui.statusbar.notification.stack.ViewState;
|
||||||
import com.android.systemui.statusbar.policy.ConfigurationController;
|
import com.android.systemui.statusbar.policy.ConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
@@ -71,6 +78,8 @@ import java.util.function.Consumer;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Controls both the scrim behind the notifications and in front of the notifications (when a
|
* Controls both the scrim behind the notifications and in front of the notifications (when a
|
||||||
* security method gets shown).
|
* security method gets shown).
|
||||||
@@ -197,6 +206,7 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
private final ScreenOffAnimationController mScreenOffAnimationController;
|
private final ScreenOffAnimationController mScreenOffAnimationController;
|
||||||
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
private final KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
private final StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||||
|
private final SysuiStatusBarStateController mStatusBarStateController;
|
||||||
|
|
||||||
private GradientColors mColors;
|
private GradientColors mColors;
|
||||||
private boolean mNeedsDrawableColorUpdate;
|
private boolean mNeedsDrawableColorUpdate;
|
||||||
@@ -251,6 +261,20 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
private boolean mWakeLockHeld;
|
private boolean mWakeLockHeld;
|
||||||
private boolean mKeyguardOccluded;
|
private boolean mKeyguardOccluded;
|
||||||
|
|
||||||
|
private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
||||||
|
private CoroutineDispatcher mMainDispatcher;
|
||||||
|
private boolean mIsBouncerToGoneTransitionRunning = false;
|
||||||
|
private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
|
||||||
|
private final Consumer<Float> mScrimAlphaConsumer =
|
||||||
|
(Float alpha) -> {
|
||||||
|
mScrimInFront.setViewAlpha(mInFrontAlpha);
|
||||||
|
mNotificationsScrim.setViewAlpha(mNotificationsAlpha);
|
||||||
|
mBehindAlpha = alpha;
|
||||||
|
mScrimBehind.setViewAlpha(alpha);
|
||||||
|
};
|
||||||
|
|
||||||
|
Consumer<TransitionStep> mPrimaryBouncerToGoneTransition;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ScrimController(
|
public ScrimController(
|
||||||
LightBarController lightBarController,
|
LightBarController lightBarController,
|
||||||
@@ -265,13 +289,18 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
@Main Executor mainExecutor,
|
@Main Executor mainExecutor,
|
||||||
ScreenOffAnimationController screenOffAnimationController,
|
ScreenOffAnimationController screenOffAnimationController,
|
||||||
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
KeyguardUnlockAnimationController keyguardUnlockAnimationController,
|
||||||
StatusBarKeyguardViewManager statusBarKeyguardViewManager) {
|
StatusBarKeyguardViewManager statusBarKeyguardViewManager,
|
||||||
|
PrimaryBouncerToGoneTransitionViewModel primaryBouncerToGoneTransitionViewModel,
|
||||||
|
KeyguardTransitionInteractor keyguardTransitionInteractor,
|
||||||
|
SysuiStatusBarStateController sysuiStatusBarStateController,
|
||||||
|
@Main CoroutineDispatcher mainDispatcher) {
|
||||||
mScrimStateListener = lightBarController::setScrimState;
|
mScrimStateListener = lightBarController::setScrimState;
|
||||||
mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
|
mDefaultScrimAlpha = BUSY_SCRIM_ALPHA;
|
||||||
|
|
||||||
mKeyguardStateController = keyguardStateController;
|
mKeyguardStateController = keyguardStateController;
|
||||||
mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
|
mDarkenWhileDragging = !mKeyguardStateController.canDismissLockScreen();
|
||||||
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
mKeyguardUpdateMonitor = keyguardUpdateMonitor;
|
||||||
|
mStatusBarStateController = sysuiStatusBarStateController;
|
||||||
mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
|
mKeyguardVisibilityCallback = new KeyguardVisibilityCallback();
|
||||||
mHandler = handler;
|
mHandler = handler;
|
||||||
mMainExecutor = mainExecutor;
|
mMainExecutor = mainExecutor;
|
||||||
@@ -304,6 +333,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
mColors = new GradientColors();
|
mColors = new GradientColors();
|
||||||
|
mPrimaryBouncerToGoneTransitionViewModel = primaryBouncerToGoneTransitionViewModel;
|
||||||
|
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
|
||||||
|
mMainDispatcher = mainDispatcher;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -343,6 +375,33 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
for (ScrimState state : ScrimState.values()) {
|
for (ScrimState state : ScrimState.values()) {
|
||||||
state.prepare(state);
|
state.prepare(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Directly control transition to UNLOCKED scrim state from PRIMARY_BOUNCER, and make sure
|
||||||
|
// to report back that keyguard has faded away. This fixes cases where the scrim state was
|
||||||
|
// rapidly switching on unlock, due to shifts in state in CentralSurfacesImpl
|
||||||
|
mPrimaryBouncerToGoneTransition =
|
||||||
|
(TransitionStep step) -> {
|
||||||
|
TransitionState state = step.getTransitionState();
|
||||||
|
|
||||||
|
mIsBouncerToGoneTransitionRunning = state == TransitionState.RUNNING;
|
||||||
|
|
||||||
|
if (state == TransitionState.STARTED) {
|
||||||
|
setExpansionAffectsAlpha(false);
|
||||||
|
transitionTo(ScrimState.UNLOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (state == TransitionState.FINISHED || state == TransitionState.CANCELED) {
|
||||||
|
setExpansionAffectsAlpha(true);
|
||||||
|
if (mKeyguardStateController.isKeyguardFadingAway()) {
|
||||||
|
mStatusBarKeyguardViewManager.onKeyguardFadedAway();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
collectFlow(behindScrim, mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition(),
|
||||||
|
mPrimaryBouncerToGoneTransition, mMainDispatcher);
|
||||||
|
collectFlow(behindScrim, mPrimaryBouncerToGoneTransitionViewModel.getScrimBehindAlpha(),
|
||||||
|
mScrimAlphaConsumer, mMainDispatcher);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -365,6 +424,11 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void transitionTo(ScrimState state, Callback callback) {
|
public void transitionTo(ScrimState state, Callback callback) {
|
||||||
|
if (mIsBouncerToGoneTransitionRunning) {
|
||||||
|
Log.i(TAG, "Skipping transition to: " + state
|
||||||
|
+ " while mIsBouncerToGoneTransitionRunning");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (state == mState) {
|
if (state == mState) {
|
||||||
// Call the callback anyway, unless it's already enqueued
|
// Call the callback anyway, unless it's already enqueued
|
||||||
if (callback != null && mCallback != callback) {
|
if (callback != null && mCallback != callback) {
|
||||||
@@ -1036,7 +1100,8 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
mBehindAlpha = 1;
|
mBehindAlpha = 1;
|
||||||
}
|
}
|
||||||
// Prevent notification scrim flicker when transitioning away from keyguard.
|
// Prevent notification scrim flicker when transitioning away from keyguard.
|
||||||
if (mKeyguardStateController.isKeyguardGoingAway()) {
|
if (mKeyguardStateController.isKeyguardGoingAway()
|
||||||
|
&& !mStatusBarStateController.leaveOpenOnKeyguardHide()) {
|
||||||
mNotificationsAlpha = 0;
|
mNotificationsAlpha = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1125,7 +1190,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
|
Trace.traceCounter(Trace.TRACE_TAG_APP, getScrimName(scrimView) + "_tint",
|
||||||
Color.alpha(tint));
|
Color.alpha(tint));
|
||||||
scrimView.setTint(tint);
|
scrimView.setTint(tint);
|
||||||
|
if (!mIsBouncerToGoneTransitionRunning) {
|
||||||
scrimView.setViewAlpha(alpha);
|
scrimView.setViewAlpha(alpha);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
scrim.setAlpha(alpha);
|
scrim.setAlpha(alpha);
|
||||||
}
|
}
|
||||||
@@ -1473,6 +1540,9 @@ public class ScrimController implements ViewTreeObserver.OnPreDrawListener, Dump
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void setKeyguardOccluded(boolean keyguardOccluded) {
|
public void setKeyguardOccluded(boolean keyguardOccluded) {
|
||||||
|
if (mKeyguardOccluded == keyguardOccluded) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
mKeyguardOccluded = keyguardOccluded;
|
mKeyguardOccluded = keyguardOccluded;
|
||||||
updateScrims();
|
updateScrims();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -218,6 +218,29 @@ class KeyguardRepositoryImplTest : SysuiTestCase() {
|
|||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun isKeyguardUnlocked() =
|
||||||
|
runTest(UnconfinedTestDispatcher()) {
|
||||||
|
whenever(keyguardStateController.isUnlocked).thenReturn(false)
|
||||||
|
var latest: Boolean? = null
|
||||||
|
val job = underTest.isKeyguardUnlocked.onEach { latest = it }.launchIn(this)
|
||||||
|
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
val captor = argumentCaptor<KeyguardStateController.Callback>()
|
||||||
|
verify(keyguardStateController).addCallback(captor.capture())
|
||||||
|
|
||||||
|
whenever(keyguardStateController.isUnlocked).thenReturn(true)
|
||||||
|
captor.value.onUnlockedChanged()
|
||||||
|
assertThat(latest).isTrue()
|
||||||
|
|
||||||
|
whenever(keyguardStateController.isUnlocked).thenReturn(false)
|
||||||
|
captor.value.onUnlockedChanged()
|
||||||
|
assertThat(latest).isFalse()
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun isDozing() =
|
fun isDozing() =
|
||||||
runTest(UnconfinedTestDispatcher()) {
|
runTest(UnconfinedTestDispatcher()) {
|
||||||
|
|||||||
@@ -19,6 +19,8 @@ package com.android.systemui.keyguard.domain.interactor
|
|||||||
import android.animation.ValueAnimator
|
import android.animation.ValueAnimator
|
||||||
import androidx.test.filters.FlakyTest
|
import androidx.test.filters.FlakyTest
|
||||||
import androidx.test.filters.SmallTest
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel
|
||||||
|
import com.android.keyguard.KeyguardSecurityModel.SecurityMode.PIN
|
||||||
import com.android.systemui.SysuiTestCase
|
import com.android.systemui.SysuiTestCase
|
||||||
import com.android.systemui.animation.Interpolators
|
import com.android.systemui.animation.Interpolators
|
||||||
import com.android.systemui.flags.FakeFeatureFlags
|
import com.android.systemui.flags.FakeFeatureFlags
|
||||||
@@ -40,6 +42,7 @@ import com.android.systemui.keyguard.util.KeyguardTransitionRunner
|
|||||||
import com.android.systemui.shade.data.repository.FakeShadeRepository
|
import com.android.systemui.shade.data.repository.FakeShadeRepository
|
||||||
import com.android.systemui.shade.data.repository.ShadeRepository
|
import com.android.systemui.shade.data.repository.ShadeRepository
|
||||||
import com.android.systemui.statusbar.CommandQueue
|
import com.android.systemui.statusbar.CommandQueue
|
||||||
|
import com.android.systemui.util.mockito.whenever
|
||||||
import com.android.systemui.util.mockito.withArgCaptor
|
import com.android.systemui.util.mockito.withArgCaptor
|
||||||
import com.google.common.truth.Truth.assertThat
|
import com.google.common.truth.Truth.assertThat
|
||||||
import kotlinx.coroutines.cancelChildren
|
import kotlinx.coroutines.cancelChildren
|
||||||
@@ -51,6 +54,8 @@ import org.junit.Before
|
|||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
import org.junit.runner.RunWith
|
import org.junit.runner.RunWith
|
||||||
import org.junit.runners.JUnit4
|
import org.junit.runners.JUnit4
|
||||||
|
import org.mockito.ArgumentMatchers.anyBoolean
|
||||||
|
import org.mockito.ArgumentMatchers.anyInt
|
||||||
import org.mockito.Mock
|
import org.mockito.Mock
|
||||||
import org.mockito.Mockito.reset
|
import org.mockito.Mockito.reset
|
||||||
import org.mockito.Mockito.verify
|
import org.mockito.Mockito.verify
|
||||||
@@ -77,6 +82,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
// Used to verify transition requests for test output
|
// Used to verify transition requests for test output
|
||||||
@Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
|
@Mock private lateinit var mockTransitionRepository: KeyguardTransitionRepository
|
||||||
@Mock private lateinit var commandQueue: CommandQueue
|
@Mock private lateinit var commandQueue: CommandQueue
|
||||||
|
@Mock private lateinit var keyguardSecurityModel: KeyguardSecurityModel
|
||||||
|
|
||||||
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
|
private lateinit var fromLockscreenTransitionInteractor: FromLockscreenTransitionInteractor
|
||||||
private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
|
private lateinit var fromDreamingTransitionInteractor: FromDreamingTransitionInteractor
|
||||||
@@ -102,6 +108,8 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
transitionRepository = KeyguardTransitionRepositoryImpl()
|
transitionRepository = KeyguardTransitionRepositoryImpl()
|
||||||
runner = KeyguardTransitionRunner(transitionRepository)
|
runner = KeyguardTransitionRunner(transitionRepository)
|
||||||
|
|
||||||
|
whenever(keyguardSecurityModel.getSecurityMode(anyInt())).thenReturn(PIN)
|
||||||
|
|
||||||
val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
|
val featureFlags = FakeFeatureFlags().apply { set(Flags.FACE_AUTH_REFACTOR, true) }
|
||||||
fromLockscreenTransitionInteractor =
|
fromLockscreenTransitionInteractor =
|
||||||
FromLockscreenTransitionInteractor(
|
FromLockscreenTransitionInteractor(
|
||||||
@@ -173,16 +181,17 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
keyguardInteractor = createKeyguardInteractor(featureFlags),
|
keyguardInteractor = createKeyguardInteractor(featureFlags),
|
||||||
keyguardTransitionRepository = mockTransitionRepository,
|
keyguardTransitionRepository = mockTransitionRepository,
|
||||||
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
|
keyguardTransitionInteractor = KeyguardTransitionInteractor(transitionRepository),
|
||||||
|
keyguardSecurityModel = keyguardSecurityModel,
|
||||||
)
|
)
|
||||||
fromPrimaryBouncerTransitionInteractor.start()
|
fromPrimaryBouncerTransitionInteractor.start()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun `DREAMING to LOCKSCREEN - dreaming state changes first`() =
|
fun `DREAMING to LOCKSCREEN`() =
|
||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
// GIVEN a device is dreaming and occluded
|
// GIVEN a device is dreaming
|
||||||
keyguardRepository.setDreamingWithOverlay(true)
|
keyguardRepository.setDreamingWithOverlay(true)
|
||||||
keyguardRepository.setKeyguardOccluded(true)
|
keyguardRepository.setWakefulnessModel(startingToWake())
|
||||||
runCurrent()
|
runCurrent()
|
||||||
|
|
||||||
// GIVEN a prior transition has run to DREAMING
|
// GIVEN a prior transition has run to DREAMING
|
||||||
@@ -215,56 +224,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
|
||||||
// THEN a transition to BOUNCER should occur
|
|
||||||
assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
|
|
||||||
assertThat(info.from).isEqualTo(KeyguardState.DREAMING)
|
|
||||||
assertThat(info.to).isEqualTo(KeyguardState.LOCKSCREEN)
|
|
||||||
assertThat(info.animator).isNotNull()
|
|
||||||
|
|
||||||
coroutineContext.cancelChildren()
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun `DREAMING to LOCKSCREEN - occluded state changes first`() =
|
|
||||||
testScope.runTest {
|
|
||||||
// GIVEN a device is dreaming and occluded
|
|
||||||
keyguardRepository.setDreamingWithOverlay(true)
|
|
||||||
keyguardRepository.setKeyguardOccluded(true)
|
|
||||||
runCurrent()
|
|
||||||
|
|
||||||
// GIVEN a prior transition has run to DREAMING
|
|
||||||
runner.startTransition(
|
|
||||||
testScope,
|
|
||||||
TransitionInfo(
|
|
||||||
ownerName = "",
|
|
||||||
from = KeyguardState.LOCKSCREEN,
|
|
||||||
to = KeyguardState.DREAMING,
|
|
||||||
animator =
|
|
||||||
ValueAnimator().apply {
|
|
||||||
duration = 10
|
|
||||||
interpolator = Interpolators.LINEAR
|
|
||||||
},
|
|
||||||
)
|
|
||||||
)
|
|
||||||
runCurrent()
|
|
||||||
reset(mockTransitionRepository)
|
|
||||||
|
|
||||||
// WHEN doze is complete
|
|
||||||
keyguardRepository.setDozeTransitionModel(
|
|
||||||
DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
|
|
||||||
)
|
|
||||||
// AND occluded has stopped
|
|
||||||
keyguardRepository.setKeyguardOccluded(false)
|
|
||||||
advanceUntilIdle()
|
|
||||||
// AND then dreaming has stopped
|
|
||||||
keyguardRepository.setDreamingWithOverlay(false)
|
|
||||||
advanceUntilIdle()
|
|
||||||
|
|
||||||
val info =
|
|
||||||
withArgCaptor<TransitionInfo> {
|
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
|
||||||
}
|
}
|
||||||
// THEN a transition to BOUNCER should occur
|
// THEN a transition to BOUNCER should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromDreamingTransitionInteractor")
|
||||||
@@ -304,7 +264,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to PRIMARY_BOUNCER should occur
|
// THEN a transition to PRIMARY_BOUNCER should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
||||||
@@ -345,7 +305,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
|
||||||
@@ -386,7 +346,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromOccludedTransitionInteractor")
|
||||||
@@ -427,7 +387,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
||||||
@@ -468,7 +428,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromLockscreenTransitionInteractor")
|
||||||
@@ -505,7 +465,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
|
||||||
@@ -542,7 +502,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromDozingTransitionInteractor")
|
||||||
@@ -583,7 +543,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
||||||
@@ -624,7 +584,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to AOD should occur
|
// THEN a transition to AOD should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
||||||
@@ -661,7 +621,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to AOD should occur
|
// THEN a transition to AOD should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
||||||
@@ -677,6 +637,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
testScope.runTest {
|
testScope.runTest {
|
||||||
// GIVEN a device that is not dreaming or dozing
|
// GIVEN a device that is not dreaming or dozing
|
||||||
keyguardRepository.setDreamingWithOverlay(false)
|
keyguardRepository.setDreamingWithOverlay(false)
|
||||||
|
keyguardRepository.setWakefulnessModel(startingToWake())
|
||||||
keyguardRepository.setDozeTransitionModel(
|
keyguardRepository.setDozeTransitionModel(
|
||||||
DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
|
DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
|
||||||
)
|
)
|
||||||
@@ -704,7 +665,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DREAMING should occur
|
// THEN a transition to DREAMING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
||||||
@@ -741,7 +702,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to PRIMARY_BOUNCER should occur
|
// THEN a transition to PRIMARY_BOUNCER should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
||||||
@@ -784,7 +745,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to AOD should occur
|
// THEN a transition to AOD should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
||||||
@@ -828,7 +789,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
||||||
@@ -870,7 +831,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to LOCKSCREEN should occur
|
// THEN a transition to LOCKSCREEN should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromAlternateBouncerTransitionInteractor")
|
||||||
@@ -912,7 +873,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to AOD should occur
|
// THEN a transition to AOD should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
|
||||||
@@ -954,7 +915,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to DOZING should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
|
||||||
@@ -995,7 +956,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture(), anyBoolean())
|
||||||
}
|
}
|
||||||
// THEN a transition to LOCKSCREEN should occur
|
// THEN a transition to LOCKSCREEN should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromPrimaryBouncerTransitionInteractor")
|
||||||
|
|||||||
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2023 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.ui.viewmodel
|
||||||
|
|
||||||
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
|
import androidx.test.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
|
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||||
|
import com.android.systemui.statusbar.SysuiStatusBarStateController
|
||||||
|
import com.android.systemui.util.mockito.whenever
|
||||||
|
import com.google.common.collect.Range
|
||||||
|
import com.google.common.truth.Truth.assertThat
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.test.UnconfinedTestDispatcher
|
||||||
|
import kotlinx.coroutines.test.runTest
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
import org.junit.runner.RunWith
|
||||||
|
import org.mockito.Mock
|
||||||
|
import org.mockito.MockitoAnnotations
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(AndroidJUnit4::class)
|
||||||
|
class PrimaryBouncerToGoneTransitionViewModelTest : SysuiTestCase() {
|
||||||
|
private lateinit var underTest: PrimaryBouncerToGoneTransitionViewModel
|
||||||
|
private lateinit var repository: FakeKeyguardTransitionRepository
|
||||||
|
@Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
MockitoAnnotations.initMocks(this)
|
||||||
|
repository = FakeKeyguardTransitionRepository()
|
||||||
|
val interactor = KeyguardTransitionInteractor(repository)
|
||||||
|
underTest = PrimaryBouncerToGoneTransitionViewModel(interactor, statusBarStateController)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun scrimBehindAlpha_leaveShadeOpen() =
|
||||||
|
runTest(UnconfinedTestDispatcher()) {
|
||||||
|
val values = mutableListOf<Float>()
|
||||||
|
|
||||||
|
val job = underTest.scrimBehindAlpha.onEach { values.add(it) }.launchIn(this)
|
||||||
|
|
||||||
|
whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(true)
|
||||||
|
|
||||||
|
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
|
||||||
|
repository.sendTransitionStep(step(0.3f))
|
||||||
|
repository.sendTransitionStep(step(0.6f))
|
||||||
|
repository.sendTransitionStep(step(1f))
|
||||||
|
|
||||||
|
assertThat(values.size).isEqualTo(4)
|
||||||
|
values.forEach { assertThat(it).isEqualTo(1f) }
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun scrimBehindAlpha_doNotLeaveShadeOpen() =
|
||||||
|
runTest(UnconfinedTestDispatcher()) {
|
||||||
|
val values = mutableListOf<Float>()
|
||||||
|
|
||||||
|
val job = underTest.scrimBehindAlpha.onEach { values.add(it) }.launchIn(this)
|
||||||
|
|
||||||
|
whenever(statusBarStateController.leaveOpenOnKeyguardHide()).thenReturn(false)
|
||||||
|
|
||||||
|
repository.sendTransitionStep(step(0f, TransitionState.STARTED))
|
||||||
|
repository.sendTransitionStep(step(0.3f))
|
||||||
|
repository.sendTransitionStep(step(0.6f))
|
||||||
|
repository.sendTransitionStep(step(1f))
|
||||||
|
|
||||||
|
assertThat(values.size).isEqualTo(4)
|
||||||
|
values.forEach { assertThat(it).isIn(Range.closed(0f, 1f)) }
|
||||||
|
assertThat(values[3]).isEqualTo(0f)
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun step(
|
||||||
|
value: Float,
|
||||||
|
state: TransitionState = TransitionState.RUNNING
|
||||||
|
): TransitionStep {
|
||||||
|
return TransitionStep(
|
||||||
|
from = KeyguardState.PRIMARY_BOUNCER,
|
||||||
|
to = KeyguardState.GONE,
|
||||||
|
value = value,
|
||||||
|
transitionState = state,
|
||||||
|
ownerName = "PrimaryBouncerToGoneTransitionViewModelTest"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -33,6 +33,7 @@ import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteracto
|
|||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionStep
|
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel
|
||||||
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
|
import com.android.systemui.shade.NotificationShadeWindowView.InteractionEventHandler
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController
|
||||||
import com.android.systemui.statusbar.NotificationInsetsController
|
import com.android.systemui.statusbar.NotificationInsetsController
|
||||||
@@ -65,48 +66,32 @@ import org.mockito.MockitoAnnotations
|
|||||||
@RunWith(AndroidTestingRunner::class)
|
@RunWith(AndroidTestingRunner::class)
|
||||||
@RunWithLooper(setAsMainLooper = true)
|
@RunWithLooper(setAsMainLooper = true)
|
||||||
class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
||||||
@Mock
|
@Mock private lateinit var view: NotificationShadeWindowView
|
||||||
private lateinit var view: NotificationShadeWindowView
|
@Mock private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
|
||||||
@Mock
|
@Mock private lateinit var centralSurfaces: CentralSurfaces
|
||||||
private lateinit var sysuiStatusBarStateController: SysuiStatusBarStateController
|
@Mock private lateinit var dockManager: DockManager
|
||||||
@Mock
|
@Mock private lateinit var notificationPanelViewController: NotificationPanelViewController
|
||||||
private lateinit var centralSurfaces: CentralSurfaces
|
@Mock private lateinit var notificationShadeDepthController: NotificationShadeDepthController
|
||||||
@Mock
|
@Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
|
||||||
private lateinit var dockManager: DockManager
|
@Mock private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
|
||||||
@Mock
|
@Mock private lateinit var ambientState: AmbientState
|
||||||
private lateinit var notificationPanelViewController: NotificationPanelViewController
|
@Mock private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
|
||||||
@Mock
|
@Mock private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
|
||||||
private lateinit var notificationShadeDepthController: NotificationShadeDepthController
|
@Mock private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
||||||
@Mock
|
@Mock private lateinit var statusBarWindowStateController: StatusBarWindowStateController
|
||||||
private lateinit var notificationShadeWindowController: NotificationShadeWindowController
|
|
||||||
@Mock
|
|
||||||
private lateinit var keyguardUnlockAnimationController: KeyguardUnlockAnimationController
|
|
||||||
@Mock
|
|
||||||
private lateinit var ambientState: AmbientState
|
|
||||||
@Mock
|
|
||||||
private lateinit var keyguardBouncerViewModel: KeyguardBouncerViewModel
|
|
||||||
@Mock
|
|
||||||
private lateinit var stackScrollLayoutController: NotificationStackScrollLayoutController
|
|
||||||
@Mock
|
|
||||||
private lateinit var statusBarKeyguardViewManager: StatusBarKeyguardViewManager
|
|
||||||
@Mock
|
|
||||||
private lateinit var statusBarWindowStateController: StatusBarWindowStateController
|
|
||||||
@Mock
|
@Mock
|
||||||
private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
|
private lateinit var lockscreenShadeTransitionController: LockscreenShadeTransitionController
|
||||||
@Mock
|
@Mock private lateinit var lockIconViewController: LockIconViewController
|
||||||
private lateinit var lockIconViewController: LockIconViewController
|
@Mock private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
||||||
@Mock
|
@Mock private lateinit var pulsingGestureListener: PulsingGestureListener
|
||||||
private lateinit var phoneStatusBarViewController: PhoneStatusBarViewController
|
@Mock private lateinit var notificationInsetsController: NotificationInsetsController
|
||||||
@Mock
|
@Mock private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
||||||
private lateinit var pulsingGestureListener: PulsingGestureListener
|
|
||||||
@Mock
|
|
||||||
private lateinit var notificationInsetsController: NotificationInsetsController
|
|
||||||
@Mock
|
|
||||||
private lateinit var alternateBouncerInteractor: AlternateBouncerInteractor
|
|
||||||
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
|
@Mock lateinit var keyguardBouncerComponentFactory: KeyguardBouncerComponent.Factory
|
||||||
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
|
@Mock lateinit var keyguardBouncerComponent: KeyguardBouncerComponent
|
||||||
@Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
|
@Mock lateinit var keyguardSecurityContainerController: KeyguardSecurityContainerController
|
||||||
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
@Mock lateinit var keyguardTransitionInteractor: KeyguardTransitionInteractor
|
||||||
|
@Mock
|
||||||
|
lateinit var primaryBouncerToGoneTransitionViewModel: PrimaryBouncerToGoneTransitionViewModel
|
||||||
|
|
||||||
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
private lateinit var interactionEventHandlerCaptor: ArgumentCaptor<InteractionEventHandler>
|
||||||
private lateinit var interactionEventHandler: InteractionEventHandler
|
private lateinit var interactionEventHandler: InteractionEventHandler
|
||||||
@@ -125,7 +110,8 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
.thenReturn(keyguardSecurityContainerController)
|
.thenReturn(keyguardSecurityContainerController)
|
||||||
whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
|
whenever(keyguardTransitionInteractor.lockscreenToDreamingTransition)
|
||||||
.thenReturn(emptyFlow<TransitionStep>())
|
.thenReturn(emptyFlow<TransitionStep>())
|
||||||
underTest = NotificationShadeWindowViewController(
|
underTest =
|
||||||
|
NotificationShadeWindowViewController(
|
||||||
lockscreenShadeTransitionController,
|
lockscreenShadeTransitionController,
|
||||||
FalsingCollectorFake(),
|
FalsingCollectorFake(),
|
||||||
sysuiStatusBarStateController,
|
sysuiStatusBarStateController,
|
||||||
@@ -148,11 +134,11 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
keyguardBouncerComponentFactory,
|
keyguardBouncerComponentFactory,
|
||||||
alternateBouncerInteractor,
|
alternateBouncerInteractor,
|
||||||
keyguardTransitionInteractor,
|
keyguardTransitionInteractor,
|
||||||
|
primaryBouncerToGoneTransitionViewModel,
|
||||||
)
|
)
|
||||||
underTest.setupExpandedStatusBar()
|
underTest.setupExpandedStatusBar()
|
||||||
|
|
||||||
interactionEventHandlerCaptor =
|
interactionEventHandlerCaptor = ArgumentCaptor.forClass(InteractionEventHandler::class.java)
|
||||||
ArgumentCaptor.forClass(InteractionEventHandler::class.java)
|
|
||||||
verify(view).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
|
verify(view).setInteractionEventHandler(interactionEventHandlerCaptor.capture())
|
||||||
interactionEventHandler = interactionEventHandlerCaptor.value
|
interactionEventHandler = interactionEventHandlerCaptor.value
|
||||||
}
|
}
|
||||||
@@ -184,14 +170,11 @@ class NotificationShadeWindowViewControllerTest : SysuiTestCase() {
|
|||||||
@Test
|
@Test
|
||||||
fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() {
|
fun handleDispatchTouchEvent_downTouchBelowViewThenAnotherTouch_sendsTouchToSb() {
|
||||||
underTest.setStatusBarViewController(phoneStatusBarViewController)
|
underTest.setStatusBarViewController(phoneStatusBarViewController)
|
||||||
val downEvBelow = MotionEvent.obtain(
|
val downEvBelow =
|
||||||
0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0
|
MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_DOWN, 0f, VIEW_BOTTOM + 4f, 0)
|
||||||
)
|
|
||||||
interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
|
interactionEventHandler.handleDispatchTouchEvent(downEvBelow)
|
||||||
|
|
||||||
val nextEvent = MotionEvent.obtain(
|
val nextEvent = MotionEvent.obtain(0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0)
|
||||||
0L, 0L, MotionEvent.ACTION_MOVE, 0f, VIEW_BOTTOM + 5f, 0
|
|
||||||
)
|
|
||||||
whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
|
whenever(phoneStatusBarViewController.sendTouchToView(nextEvent)).thenReturn(true)
|
||||||
|
|
||||||
val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
|
val returnVal = interactionEventHandler.handleDispatchTouchEvent(nextEvent)
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
|||||||
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
|
import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteractor;
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBouncerViewModel;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
|
||||||
import com.android.systemui.statusbar.DragDownHelper;
|
import com.android.systemui.statusbar.DragDownHelper;
|
||||||
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
import com.android.systemui.statusbar.LockscreenShadeTransitionController;
|
||||||
import com.android.systemui.statusbar.NotificationInsetsController;
|
import com.android.systemui.statusbar.NotificationInsetsController;
|
||||||
@@ -101,6 +102,7 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
@Mock private NotificationInsetsController mNotificationInsetsController;
|
@Mock private NotificationInsetsController mNotificationInsetsController;
|
||||||
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
|
@Mock private AlternateBouncerInteractor mAlternateBouncerInteractor;
|
||||||
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
||||||
|
@Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
|
||||||
|
|
||||||
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
@Captor private ArgumentCaptor<NotificationShadeWindowView.InteractionEventHandler>
|
||||||
mInteractionEventHandlerCaptor;
|
mInteractionEventHandlerCaptor;
|
||||||
@@ -150,7 +152,8 @@ public class NotificationShadeWindowViewTest extends SysuiTestCase {
|
|||||||
mKeyguardBouncerViewModel,
|
mKeyguardBouncerViewModel,
|
||||||
mKeyguardBouncerComponentFactory,
|
mKeyguardBouncerComponentFactory,
|
||||||
mAlternateBouncerInteractor,
|
mAlternateBouncerInteractor,
|
||||||
mKeyguardTransitionInteractor
|
mKeyguardTransitionInteractor,
|
||||||
|
mPrimaryBouncerToGoneTransitionViewModel
|
||||||
);
|
);
|
||||||
mController.setupExpandedStatusBar();
|
mController.setupExpandedStatusBar();
|
||||||
mController.setDragDownHelper(mDragDownHelper);
|
mController.setDragDownHelper(mDragDownHelper);
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import static com.android.systemui.statusbar.phone.ScrimState.SHADE_LOCKED;
|
|||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
|
import static kotlinx.coroutines.flow.FlowKt.emptyFlow;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.mockito.ArgumentMatchers.any;
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
import static org.mockito.ArgumentMatchers.anyFloat;
|
import static org.mockito.ArgumentMatchers.anyFloat;
|
||||||
@@ -58,8 +60,14 @@ import com.android.systemui.SysuiTestCase;
|
|||||||
import com.android.systemui.animation.ShadeInterpolation;
|
import com.android.systemui.animation.ShadeInterpolation;
|
||||||
import com.android.systemui.dock.DockManager;
|
import com.android.systemui.dock.DockManager;
|
||||||
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
import com.android.systemui.keyguard.KeyguardUnlockAnimationController;
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||||
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
|
import com.android.systemui.keyguard.shared.constants.KeyguardBouncerConstants;
|
||||||
|
import com.android.systemui.keyguard.shared.model.KeyguardState;
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState;
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionStep;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.PrimaryBouncerToGoneTransitionViewModel;
|
||||||
import com.android.systemui.scrim.ScrimView;
|
import com.android.systemui.scrim.ScrimView;
|
||||||
|
import com.android.systemui.statusbar.SysuiStatusBarStateController;
|
||||||
import com.android.systemui.statusbar.policy.FakeConfigurationController;
|
import com.android.systemui.statusbar.policy.FakeConfigurationController;
|
||||||
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
import com.android.systemui.statusbar.policy.KeyguardStateController;
|
||||||
import com.android.systemui.util.concurrency.FakeExecutor;
|
import com.android.systemui.util.concurrency.FakeExecutor;
|
||||||
@@ -85,8 +93,10 @@ import java.util.HashMap;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import kotlinx.coroutines.CoroutineDispatcher;
|
||||||
|
|
||||||
@RunWith(AndroidTestingRunner.class)
|
@RunWith(AndroidTestingRunner.class)
|
||||||
@TestableLooper.RunWithLooper
|
@TestableLooper.RunWithLooper(setAsMainLooper = true)
|
||||||
@SmallTest
|
@SmallTest
|
||||||
public class ScrimControllerTest extends SysuiTestCase {
|
public class ScrimControllerTest extends SysuiTestCase {
|
||||||
|
|
||||||
@@ -115,6 +125,11 @@ public class ScrimControllerTest extends SysuiTestCase {
|
|||||||
@Mock private DockManager mDockManager;
|
@Mock private DockManager mDockManager;
|
||||||
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
|
@Mock private ScreenOffAnimationController mScreenOffAnimationController;
|
||||||
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
@Mock private KeyguardUnlockAnimationController mKeyguardUnlockAnimationController;
|
||||||
|
@Mock private PrimaryBouncerToGoneTransitionViewModel mPrimaryBouncerToGoneTransitionViewModel;
|
||||||
|
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
||||||
|
@Mock private CoroutineDispatcher mMainDispatcher;
|
||||||
|
@Mock private SysuiStatusBarStateController mSysuiStatusBarStateController;
|
||||||
|
|
||||||
// TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
|
// TODO(b/204991468): Use a real PanelExpansionStateManager object once this bug is fixed. (The
|
||||||
// event-dispatch-on-registration pattern caused some of these unit tests to fail.)
|
// event-dispatch-on-registration pattern caused some of these unit tests to fail.)
|
||||||
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
@Mock private StatusBarKeyguardViewManager mStatusBarKeyguardViewManager;
|
||||||
@@ -225,13 +240,22 @@ public class ScrimControllerTest extends SysuiTestCase {
|
|||||||
when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
|
when(mDelayedWakeLockBuilder.build()).thenReturn(mWakeLock);
|
||||||
when(mDockManager.isDocked()).thenReturn(false);
|
when(mDockManager.isDocked()).thenReturn(false);
|
||||||
|
|
||||||
|
when(mKeyguardTransitionInteractor.getPrimaryBouncerToGoneTransition())
|
||||||
|
.thenReturn(emptyFlow());
|
||||||
|
when(mPrimaryBouncerToGoneTransitionViewModel.getScrimBehindAlpha())
|
||||||
|
.thenReturn(emptyFlow());
|
||||||
|
|
||||||
mScrimController = new ScrimController(mLightBarController,
|
mScrimController = new ScrimController(mLightBarController,
|
||||||
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
|
mDozeParameters, mAlarmManager, mKeyguardStateController, mDelayedWakeLockBuilder,
|
||||||
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
|
new FakeHandler(mLooper.getLooper()), mKeyguardUpdateMonitor,
|
||||||
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
|
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
|
||||||
mScreenOffAnimationController,
|
mScreenOffAnimationController,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mStatusBarKeyguardViewManager);
|
mStatusBarKeyguardViewManager,
|
||||||
|
mPrimaryBouncerToGoneTransitionViewModel,
|
||||||
|
mKeyguardTransitionInteractor,
|
||||||
|
mSysuiStatusBarStateController,
|
||||||
|
mMainDispatcher);
|
||||||
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
|
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
|
||||||
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
|
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
|
||||||
mScrimController.setAnimatorListener(mAnimatorListener);
|
mScrimController.setAnimatorListener(mAnimatorListener);
|
||||||
@@ -861,7 +885,11 @@ public class ScrimControllerTest extends SysuiTestCase {
|
|||||||
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
|
mDockManager, mConfigurationController, new FakeExecutor(new FakeSystemClock()),
|
||||||
mScreenOffAnimationController,
|
mScreenOffAnimationController,
|
||||||
mKeyguardUnlockAnimationController,
|
mKeyguardUnlockAnimationController,
|
||||||
mStatusBarKeyguardViewManager);
|
mStatusBarKeyguardViewManager,
|
||||||
|
mPrimaryBouncerToGoneTransitionViewModel,
|
||||||
|
mKeyguardTransitionInteractor,
|
||||||
|
mSysuiStatusBarStateController,
|
||||||
|
mMainDispatcher);
|
||||||
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
|
mScrimController.setScrimVisibleListener(visible -> mScrimVisibility = visible);
|
||||||
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
|
mScrimController.attachViews(mScrimBehind, mNotificationsScrim, mScrimInFront);
|
||||||
mScrimController.setAnimatorListener(mAnimatorListener);
|
mScrimController.setAnimatorListener(mAnimatorListener);
|
||||||
@@ -1629,6 +1657,28 @@ public class ScrimControllerTest extends SysuiTestCase {
|
|||||||
assertScrimAlpha(mScrimBehind, 0);
|
assertScrimAlpha(mScrimBehind, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void ignoreTransitionRequestWhileKeyguardTransitionRunning() {
|
||||||
|
mScrimController.transitionTo(ScrimState.UNLOCKED);
|
||||||
|
mScrimController.mPrimaryBouncerToGoneTransition.accept(
|
||||||
|
new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
|
||||||
|
TransitionState.RUNNING, "ScrimControllerTest"));
|
||||||
|
|
||||||
|
// This request should not happen
|
||||||
|
mScrimController.transitionTo(ScrimState.BOUNCER);
|
||||||
|
assertThat(mScrimController.getState()).isEqualTo(ScrimState.UNLOCKED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void primaryBouncerToGoneOnFinishCallsKeyguardFadedAway() {
|
||||||
|
when(mKeyguardStateController.isKeyguardFadingAway()).thenReturn(true);
|
||||||
|
mScrimController.mPrimaryBouncerToGoneTransition.accept(
|
||||||
|
new TransitionStep(KeyguardState.PRIMARY_BOUNCER, KeyguardState.GONE, 0f,
|
||||||
|
TransitionState.FINISHED, "ScrimControllerTest"));
|
||||||
|
|
||||||
|
verify(mStatusBarKeyguardViewManager).onKeyguardFadedAway();
|
||||||
|
}
|
||||||
|
|
||||||
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
|
private void assertAlphaAfterExpansion(ScrimView scrim, float expectedAlpha, float expansion) {
|
||||||
mScrimController.setRawPanelExpansionFraction(expansion);
|
mScrimController.setRawPanelExpansionFraction(expansion);
|
||||||
finishAnimationsImmediately();
|
finishAnimationsImmediately();
|
||||||
|
|||||||
@@ -47,6 +47,9 @@ class FakeKeyguardRepository : KeyguardRepository {
|
|||||||
private val _isKeyguardShowing = MutableStateFlow(false)
|
private val _isKeyguardShowing = MutableStateFlow(false)
|
||||||
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
|
override val isKeyguardShowing: Flow<Boolean> = _isKeyguardShowing
|
||||||
|
|
||||||
|
private val _isKeyguardUnlocked = MutableStateFlow(false)
|
||||||
|
override val isKeyguardUnlocked: Flow<Boolean> = _isKeyguardUnlocked
|
||||||
|
|
||||||
private val _isKeyguardOccluded = MutableStateFlow(false)
|
private val _isKeyguardOccluded = MutableStateFlow(false)
|
||||||
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
|
override val isKeyguardOccluded: Flow<Boolean> = _isKeyguardOccluded
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ class FakeKeyguardTransitionRepository : KeyguardTransitionRepository {
|
|||||||
_transitions.emit(step)
|
_transitions.emit(step)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun startTransition(info: TransitionInfo): UUID? {
|
override fun startTransition(info: TransitionInfo, resetIfCanceled: Boolean): UUID? {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user