Merge changes I0808f8b8,I03c9f251,I6509e037,I0e3adb67 into tm-qpr-dev
* changes: Dreaming transitions - Enable teamfood Transitions - Update for canceled state Transitions - Handle cancel of bouncer swipe Transitions: Gone->Dreaming
This commit is contained in:
committed by
Android (Google) Code Review
commit
0e0d95d6da
@@ -1292,6 +1292,9 @@
|
|||||||
<!-- LOCKSCREEN -> DREAMING transition: Amount to shift lockscreen content on entering -->
|
<!-- LOCKSCREEN -> DREAMING transition: Amount to shift lockscreen content on entering -->
|
||||||
<dimen name="lockscreen_to_dreaming_transition_lockscreen_translation_y">-40dp</dimen>
|
<dimen name="lockscreen_to_dreaming_transition_lockscreen_translation_y">-40dp</dimen>
|
||||||
|
|
||||||
|
<!-- GONE -> DREAMING transition: Amount to shift lockscreen content on entering -->
|
||||||
|
<dimen name="gone_to_dreaming_transition_lockscreen_translation_y">-40dp</dimen>
|
||||||
|
|
||||||
<!-- LOCKSCREEN -> OCCLUDED transition: Amount to shift lockscreen content on entering -->
|
<!-- LOCKSCREEN -> OCCLUDED transition: Amount to shift lockscreen content on entering -->
|
||||||
<dimen name="lockscreen_to_occluded_transition_lockscreen_translation_y">-40dp</dimen>
|
<dimen name="lockscreen_to_occluded_transition_lockscreen_translation_y">-40dp</dimen>
|
||||||
|
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ object Flags {
|
|||||||
/** A different path for unocclusion transitions back to keyguard */
|
/** A different path for unocclusion transitions back to keyguard */
|
||||||
// TODO(b/262859270): Tracking Bug
|
// TODO(b/262859270): Tracking Bug
|
||||||
@JvmField
|
@JvmField
|
||||||
val UNOCCLUSION_TRANSITION = unreleasedFlag(223, "unocclusion_transition", teamfood = false)
|
val UNOCCLUSION_TRANSITION = unreleasedFlag(223, "unocclusion_transition", teamfood = true)
|
||||||
|
|
||||||
// flag for controlling auto pin confirmation and material u shapes in bouncer
|
// flag for controlling auto pin confirmation and material u shapes in bouncer
|
||||||
@JvmField
|
@JvmField
|
||||||
|
|||||||
@@ -209,7 +209,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state == TransitionState.FINISHED) {
|
if (state == TransitionState.FINISHED || state == TransitionState.CANCELED) {
|
||||||
updateTransitionId = null
|
updateTransitionId = null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ 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.KeyguardTransitionRepository
|
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
|
||||||
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.Companion.isWakeAndUnlock
|
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
|
||||||
import com.android.systemui.keyguard.shared.model.DozeStateModel
|
import com.android.systemui.keyguard.shared.model.DozeStateModel
|
||||||
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
|
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
|
||||||
import com.android.systemui.keyguard.shared.model.KeyguardState
|
import com.android.systemui.keyguard.shared.model.KeyguardState
|
||||||
@@ -56,7 +56,7 @@ constructor(
|
|||||||
scope.launch {
|
scope.launch {
|
||||||
// Using isDreamingWithOverlay provides an optimized path to LOCKSCREEN state, which
|
// Using isDreamingWithOverlay provides an optimized path to LOCKSCREEN state, which
|
||||||
// otherwise would have gone through OCCLUDED first
|
// otherwise would have gone through OCCLUDED first
|
||||||
keyguardInteractor.isDreamingWithOverlay
|
keyguardInteractor.isAbleToDream
|
||||||
.sample(
|
.sample(
|
||||||
combine(
|
combine(
|
||||||
keyguardInteractor.dozeTransitionModel,
|
keyguardInteractor.dozeTransitionModel,
|
||||||
@@ -65,8 +65,7 @@ constructor(
|
|||||||
),
|
),
|
||||||
::toTriple
|
::toTriple
|
||||||
)
|
)
|
||||||
.collect { triple ->
|
.collect { (isDreaming, dozeTransitionModel, lastStartedTransition) ->
|
||||||
val (isDreaming, dozeTransitionModel, lastStartedTransition) = triple
|
|
||||||
if (
|
if (
|
||||||
!isDreaming &&
|
!isDreaming &&
|
||||||
isDozeOff(dozeTransitionModel.to) &&
|
isDozeOff(dozeTransitionModel.to) &&
|
||||||
@@ -96,8 +95,7 @@ constructor(
|
|||||||
),
|
),
|
||||||
::toTriple
|
::toTriple
|
||||||
)
|
)
|
||||||
.collect { triple ->
|
.collect { (isDreaming, isOccluded, lastStartedTransition) ->
|
||||||
val (isDreaming, isOccluded, lastStartedTransition) = triple
|
|
||||||
if (
|
if (
|
||||||
isOccluded &&
|
isOccluded &&
|
||||||
!isDreaming &&
|
!isDreaming &&
|
||||||
@@ -123,24 +121,18 @@ constructor(
|
|||||||
|
|
||||||
private fun listenForDreamingToGone() {
|
private fun listenForDreamingToGone() {
|
||||||
scope.launch {
|
scope.launch {
|
||||||
keyguardInteractor.biometricUnlockState
|
keyguardInteractor.biometricUnlockState.collect { biometricUnlockState ->
|
||||||
.sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
|
if (biometricUnlockState == BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM) {
|
||||||
.collect { pair ->
|
keyguardTransitionRepository.startTransition(
|
||||||
val (biometricUnlockState, keyguardState) = pair
|
TransitionInfo(
|
||||||
if (
|
name,
|
||||||
keyguardState == KeyguardState.DREAMING &&
|
KeyguardState.DREAMING,
|
||||||
isWakeAndUnlock(biometricUnlockState)
|
KeyguardState.GONE,
|
||||||
) {
|
getAnimator(),
|
||||||
keyguardTransitionRepository.startTransition(
|
|
||||||
TransitionInfo(
|
|
||||||
name,
|
|
||||||
KeyguardState.DREAMING,
|
|
||||||
KeyguardState.GONE,
|
|
||||||
getAnimator(),
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,8 +143,7 @@ constructor(
|
|||||||
keyguardTransitionInteractor.finishedKeyguardState,
|
keyguardTransitionInteractor.finishedKeyguardState,
|
||||||
::Pair
|
::Pair
|
||||||
)
|
)
|
||||||
.collect { pair ->
|
.collect { (dozeTransitionModel, keyguardState) ->
|
||||||
val (dozeTransitionModel, keyguardState) = pair
|
|
||||||
if (
|
if (
|
||||||
dozeTransitionModel.to == DozeStateModel.DOZE &&
|
dozeTransitionModel.to == DozeStateModel.DOZE &&
|
||||||
keyguardState == KeyguardState.DREAMING
|
keyguardState == KeyguardState.DREAMING
|
||||||
|
|||||||
@@ -48,8 +48,6 @@ constructor(
|
|||||||
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
private val keyguardTransitionRepository: KeyguardTransitionRepository,
|
||||||
) : TransitionInteractor(FromLockscreenTransitionInteractor::class.simpleName!!) {
|
) : TransitionInteractor(FromLockscreenTransitionInteractor::class.simpleName!!) {
|
||||||
|
|
||||||
private var transitionId: UUID? = null
|
|
||||||
|
|
||||||
override fun start() {
|
override fun start() {
|
||||||
listenForLockscreenToGone()
|
listenForLockscreenToGone()
|
||||||
listenForLockscreenToOccluded()
|
listenForLockscreenToOccluded()
|
||||||
@@ -104,6 +102,7 @@ constructor(
|
|||||||
|
|
||||||
/* Starts transitions when manually dragging up the bouncer from the lockscreen. */
|
/* Starts transitions when manually dragging up the bouncer from the lockscreen. */
|
||||||
private fun listenForLockscreenToBouncerDragging() {
|
private fun listenForLockscreenToBouncerDragging() {
|
||||||
|
var transitionId: UUID? = null
|
||||||
scope.launch {
|
scope.launch {
|
||||||
shadeRepository.shadeModel
|
shadeRepository.shadeModel
|
||||||
.sample(
|
.sample(
|
||||||
@@ -114,25 +113,43 @@ constructor(
|
|||||||
),
|
),
|
||||||
::toTriple
|
::toTriple
|
||||||
)
|
)
|
||||||
.collect { triple ->
|
.collect { (shadeModel, keyguardState, statusBarState) ->
|
||||||
val (shadeModel, keyguardState, statusBarState) = triple
|
|
||||||
|
|
||||||
val id = transitionId
|
val id = transitionId
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
// 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
|
// `updateTransition` will control it until FINISHED or CANCELED
|
||||||
keyguardTransitionRepository.updateTransition(
|
var nextState =
|
||||||
id,
|
if (shadeModel.expansionAmount == 0f) {
|
||||||
1f - shadeModel.expansionAmount,
|
|
||||||
if (
|
|
||||||
shadeModel.expansionAmount == 0f || shadeModel.expansionAmount == 1f
|
|
||||||
) {
|
|
||||||
transitionId = null
|
|
||||||
TransitionState.FINISHED
|
TransitionState.FINISHED
|
||||||
|
} else if (shadeModel.expansionAmount == 1f) {
|
||||||
|
TransitionState.CANCELED
|
||||||
} else {
|
} else {
|
||||||
TransitionState.RUNNING
|
TransitionState.RUNNING
|
||||||
}
|
}
|
||||||
|
keyguardTransitionRepository.updateTransition(
|
||||||
|
id,
|
||||||
|
1f - shadeModel.expansionAmount,
|
||||||
|
nextState,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (
|
||||||
|
nextState == TransitionState.CANCELED ||
|
||||||
|
nextState == TransitionState.FINISHED
|
||||||
|
) {
|
||||||
|
transitionId = null
|
||||||
|
}
|
||||||
|
|
||||||
|
// If canceled, just put the state back
|
||||||
|
if (nextState == TransitionState.CANCELED) {
|
||||||
|
keyguardTransitionRepository.startTransition(
|
||||||
|
TransitionInfo(
|
||||||
|
ownerName = name,
|
||||||
|
from = KeyguardState.BOUNCER,
|
||||||
|
to = KeyguardState.LOCKSCREEN,
|
||||||
|
animator = getAnimator(0.milliseconds)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
} 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
|
||||||
|
|||||||
@@ -32,12 +32,15 @@ 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.statusbar.CommandQueue
|
import com.android.systemui.statusbar.CommandQueue
|
||||||
import com.android.systemui.statusbar.CommandQueue.Callbacks
|
import com.android.systemui.statusbar.CommandQueue.Callbacks
|
||||||
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.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.combine
|
||||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.flatMapLatest
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
import kotlinx.coroutines.flow.merge
|
import kotlinx.coroutines.flow.merge
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -89,15 +92,23 @@ constructor(
|
|||||||
/**
|
/**
|
||||||
* 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.
|
||||||
|
*
|
||||||
|
* Allow a brief moment to prevent rapidly oscillating between true/false signals.
|
||||||
*/
|
*/
|
||||||
val isAbleToDream: Flow<Boolean> =
|
val isAbleToDream: Flow<Boolean> =
|
||||||
merge(isDreaming, isDreamingWithOverlay)
|
merge(isDreaming, isDreamingWithOverlay)
|
||||||
.sample(
|
.combine(
|
||||||
dozeTransitionModel,
|
dozeTransitionModel,
|
||||||
{ isDreaming, dozeTransitionModel ->
|
{ isDreaming, dozeTransitionModel ->
|
||||||
isDreaming && isDozeOff(dozeTransitionModel.to)
|
isDreaming && isDozeOff(dozeTransitionModel.to)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
.flatMapLatest { isAbleToDream ->
|
||||||
|
flow {
|
||||||
|
delay(50)
|
||||||
|
emit(isAbleToDream)
|
||||||
|
}
|
||||||
|
}
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
|
|
||||||
/** Whether the keyguard is showing or not. */
|
/** Whether the keyguard is showing or not. */
|
||||||
|
|||||||
@@ -22,13 +22,17 @@ import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepositor
|
|||||||
import com.android.systemui.keyguard.shared.model.AnimationParams
|
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||||
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.BOUNCER
|
||||||
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
|
import com.android.systemui.keyguard.shared.model.KeyguardState.DREAMING
|
||||||
|
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.KeyguardState.OCCLUDED
|
import com.android.systemui.keyguard.shared.model.KeyguardState.OCCLUDED
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
import com.android.systemui.keyguard.shared.model.TransitionState
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
|
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionStep
|
import com.android.systemui.keyguard.shared.model.TransitionStep
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
import kotlin.math.max
|
||||||
|
import kotlin.math.min
|
||||||
import kotlin.time.Duration
|
import kotlin.time.Duration
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
import kotlinx.coroutines.flow.filter
|
import kotlinx.coroutines.flow.filter
|
||||||
@@ -53,9 +57,16 @@ constructor(
|
|||||||
val dreamingToLockscreenTransition: Flow<TransitionStep> =
|
val dreamingToLockscreenTransition: Flow<TransitionStep> =
|
||||||
repository.transition(DREAMING, LOCKSCREEN)
|
repository.transition(DREAMING, LOCKSCREEN)
|
||||||
|
|
||||||
|
/** GONE->DREAMING transition information. */
|
||||||
|
val goneToDreamingTransition: Flow<TransitionStep> = repository.transition(GONE, DREAMING)
|
||||||
|
|
||||||
/** LOCKSCREEN->AOD transition information. */
|
/** LOCKSCREEN->AOD transition information. */
|
||||||
val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
|
val lockscreenToAodTransition: Flow<TransitionStep> = repository.transition(LOCKSCREEN, AOD)
|
||||||
|
|
||||||
|
/** LOCKSCREEN->BOUNCER transition information. */
|
||||||
|
val lockscreenToBouncerTransition: Flow<TransitionStep> =
|
||||||
|
repository.transition(LOCKSCREEN, BOUNCER)
|
||||||
|
|
||||||
/** LOCKSCREEN->DREAMING transition information. */
|
/** LOCKSCREEN->DREAMING transition information. */
|
||||||
val lockscreenToDreamingTransition: Flow<TransitionStep> =
|
val lockscreenToDreamingTransition: Flow<TransitionStep> =
|
||||||
repository.transition(LOCKSCREEN, DREAMING)
|
repository.transition(LOCKSCREEN, DREAMING)
|
||||||
@@ -106,13 +117,23 @@ constructor(
|
|||||||
): Flow<Float> {
|
): Flow<Float> {
|
||||||
val start = (params.startTime / totalDuration).toFloat()
|
val start = (params.startTime / totalDuration).toFloat()
|
||||||
val chunks = (totalDuration / params.duration).toFloat()
|
val chunks = (totalDuration / params.duration).toFloat()
|
||||||
|
var isRunning = false
|
||||||
return flow
|
return flow
|
||||||
// When starting, emit a value of 0f to give animations a chance to set initial state
|
|
||||||
.map { step ->
|
.map { step ->
|
||||||
|
val value = (step.value - start) * chunks
|
||||||
if (step.transitionState == STARTED) {
|
if (step.transitionState == STARTED) {
|
||||||
0f
|
// When starting, make sure to always emit. If a transition is started from the
|
||||||
|
// middle, it is possible this animation is being skipped but we need to inform
|
||||||
|
// the ViewModels of the last update
|
||||||
|
isRunning = true
|
||||||
|
max(0f, min(1f, value))
|
||||||
|
} else if (isRunning && value >= 1f) {
|
||||||
|
// Always send a final value of 1. Because of rounding, [value] may never be
|
||||||
|
// exactly 1.
|
||||||
|
isRunning = false
|
||||||
|
1f
|
||||||
} else {
|
} else {
|
||||||
(step.value - start) * chunks
|
value
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.filter { value -> value >= 0f && value <= 1f }
|
.filter { value -> value >= 0f && value <= 1f }
|
||||||
|
|||||||
@@ -22,10 +22,14 @@ import com.android.systemui.dagger.SysUISingleton
|
|||||||
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
|
import com.android.systemui.keyguard.domain.interactor.FromDreamingTransitionInteractor.Companion.TO_LOCKSCREEN_DURATION
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
import com.android.systemui.keyguard.shared.model.AnimationParams
|
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
import kotlinx.coroutines.flow.map
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.merge
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
|
* Breaks down DREAMING->LOCKSCREEN transition into discrete steps for corresponding views to
|
||||||
@@ -49,9 +53,15 @@ constructor(
|
|||||||
|
|
||||||
/** Lockscreen views y-translation */
|
/** Lockscreen views y-translation */
|
||||||
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
|
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
|
||||||
return flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
|
return merge(
|
||||||
-translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx)
|
flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
|
||||||
}
|
-translatePx + (EMPHASIZED_DECELERATE.getInterpolation(value) * translatePx)
|
||||||
|
},
|
||||||
|
// On end, reset the translation to 0
|
||||||
|
interactor.dreamingToLockscreenTransition
|
||||||
|
.filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
|
||||||
|
.map { 0f }
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Lockscreen views alpha */
|
/** Lockscreen views alpha */
|
||||||
|
|||||||
@@ -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.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
|
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
|
||||||
|
import javax.inject.Inject
|
||||||
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.filter
|
||||||
|
import kotlinx.coroutines.flow.map
|
||||||
|
import kotlinx.coroutines.flow.merge
|
||||||
|
|
||||||
|
/** Breaks down GONE->DREAMING transition into discrete steps for corresponding views to consume. */
|
||||||
|
@SysUISingleton
|
||||||
|
class GoneToDreamingTransitionViewModel
|
||||||
|
@Inject
|
||||||
|
constructor(
|
||||||
|
private val interactor: KeyguardTransitionInteractor,
|
||||||
|
) {
|
||||||
|
|
||||||
|
/** Lockscreen views y-translation */
|
||||||
|
fun lockscreenTranslationY(translatePx: Int): Flow<Float> {
|
||||||
|
return merge(
|
||||||
|
flowForAnimation(LOCKSCREEN_TRANSLATION_Y).map { value ->
|
||||||
|
(EMPHASIZED_ACCELERATE.getInterpolation(value) * translatePx)
|
||||||
|
},
|
||||||
|
// On end, reset the translation to 0
|
||||||
|
interactor.goneToDreamingTransition
|
||||||
|
.filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
|
||||||
|
.map { 0f }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lockscreen views alpha */
|
||||||
|
val lockscreenAlpha: Flow<Float> = flowForAnimation(LOCKSCREEN_ALPHA).map { 1f - it }
|
||||||
|
|
||||||
|
private fun flowForAnimation(params: AnimationParams): Flow<Float> {
|
||||||
|
return interactor.transitionStepAnimation(
|
||||||
|
interactor.goneToDreamingTransition,
|
||||||
|
params,
|
||||||
|
totalDuration = TO_DREAMING_DURATION
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
val LOCKSCREEN_TRANSLATION_Y = AnimationParams(duration = 500.milliseconds)
|
||||||
|
val LOCKSCREEN_ALPHA = AnimationParams(duration = 250.milliseconds)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -21,7 +21,8 @@ import com.android.systemui.dagger.SysUISingleton
|
|||||||
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_DURATION
|
import com.android.systemui.keyguard.domain.interactor.FromLockscreenTransitionInteractor.Companion.TO_DREAMING_DURATION
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
import com.android.systemui.keyguard.shared.model.AnimationParams
|
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||||
import com.android.systemui.keyguard.shared.model.TransitionState
|
import com.android.systemui.keyguard.shared.model.TransitionState.CANCELED
|
||||||
|
import com.android.systemui.keyguard.shared.model.TransitionState.FINISHED
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
import kotlin.time.Duration.Companion.milliseconds
|
import kotlin.time.Duration.Companion.milliseconds
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
@@ -48,7 +49,7 @@ constructor(
|
|||||||
},
|
},
|
||||||
// On end, reset the translation to 0
|
// On end, reset the translation to 0
|
||||||
interactor.lockscreenToDreamingTransition
|
interactor.lockscreenToDreamingTransition
|
||||||
.filter { step -> step.transitionState == TransitionState.FINISHED }
|
.filter { it.transitionState == FINISHED || it.transitionState == CANCELED }
|
||||||
.map { 0f }
|
.map { 0f }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -144,6 +144,7 @@ import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInterac
|
|||||||
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;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
|
||||||
@@ -692,6 +693,7 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
|
private DreamingToLockscreenTransitionViewModel mDreamingToLockscreenTransitionViewModel;
|
||||||
private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
|
private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
|
||||||
private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
|
private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
|
||||||
|
private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
|
||||||
private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
|
private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
|
||||||
|
|
||||||
private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
||||||
@@ -700,6 +702,7 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
private int mDreamingToLockscreenTransitionTranslationY;
|
private int mDreamingToLockscreenTransitionTranslationY;
|
||||||
private int mOccludedToLockscreenTransitionTranslationY;
|
private int mOccludedToLockscreenTransitionTranslationY;
|
||||||
private int mLockscreenToDreamingTransitionTranslationY;
|
private int mLockscreenToDreamingTransitionTranslationY;
|
||||||
|
private int mGoneToDreamingTransitionTranslationY;
|
||||||
private int mLockscreenToOccludedTransitionTranslationY;
|
private int mLockscreenToOccludedTransitionTranslationY;
|
||||||
private boolean mUnocclusionTransitionFlagEnabled = false;
|
private boolean mUnocclusionTransitionFlagEnabled = false;
|
||||||
|
|
||||||
@@ -735,6 +738,12 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
step.getTransitionState() == TransitionState.RUNNING;
|
step.getTransitionState() == TransitionState.RUNNING;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final Consumer<TransitionStep> mGoneToDreamingTransition =
|
||||||
|
(TransitionStep step) -> {
|
||||||
|
mIsOcclusionTransitionRunning =
|
||||||
|
step.getTransitionState() == TransitionState.RUNNING;
|
||||||
|
};
|
||||||
|
|
||||||
private final Consumer<TransitionStep> mLockscreenToOccludedTransition =
|
private final Consumer<TransitionStep> mLockscreenToOccludedTransition =
|
||||||
(TransitionStep step) -> {
|
(TransitionStep step) -> {
|
||||||
mIsOcclusionTransitionRunning =
|
mIsOcclusionTransitionRunning =
|
||||||
@@ -813,6 +822,7 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
DreamingToLockscreenTransitionViewModel dreamingToLockscreenTransitionViewModel,
|
DreamingToLockscreenTransitionViewModel dreamingToLockscreenTransitionViewModel,
|
||||||
OccludedToLockscreenTransitionViewModel occludedToLockscreenTransitionViewModel,
|
OccludedToLockscreenTransitionViewModel occludedToLockscreenTransitionViewModel,
|
||||||
LockscreenToDreamingTransitionViewModel lockscreenToDreamingTransitionViewModel,
|
LockscreenToDreamingTransitionViewModel lockscreenToDreamingTransitionViewModel,
|
||||||
|
GoneToDreamingTransitionViewModel goneToDreamingTransitionViewModel,
|
||||||
LockscreenToOccludedTransitionViewModel lockscreenToOccludedTransitionViewModel,
|
LockscreenToOccludedTransitionViewModel lockscreenToOccludedTransitionViewModel,
|
||||||
@Main CoroutineDispatcher mainDispatcher,
|
@Main CoroutineDispatcher mainDispatcher,
|
||||||
KeyguardTransitionInteractor keyguardTransitionInteractor,
|
KeyguardTransitionInteractor keyguardTransitionInteractor,
|
||||||
@@ -834,6 +844,7 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
|
mDreamingToLockscreenTransitionViewModel = dreamingToLockscreenTransitionViewModel;
|
||||||
mOccludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel;
|
mOccludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel;
|
||||||
mLockscreenToDreamingTransitionViewModel = lockscreenToDreamingTransitionViewModel;
|
mLockscreenToDreamingTransitionViewModel = lockscreenToDreamingTransitionViewModel;
|
||||||
|
mGoneToDreamingTransitionViewModel = goneToDreamingTransitionViewModel;
|
||||||
mLockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel;
|
mLockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel;
|
||||||
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
|
mKeyguardTransitionInteractor = keyguardTransitionInteractor;
|
||||||
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
mView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
|
||||||
@@ -1172,6 +1183,17 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
setTransitionY(mNotificationStackScrollLayoutController),
|
setTransitionY(mNotificationStackScrollLayoutController),
|
||||||
mMainDispatcher);
|
mMainDispatcher);
|
||||||
|
|
||||||
|
// Gone->Dreaming
|
||||||
|
collectFlow(mView, mKeyguardTransitionInteractor.getGoneToDreamingTransition(),
|
||||||
|
mGoneToDreamingTransition, mMainDispatcher);
|
||||||
|
collectFlow(mView, mGoneToDreamingTransitionViewModel.getLockscreenAlpha(),
|
||||||
|
setTransitionAlpha(mNotificationStackScrollLayoutController),
|
||||||
|
mMainDispatcher);
|
||||||
|
collectFlow(mView, mGoneToDreamingTransitionViewModel.lockscreenTranslationY(
|
||||||
|
mGoneToDreamingTransitionTranslationY),
|
||||||
|
setTransitionY(mNotificationStackScrollLayoutController),
|
||||||
|
mMainDispatcher);
|
||||||
|
|
||||||
// Lockscreen->Occluded
|
// Lockscreen->Occluded
|
||||||
collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
|
collectFlow(mView, mKeyguardTransitionInteractor.getLockscreenToOccludedTransition(),
|
||||||
mLockscreenToOccludedTransition, mMainDispatcher);
|
mLockscreenToOccludedTransition, mMainDispatcher);
|
||||||
@@ -1223,6 +1245,8 @@ public final class NotificationPanelViewController implements Dumpable {
|
|||||||
R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y);
|
R.dimen.occluded_to_lockscreen_transition_lockscreen_translation_y);
|
||||||
mLockscreenToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
|
mLockscreenToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
|
||||||
R.dimen.lockscreen_to_dreaming_transition_lockscreen_translation_y);
|
R.dimen.lockscreen_to_dreaming_transition_lockscreen_translation_y);
|
||||||
|
mGoneToDreamingTransitionTranslationY = mResources.getDimensionPixelSize(
|
||||||
|
R.dimen.gone_to_dreaming_transition_lockscreen_translation_y);
|
||||||
mLockscreenToOccludedTransitionTranslationY = mResources.getDimensionPixelSize(
|
mLockscreenToOccludedTransitionTranslationY = mResources.getDimensionPixelSize(
|
||||||
R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y);
|
R.dimen.lockscreen_to_occluded_transition_lockscreen_translation_y);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -168,6 +168,25 @@ class KeyguardTransitionRepositoryTest : SysuiTestCase() {
|
|||||||
assertThat(wtfHandler.failed).isTrue()
|
assertThat(wtfHandler.failed).isTrue()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `Attempt to manually update transition after CANCELED state throws exception`() {
|
||||||
|
val uuid =
|
||||||
|
underTest.startTransition(
|
||||||
|
TransitionInfo(
|
||||||
|
ownerName = OWNER_NAME,
|
||||||
|
from = AOD,
|
||||||
|
to = LOCKSCREEN,
|
||||||
|
animator = null,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
checkNotNull(uuid).let {
|
||||||
|
underTest.updateTransition(it, 0.2f, TransitionState.CANCELED)
|
||||||
|
underTest.updateTransition(it, 0.5f, TransitionState.RUNNING)
|
||||||
|
}
|
||||||
|
assertThat(wtfHandler.failed).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
private fun listWithStep(
|
private fun listWithStep(
|
||||||
step: BigDecimal,
|
step: BigDecimal,
|
||||||
start: BigDecimal = BigDecimal.ZERO,
|
start: BigDecimal = BigDecimal.ZERO,
|
||||||
|
|||||||
@@ -38,6 +38,7 @@ 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
|
||||||
import kotlinx.coroutines.test.TestScope
|
import kotlinx.coroutines.test.TestScope
|
||||||
|
import kotlinx.coroutines.test.advanceUntilIdle
|
||||||
import kotlinx.coroutines.test.runCurrent
|
import kotlinx.coroutines.test.runCurrent
|
||||||
import kotlinx.coroutines.test.runTest
|
import kotlinx.coroutines.test.runTest
|
||||||
import org.junit.Before
|
import org.junit.Before
|
||||||
@@ -177,7 +178,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
keyguardRepository.setDreamingWithOverlay(false)
|
keyguardRepository.setDreamingWithOverlay(false)
|
||||||
// AND occluded has stopped
|
// AND occluded has stopped
|
||||||
keyguardRepository.setKeyguardOccluded(false)
|
keyguardRepository.setKeyguardOccluded(false)
|
||||||
runCurrent()
|
advanceUntilIdle()
|
||||||
|
|
||||||
val info =
|
val info =
|
||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
@@ -506,7 +507,7 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
withArgCaptor<TransitionInfo> {
|
withArgCaptor<TransitionInfo> {
|
||||||
verify(mockTransitionRepository).startTransition(capture())
|
verify(mockTransitionRepository).startTransition(capture())
|
||||||
}
|
}
|
||||||
// THEN a transition to DOZING should occur
|
// THEN a transition to AOD should occur
|
||||||
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
||||||
assertThat(info.from).isEqualTo(KeyguardState.GONE)
|
assertThat(info.from).isEqualTo(KeyguardState.GONE)
|
||||||
assertThat(info.to).isEqualTo(KeyguardState.AOD)
|
assertThat(info.to).isEqualTo(KeyguardState.AOD)
|
||||||
@@ -515,6 +516,49 @@ class KeyguardTransitionScenariosTest : SysuiTestCase() {
|
|||||||
coroutineContext.cancelChildren()
|
coroutineContext.cancelChildren()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun `GONE to DREAMING`() =
|
||||||
|
testScope.runTest {
|
||||||
|
// GIVEN a device that is not dreaming or dozing
|
||||||
|
keyguardRepository.setDreamingWithOverlay(false)
|
||||||
|
keyguardRepository.setDozeTransitionModel(
|
||||||
|
DozeTransitionModel(from = DozeStateModel.DOZE, to = DozeStateModel.FINISH)
|
||||||
|
)
|
||||||
|
runCurrent()
|
||||||
|
|
||||||
|
// GIVEN a prior transition has run to GONE
|
||||||
|
runner.startTransition(
|
||||||
|
testScope,
|
||||||
|
TransitionInfo(
|
||||||
|
ownerName = "",
|
||||||
|
from = KeyguardState.LOCKSCREEN,
|
||||||
|
to = KeyguardState.GONE,
|
||||||
|
animator =
|
||||||
|
ValueAnimator().apply {
|
||||||
|
duration = 10
|
||||||
|
interpolator = Interpolators.LINEAR
|
||||||
|
},
|
||||||
|
)
|
||||||
|
)
|
||||||
|
reset(mockTransitionRepository)
|
||||||
|
|
||||||
|
// WHEN the device begins to dream
|
||||||
|
keyguardRepository.setDreamingWithOverlay(true)
|
||||||
|
advanceUntilIdle()
|
||||||
|
|
||||||
|
val info =
|
||||||
|
withArgCaptor<TransitionInfo> {
|
||||||
|
verify(mockTransitionRepository).startTransition(capture())
|
||||||
|
}
|
||||||
|
// THEN a transition to DREAMING should occur
|
||||||
|
assertThat(info.ownerName).isEqualTo("FromGoneTransitionInteractor")
|
||||||
|
assertThat(info.from).isEqualTo(KeyguardState.GONE)
|
||||||
|
assertThat(info.to).isEqualTo(KeyguardState.DREAMING)
|
||||||
|
assertThat(info.animator).isNotNull()
|
||||||
|
|
||||||
|
coroutineContext.cancelChildren()
|
||||||
|
}
|
||||||
|
|
||||||
private fun startingToWake() =
|
private fun startingToWake() =
|
||||||
WakefulnessModel(
|
WakefulnessModel(
|
||||||
WakefulnessState.STARTING_TO_WAKE,
|
WakefulnessState.STARTING_TO_WAKE,
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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.filters.SmallTest
|
||||||
|
import com.android.systemui.SysuiTestCase
|
||||||
|
import com.android.systemui.animation.Interpolators.EMPHASIZED_ACCELERATE
|
||||||
|
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.FromGoneTransitionInteractor.Companion.TO_DREAMING_DURATION
|
||||||
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
|
||||||
|
import com.android.systemui.keyguard.shared.model.AnimationParams
|
||||||
|
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.GoneToDreamingTransitionViewModel.Companion.LOCKSCREEN_ALPHA
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel.Companion.LOCKSCREEN_TRANSLATION_Y
|
||||||
|
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.junit.runners.JUnit4
|
||||||
|
|
||||||
|
@SmallTest
|
||||||
|
@RunWith(JUnit4::class)
|
||||||
|
class GoneToDreamingTransitionViewModelTest : SysuiTestCase() {
|
||||||
|
private lateinit var underTest: GoneToDreamingTransitionViewModel
|
||||||
|
private lateinit var repository: FakeKeyguardTransitionRepository
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun setUp() {
|
||||||
|
repository = FakeKeyguardTransitionRepository()
|
||||||
|
val interactor = KeyguardTransitionInteractor(repository)
|
||||||
|
underTest = GoneToDreamingTransitionViewModel(interactor)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun lockscreenFadeOut() =
|
||||||
|
runTest(UnconfinedTestDispatcher()) {
|
||||||
|
val values = mutableListOf<Float>()
|
||||||
|
|
||||||
|
val job = underTest.lockscreenAlpha.onEach { values.add(it) }.launchIn(this)
|
||||||
|
|
||||||
|
// Should start running here...
|
||||||
|
repository.sendTransitionStep(step(0f))
|
||||||
|
repository.sendTransitionStep(step(0.1f))
|
||||||
|
repository.sendTransitionStep(step(0.2f))
|
||||||
|
// ...up to here
|
||||||
|
repository.sendTransitionStep(step(0.3f))
|
||||||
|
repository.sendTransitionStep(step(1f))
|
||||||
|
|
||||||
|
// Only three values should be present, since the dream overlay runs for a small
|
||||||
|
// fraction
|
||||||
|
// of the overall animation time
|
||||||
|
assertThat(values.size).isEqualTo(3)
|
||||||
|
assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
|
||||||
|
assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
|
||||||
|
assertThat(values[2]).isEqualTo(1f - animValue(0.2f, LOCKSCREEN_ALPHA))
|
||||||
|
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun lockscreenTranslationY() =
|
||||||
|
runTest(UnconfinedTestDispatcher()) {
|
||||||
|
val values = mutableListOf<Float>()
|
||||||
|
|
||||||
|
val pixels = 100
|
||||||
|
val job =
|
||||||
|
underTest.lockscreenTranslationY(pixels).onEach { values.add(it) }.launchIn(this)
|
||||||
|
|
||||||
|
// Should start running here...
|
||||||
|
repository.sendTransitionStep(step(0f))
|
||||||
|
repository.sendTransitionStep(step(0.3f))
|
||||||
|
repository.sendTransitionStep(step(0.5f))
|
||||||
|
// ...up to here
|
||||||
|
repository.sendTransitionStep(step(1f))
|
||||||
|
// And a final reset event on CANCEL
|
||||||
|
repository.sendTransitionStep(step(0.8f, TransitionState.CANCELED))
|
||||||
|
|
||||||
|
assertThat(values.size).isEqualTo(4)
|
||||||
|
assertThat(values[0])
|
||||||
|
.isEqualTo(
|
||||||
|
EMPHASIZED_ACCELERATE.getInterpolation(
|
||||||
|
animValue(0f, LOCKSCREEN_TRANSLATION_Y)
|
||||||
|
) * pixels
|
||||||
|
)
|
||||||
|
assertThat(values[1])
|
||||||
|
.isEqualTo(
|
||||||
|
EMPHASIZED_ACCELERATE.getInterpolation(
|
||||||
|
animValue(0.3f, LOCKSCREEN_TRANSLATION_Y)
|
||||||
|
) * pixels
|
||||||
|
)
|
||||||
|
assertThat(values[2])
|
||||||
|
.isEqualTo(
|
||||||
|
EMPHASIZED_ACCELERATE.getInterpolation(
|
||||||
|
animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
|
||||||
|
) * pixels
|
||||||
|
)
|
||||||
|
assertThat(values[3]).isEqualTo(0f)
|
||||||
|
job.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun animValue(stepValue: Float, params: AnimationParams): Float {
|
||||||
|
val totalDuration = TO_DREAMING_DURATION
|
||||||
|
val startValue = (params.startTime / totalDuration).toFloat()
|
||||||
|
|
||||||
|
val multiplier = (totalDuration / params.duration).toFloat()
|
||||||
|
return (stepValue - startValue) * multiplier
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun step(
|
||||||
|
value: Float,
|
||||||
|
state: TransitionState = TransitionState.RUNNING
|
||||||
|
): TransitionStep {
|
||||||
|
return TransitionStep(
|
||||||
|
from = KeyguardState.GONE,
|
||||||
|
to = KeyguardState.DREAMING,
|
||||||
|
value = value,
|
||||||
|
transitionState = state,
|
||||||
|
ownerName = "GoneToDreamingTransitionViewModelTest"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -67,8 +67,7 @@ class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
|
|||||||
repository.sendTransitionStep(step(1f))
|
repository.sendTransitionStep(step(1f))
|
||||||
|
|
||||||
// Only three values should be present, since the dream overlay runs for a small
|
// Only three values should be present, since the dream overlay runs for a small
|
||||||
// fraction
|
// fraction of the overall animation time
|
||||||
// of the overall animation time
|
|
||||||
assertThat(values.size).isEqualTo(3)
|
assertThat(values.size).isEqualTo(3)
|
||||||
assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
|
assertThat(values[0]).isEqualTo(1f - animValue(0f, LOCKSCREEN_ALPHA))
|
||||||
assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
|
assertThat(values[1]).isEqualTo(1f - animValue(0.1f, LOCKSCREEN_ALPHA))
|
||||||
@@ -92,8 +91,10 @@ class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
|
|||||||
repository.sendTransitionStep(step(0.5f))
|
repository.sendTransitionStep(step(0.5f))
|
||||||
// ...up to here
|
// ...up to here
|
||||||
repository.sendTransitionStep(step(1f))
|
repository.sendTransitionStep(step(1f))
|
||||||
|
// And a final reset event on FINISHED
|
||||||
|
repository.sendTransitionStep(step(1f, TransitionState.FINISHED))
|
||||||
|
|
||||||
assertThat(values.size).isEqualTo(3)
|
assertThat(values.size).isEqualTo(4)
|
||||||
assertThat(values[0])
|
assertThat(values[0])
|
||||||
.isEqualTo(
|
.isEqualTo(
|
||||||
EMPHASIZED_ACCELERATE.getInterpolation(
|
EMPHASIZED_ACCELERATE.getInterpolation(
|
||||||
@@ -112,6 +113,8 @@ class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
|
|||||||
animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
|
animValue(0.5f, LOCKSCREEN_TRANSLATION_Y)
|
||||||
) * pixels
|
) * pixels
|
||||||
)
|
)
|
||||||
|
assertThat(values[3]).isEqualTo(0f)
|
||||||
|
|
||||||
job.cancel()
|
job.cancel()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,12 +126,15 @@ class LockscreenToDreamingTransitionViewModelTest : SysuiTestCase() {
|
|||||||
return (stepValue - startValue) * multiplier
|
return (stepValue - startValue) * multiplier
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun step(value: Float): TransitionStep {
|
private fun step(
|
||||||
|
value: Float,
|
||||||
|
state: TransitionState = TransitionState.RUNNING
|
||||||
|
): TransitionStep {
|
||||||
return TransitionStep(
|
return TransitionStep(
|
||||||
from = KeyguardState.LOCKSCREEN,
|
from = KeyguardState.LOCKSCREEN,
|
||||||
to = KeyguardState.DREAMING,
|
to = KeyguardState.DREAMING,
|
||||||
value = value,
|
value = value,
|
||||||
transitionState = TransitionState.RUNNING,
|
transitionState = state,
|
||||||
ownerName = "LockscreenToDreamingTransitionViewModelTest"
|
ownerName = "LockscreenToDreamingTransitionViewModelTest"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ import com.android.systemui.keyguard.domain.interactor.AlternateBouncerInteracto
|
|||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
|
import com.android.systemui.keyguard.domain.interactor.KeyguardBottomAreaInteractor;
|
||||||
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.DreamingToLockscreenTransitionViewModel;
|
||||||
|
import com.android.systemui.keyguard.ui.viewmodel.GoneToDreamingTransitionViewModel;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.KeyguardBottomAreaViewModel;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToDreamingTransitionViewModel;
|
||||||
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
|
import com.android.systemui.keyguard.ui.viewmodel.LockscreenToOccludedTransitionViewModel;
|
||||||
@@ -298,6 +299,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
@Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
|
@Mock private OccludedToLockscreenTransitionViewModel mOccludedToLockscreenTransitionViewModel;
|
||||||
@Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
|
@Mock private LockscreenToDreamingTransitionViewModel mLockscreenToDreamingTransitionViewModel;
|
||||||
@Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
|
@Mock private LockscreenToOccludedTransitionViewModel mLockscreenToOccludedTransitionViewModel;
|
||||||
|
@Mock private GoneToDreamingTransitionViewModel mGoneToDreamingTransitionViewModel;
|
||||||
|
|
||||||
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
@Mock private KeyguardTransitionInteractor mKeyguardTransitionInteractor;
|
||||||
@Mock private CoroutineDispatcher mMainDispatcher;
|
@Mock private CoroutineDispatcher mMainDispatcher;
|
||||||
@@ -522,6 +524,7 @@ public class NotificationPanelViewControllerTest extends SysuiTestCase {
|
|||||||
mDreamingToLockscreenTransitionViewModel,
|
mDreamingToLockscreenTransitionViewModel,
|
||||||
mOccludedToLockscreenTransitionViewModel,
|
mOccludedToLockscreenTransitionViewModel,
|
||||||
mLockscreenToDreamingTransitionViewModel,
|
mLockscreenToDreamingTransitionViewModel,
|
||||||
|
mGoneToDreamingTransitionViewModel,
|
||||||
mLockscreenToOccludedTransitionViewModel,
|
mLockscreenToOccludedTransitionViewModel,
|
||||||
mMainDispatcher,
|
mMainDispatcher,
|
||||||
mKeyguardTransitionInteractor,
|
mKeyguardTransitionInteractor,
|
||||||
|
|||||||
Reference in New Issue
Block a user