Merge "Fade out UDFPS on shadeExpand & dialogProgress" into udc-qpr-dev

This commit is contained in:
Treehugger Robot
2023-07-20 20:02:50 +00:00
committed by Android (Google) Code Review
7 changed files with 454 additions and 60 deletions

View File

@@ -21,10 +21,16 @@ import android.animation.FloatEvaluator
import android.animation.IntEvaluator
import com.android.systemui.common.ui.data.repository.ConfigurationRepository
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.statusbar.phone.hideAffordancesRequest
import javax.inject.Inject
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
/** Encapsulates business logic for transitions between UDFPS states on the keyguard. */
@ExperimentalCoroutinesApi
@@ -35,6 +41,8 @@ constructor(
configRepo: ConfigurationRepository,
burnInInteractor: BurnInInteractor,
keyguardInteractor: KeyguardInteractor,
shadeRepository: ShadeRepository,
dialogManager: SystemUIDialogManager,
) {
private val intEvaluator = IntEvaluator()
private val floatEvaluator = FloatEvaluator()
@@ -56,6 +64,26 @@ constructor(
floatEvaluator.evaluate(dozeAmount, 0, fullyDozingBurnInProgress),
)
}
val dialogHideAffordancesRequest: Flow<Boolean> = dialogManager.hideAffordancesRequest
val qsProgress: Flow<Float> =
shadeRepository.qsExpansion // swipe from top of LS
.map { (it * 2).coerceIn(0f, 1f) }
.onStart { emit(0f) }
val shadeExpansion: Flow<Float> =
combine(
shadeRepository.udfpsTransitionToFullShadeProgress, // swipe from middle of LS
keyguardInteractor.statusBarState, // quick swipe from middle of LS
) { shadeProgress, statusBarState ->
if (statusBarState == StatusBarState.SHADE_LOCKED) {
1f
} else {
shadeProgress
}
}
.onStart { emit(0f) }
}
data class BurnInOffsets(

View File

@@ -21,13 +21,17 @@ import androidx.annotation.ColorInt
import com.android.settingslib.Utils.getColorAttrDefaultColor
import com.android.systemui.R
import com.android.systemui.keyguard.domain.interactor.BurnInOffsets
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import javax.inject.Inject
import kotlin.math.roundToInt
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
@@ -38,6 +42,8 @@ open class UdfpsLockscreenViewModel(
lockscreenColorResId: Int,
alternateBouncerColorResId: Int,
transitionInteractor: KeyguardTransitionInteractor,
udfpsKeyguardInteractor: UdfpsKeyguardInteractor,
keyguardInteractor: KeyguardInteractor,
) {
private val toLockscreen: Flow<TransitionViewModel> =
transitionInteractor.anyStateToLockscreenTransition.map {
@@ -54,46 +60,53 @@ open class UdfpsLockscreenViewModel(
}
private val toAlternateBouncer: Flow<TransitionViewModel> =
transitionInteractor.anyStateToAlternateBouncerTransition.map {
TransitionViewModel(
alpha = 1f,
scale =
if (visibleInKeyguardState(it.from)) {
1f
} else {
it.value
},
color = getColorAttrDefaultColor(context, alternateBouncerColorResId),
)
keyguardInteractor.statusBarState.flatMapLatest { statusBarState ->
transitionInteractor.anyStateToAlternateBouncerTransition.map {
TransitionViewModel(
alpha = 1f,
scale =
if (visibleInKeyguardState(it.from, statusBarState)) {
1f
} else {
it.value
},
color = getColorAttrDefaultColor(context, alternateBouncerColorResId),
)
}
}
private val fadeOut: Flow<TransitionViewModel> =
merge(
transitionInteractor.anyStateToGoneTransition,
transitionInteractor.anyStateToAodTransition,
transitionInteractor.anyStateToOccludedTransition,
transitionInteractor.anyStateToPrimaryBouncerTransition,
transitionInteractor.anyStateToDreamingTransition,
)
.map {
TransitionViewModel(
alpha =
if (visibleInKeyguardState(it.from)) {
1f - it.value
} else {
0f
},
scale = 1f,
color =
if (it.from == KeyguardState.ALTERNATE_BOUNCER) {
getColorAttrDefaultColor(context, alternateBouncerColorResId)
} else {
getColorAttrDefaultColor(context, lockscreenColorResId)
},
keyguardInteractor.statusBarState.flatMapLatest { statusBarState ->
merge(
transitionInteractor.anyStateToGoneTransition,
transitionInteractor.anyStateToAodTransition,
transitionInteractor.anyStateToOccludedTransition,
transitionInteractor.anyStateToPrimaryBouncerTransition,
transitionInteractor.anyStateToDreamingTransition,
)
}
.map {
TransitionViewModel(
alpha =
if (visibleInKeyguardState(it.from, statusBarState)) {
1f - it.value
} else {
0f
},
scale = 1f,
color =
if (it.from == KeyguardState.ALTERNATE_BOUNCER) {
getColorAttrDefaultColor(context, alternateBouncerColorResId)
} else {
getColorAttrDefaultColor(context, lockscreenColorResId)
},
)
}
}
private fun visibleInKeyguardState(state: KeyguardState): Boolean {
private fun visibleInKeyguardState(
state: KeyguardState,
statusBarState: StatusBarState
): Boolean {
return when (state) {
KeyguardState.OFF,
KeyguardState.DOZING,
@@ -102,17 +115,53 @@ open class UdfpsLockscreenViewModel(
KeyguardState.PRIMARY_BOUNCER,
KeyguardState.GONE,
KeyguardState.OCCLUDED -> false
KeyguardState.LOCKSCREEN,
KeyguardState.LOCKSCREEN -> statusBarState == StatusBarState.KEYGUARD
KeyguardState.ALTERNATE_BOUNCER -> true
}
}
val transition: Flow<TransitionViewModel> =
private val keyguardStateTransition =
merge(
toAlternateBouncer,
toLockscreen,
fadeOut,
)
private val dialogHideAffordancesAlphaMultiplier: Flow<Float> =
udfpsKeyguardInteractor.dialogHideAffordancesRequest.map { hideAffordances ->
if (hideAffordances) {
0f
} else {
1f
}
}
private val alphaMultiplier: Flow<Float> =
combine(
transitionInteractor.startedKeyguardState,
dialogHideAffordancesAlphaMultiplier,
udfpsKeyguardInteractor.shadeExpansion,
udfpsKeyguardInteractor.qsProgress,
) { startedKeyguardState, dialogHideAffordancesAlphaMultiplier, shadeExpansion, qsProgress
->
if (startedKeyguardState == KeyguardState.ALTERNATE_BOUNCER) {
1f
} else {
dialogHideAffordancesAlphaMultiplier * (1f - shadeExpansion) * (1f - qsProgress)
}
}
val transition: Flow<TransitionViewModel> =
combine(
alphaMultiplier,
keyguardStateTransition,
) { alphaMultiplier, keyguardStateTransition ->
TransitionViewModel(
alpha = keyguardStateTransition.alpha * alphaMultiplier,
scale = keyguardStateTransition.scale,
color = keyguardStateTransition.color,
)
}
val visible: Flow<Boolean> = transition.map { it.alpha != 0f }
}
@@ -123,12 +172,15 @@ constructor(
val context: Context,
transitionInteractor: KeyguardTransitionInteractor,
interactor: UdfpsKeyguardInteractor,
keyguardInteractor: KeyguardInteractor,
) :
UdfpsLockscreenViewModel(
context,
android.R.attr.textColorPrimary,
com.android.internal.R.attr.materialColorOnPrimaryFixed,
transitionInteractor,
interactor,
keyguardInteractor,
) {
val dozeAmount: Flow<Float> = interactor.dozeAmount
val burnInOffsets: Flow<BurnInOffsets> = interactor.burnInOffsets
@@ -147,12 +199,16 @@ class BackgroundViewModel
constructor(
val context: Context,
transitionInteractor: KeyguardTransitionInteractor,
interactor: UdfpsKeyguardInteractor,
keyguardInteractor: KeyguardInteractor,
) :
UdfpsLockscreenViewModel(
context,
com.android.internal.R.attr.colorSurface,
com.android.internal.R.attr.materialColorPrimaryFixed,
transitionInteractor,
interactor,
keyguardInteractor,
)
data class TransitionViewModel(

View File

@@ -0,0 +1,34 @@
/*
* 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.statusbar.phone
import com.android.systemui.common.coroutine.ChannelExt.trySendWithFailureLogging
import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCallbackFlow
import kotlinx.coroutines.channels.awaitClose
import kotlinx.coroutines.flow.Flow
/** Whether dialogs are requesting for affordances to be hidden or not. */
val SystemUIDialogManager.hideAffordancesRequest: Flow<Boolean>
get() = conflatedCallbackFlow {
val callback =
SystemUIDialogManager.Listener { hideAffordance ->
trySendWithFailureLogging(hideAffordance, "dialogHideAffordancesRequest")
}
registerListener(callback)
trySendWithFailureLogging(shouldHideAffordance(), "dialogHideAffordancesRequestInitial")
awaitClose { unregisterListener(callback) }
}

View File

@@ -33,6 +33,9 @@ import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakeSleepReason
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.keyguard.shared.model.WakefulnessState
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.whenever
import com.android.systemui.util.time.FakeSystemClock
@@ -46,6 +49,7 @@ import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mock
import org.mockito.Mockito.verify
import org.mockito.MockitoAnnotations
@ExperimentalCoroutinesApi
@@ -63,19 +67,21 @@ class UdfpsKeyguardInteractorTest : SysuiTestCase() {
private lateinit var fakeCommandQueue: FakeCommandQueue
private lateinit var featureFlags: FakeFeatureFlags
private lateinit var burnInInteractor: BurnInInteractor
private lateinit var shadeRepository: FakeShadeRepository
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@Mock private lateinit var dialogManager: SystemUIDialogManager
private lateinit var underTest: UdfpsKeyguardInteractor
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testScope = TestScope()
configRepository = FakeConfigurationRepository()
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
shadeRepository = FakeShadeRepository()
fakeCommandQueue = FakeCommandQueue()
featureFlags =
FakeFeatureFlags().apply {
@@ -102,6 +108,8 @@ class UdfpsKeyguardInteractorTest : SysuiTestCase() {
bouncerRepository,
configRepository,
),
shadeRepository,
dialogManager,
)
}
@@ -142,6 +150,61 @@ class UdfpsKeyguardInteractorTest : SysuiTestCase() {
assertThat(burnInOffsets?.burnInXOffset).isEqualTo(burnInXOffset)
}
@Test
fun dialogHideAffordances() =
testScope.runTest {
val dialogHideAffordancesRequest by
collectLastValue(underTest.dialogHideAffordancesRequest)
runCurrent()
val captor = argumentCaptor<SystemUIDialogManager.Listener>()
verify(dialogManager).registerListener(captor.capture())
captor.value.shouldHideAffordances(false)
assertThat(dialogHideAffordancesRequest).isEqualTo(false)
captor.value.shouldHideAffordances(true)
assertThat(dialogHideAffordancesRequest).isEqualTo(true)
captor.value.shouldHideAffordances(false)
assertThat(dialogHideAffordancesRequest).isEqualTo(false)
}
@Test
fun shadeExpansion_updates() =
testScope.runTest {
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
val shadeExpansion by collectLastValue(underTest.shadeExpansion)
assertThat(shadeExpansion).isEqualTo(0f)
shadeRepository.setUdfpsTransitionToFullShadeProgress(.5f)
assertThat(shadeExpansion).isEqualTo(.5f)
shadeRepository.setUdfpsTransitionToFullShadeProgress(.7f)
assertThat(shadeExpansion).isEqualTo(.7f)
shadeRepository.setUdfpsTransitionToFullShadeProgress(.22f)
assertThat(shadeExpansion).isEqualTo(.22f)
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
assertThat(shadeExpansion).isEqualTo(1f)
}
@Test
fun qsProgress_updates() =
testScope.runTest {
val qsProgress by collectLastValue(underTest.qsProgress)
assertThat(qsProgress).isEqualTo(0f)
shadeRepository.setQsExpansion(.22f)
assertThat(qsProgress).isEqualTo(.44f)
shadeRepository.setQsExpansion(.5f)
assertThat(qsProgress).isEqualTo(1f)
shadeRepository.setQsExpansion(.7f)
assertThat(qsProgress).isEqualTo(1f)
}
private fun initializeBurnInOffsets() {
whenever(burnInHelper.burnInProgressOffset()).thenReturn(burnInProgress)
whenever(burnInHelper.burnInOffset(anyInt(), /* xAxis */ eq(true)))

View File

@@ -32,6 +32,8 @@ import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -58,7 +60,9 @@ class UdfpsAodViewModelTest : SysuiTestCase() {
private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var fakeCommandQueue: FakeCommandQueue
private lateinit var featureFlags: FakeFeatureFlags
private lateinit var shadeRepository: FakeShadeRepository
@Mock private lateinit var dialogManager: SystemUIDialogManager
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@Before
@@ -70,6 +74,7 @@ class UdfpsAodViewModelTest : SysuiTestCase() {
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
fakeCommandQueue = FakeCommandQueue()
shadeRepository = FakeShadeRepository()
featureFlags =
FakeFeatureFlags().apply {
set(Flags.REFACTOR_UDFPS_KEYGUARD_VIEWS, true)
@@ -93,6 +98,8 @@ class UdfpsAodViewModelTest : SysuiTestCase() {
bouncerRepository,
configRepository,
),
shadeRepository,
dialogManager,
)
underTest =

View File

@@ -33,6 +33,8 @@ import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -60,8 +62,10 @@ class UdfpsFingerprintViewModelTest : SysuiTestCase() {
private lateinit var fakeCommandQueue: FakeCommandQueue
private lateinit var featureFlags: FakeFeatureFlags
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
private lateinit var shadeRepository: FakeShadeRepository
@Mock private lateinit var burnInHelper: BurnInHelperWrapper
@Mock private lateinit var dialogManager: SystemUIDialogManager
@Before
fun setUp() {
@@ -79,35 +83,39 @@ class UdfpsFingerprintViewModelTest : SysuiTestCase() {
}
bouncerRepository = FakeKeyguardBouncerRepository()
transitionRepository = FakeKeyguardTransitionRepository()
shadeRepository = FakeShadeRepository()
val transitionInteractor =
KeyguardTransitionInteractor(
transitionRepository,
testScope.backgroundScope,
)
val udfpsKeyguardInteractor =
UdfpsKeyguardInteractor(
val keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
fakeCommandQueue,
featureFlags,
bouncerRepository,
configRepository,
BurnInInteractor(
context,
burnInHelper,
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
),
KeyguardInteractor(
keyguardRepository,
fakeCommandQueue,
featureFlags,
bouncerRepository,
configRepository,
),
)
underTest =
FingerprintViewModel(
context,
transitionInteractor,
udfpsKeyguardInteractor,
UdfpsKeyguardInteractor(
configRepository,
BurnInInteractor(
context,
burnInHelper,
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
),
keyguardInteractor,
shadeRepository,
dialogManager,
),
keyguardInteractor,
)
}

View File

@@ -20,12 +20,26 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.settingslib.Utils
import com.android.systemui.SysuiTestCase
import com.android.systemui.bouncer.data.repository.FakeKeyguardBouncerRepository
import com.android.systemui.common.ui.data.repository.FakeConfigurationRepository
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.FakeFeatureFlags
import com.android.systemui.flags.Flags
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.domain.interactor.BurnInInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.domain.interactor.UdfpsKeyguardInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.statusbar.phone.SystemUIDialogManager
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.time.FakeSystemClock
import com.google.common.collect.Range
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -35,6 +49,8 @@ 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.Mockito
import org.mockito.MockitoAnnotations
/** Tests UDFPS lockscreen view model transitions. */
@@ -48,26 +64,63 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
private val alternateBouncerColor =
Utils.getColorAttrDefaultColor(context, alternateBouncerResId)
@Mock private lateinit var dialogManager: SystemUIDialogManager
private lateinit var underTest: UdfpsLockscreenViewModel
private lateinit var testScope: TestScope
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
private lateinit var configRepository: FakeConfigurationRepository
private lateinit var keyguardRepository: FakeKeyguardRepository
private lateinit var bouncerRepository: FakeKeyguardBouncerRepository
private lateinit var shadeRepository: FakeShadeRepository
private lateinit var featureFlags: FakeFeatureFlags
@Before
fun setUp() {
MockitoAnnotations.initMocks(this)
testScope = TestScope()
transitionRepository = FakeKeyguardTransitionRepository()
val transitionInteractor =
KeyguardTransitionInteractor(
transitionRepository,
testScope.backgroundScope,
configRepository = FakeConfigurationRepository()
keyguardRepository = FakeKeyguardRepository()
bouncerRepository = FakeKeyguardBouncerRepository()
shadeRepository = FakeShadeRepository()
featureFlags =
FakeFeatureFlags().apply {
set(Flags.REFACTOR_UDFPS_KEYGUARD_VIEWS, true)
set(Flags.FACE_AUTH_REFACTOR, false)
}
val keyguardInteractor =
KeyguardInteractor(
keyguardRepository,
commandQueue = mock(),
featureFlags,
bouncerRepository,
configRepository,
)
underTest =
UdfpsLockscreenViewModel(
context,
lockscreenColorResId,
alternateBouncerResId,
transitionInteractor,
KeyguardTransitionInteractor(
transitionRepository,
testScope.backgroundScope,
),
UdfpsKeyguardInteractor(
configRepository,
BurnInInteractor(
context,
burnInHelperWrapper = mock(),
testScope.backgroundScope,
configRepository,
FakeSystemClock(),
),
keyguardInteractor,
shadeRepository,
dialogManager,
),
keyguardInteractor,
)
}
@@ -125,6 +178,7 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
testScope.runTest {
val transition by collectLastValue(underTest.transition)
val visible by collectLastValue(underTest.visible)
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
// TransitionState.STARTED: lockscreen -> AOD
transitionRepository.sendTransitionStep(
@@ -175,6 +229,56 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
assertThat(visible).isFalse()
}
@Test
fun lockscreenShadeLockedToAod() =
testScope.runTest {
val transition by collectLastValue(underTest.transition)
val visible by collectLastValue(underTest.visible)
keyguardRepository.setStatusBarState(StatusBarState.SHADE_LOCKED)
// TransitionState.STARTED: lockscreen -> AOD
transitionRepository.sendTransitionStep(
TransitionStep(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.AOD,
value = 0f,
transitionState = TransitionState.STARTED,
ownerName = "lockscreenToAod",
)
)
runCurrent()
assertThat(transition?.alpha).isEqualTo(0f)
assertThat(visible).isFalse()
// TransitionState.RUNNING: lockscreen -> AOD
transitionRepository.sendTransitionStep(
TransitionStep(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.AOD,
value = .6f,
transitionState = TransitionState.RUNNING,
ownerName = "lockscreenToAod",
)
)
runCurrent()
assertThat(transition?.alpha).isEqualTo(0f)
assertThat(visible).isFalse()
// TransitionState.FINISHED: lockscreen -> AOD
transitionRepository.sendTransitionStep(
TransitionStep(
from = KeyguardState.LOCKSCREEN,
to = KeyguardState.AOD,
value = 1f,
transitionState = TransitionState.FINISHED,
ownerName = "lockscreenToAod",
)
)
runCurrent()
assertThat(transition?.alpha).isEqualTo(0f)
assertThat(visible).isFalse()
}
@Test
fun aodToLockscreen() =
testScope.runTest {
@@ -235,6 +339,7 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
testScope.runTest {
val transition by collectLastValue(underTest.transition)
val visible by collectLastValue(underTest.visible)
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
// TransitionState.STARTED: lockscreen -> alternate bouncer
transitionRepository.sendTransitionStep(
@@ -398,6 +503,7 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
testScope.runTest {
val transition by collectLastValue(underTest.transition)
val visible by collectLastValue(underTest.visible)
keyguardRepository.setStatusBarState(StatusBarState.KEYGUARD)
// TransitionState.STARTED: lockscreen -> occluded
transitionRepository.sendTransitionStep(
@@ -502,4 +608,96 @@ class UdfpsLockscreenViewModelTest : SysuiTestCase() {
assertThat(transition?.color).isEqualTo(lockscreenColor)
assertThat(visible).isTrue()
}
@Test
fun qsProgressChange() =
testScope.runTest {
val transition by collectLastValue(underTest.transition)
val visible by collectLastValue(underTest.visible)
givenTransitionToLockscreenFinished()
// qsExpansion = 0f
shadeRepository.setQsExpansion(0f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(1f)
assertThat(visible).isEqualTo(true)
// qsExpansion = .25
shadeRepository.setQsExpansion(.2f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(.6f)
assertThat(visible).isEqualTo(true)
// qsExpansion = .5
shadeRepository.setQsExpansion(.5f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(0f)
assertThat(visible).isEqualTo(false)
// qsExpansion = 1
shadeRepository.setQsExpansion(1f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(0f)
assertThat(visible).isEqualTo(false)
}
@Test
fun shadeExpansionChanged() =
testScope.runTest {
val transition by collectLastValue(underTest.transition)
val visible by collectLastValue(underTest.visible)
givenTransitionToLockscreenFinished()
// shadeExpansion = 0f
shadeRepository.setUdfpsTransitionToFullShadeProgress(0f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(1f)
assertThat(visible).isEqualTo(true)
// shadeExpansion = .2
shadeRepository.setUdfpsTransitionToFullShadeProgress(.2f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(.8f)
assertThat(visible).isEqualTo(true)
// shadeExpansion = .5
shadeRepository.setUdfpsTransitionToFullShadeProgress(.5f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(.5f)
assertThat(visible).isEqualTo(true)
// shadeExpansion = 1
shadeRepository.setUdfpsTransitionToFullShadeProgress(1f)
runCurrent()
assertThat(transition?.alpha).isEqualTo(0f)
assertThat(visible).isEqualTo(false)
}
@Test
fun dialogHideAffordancesRequestChanged() =
testScope.runTest {
val transition by collectLastValue(underTest.transition)
givenTransitionToLockscreenFinished()
runCurrent()
val captor = argumentCaptor<SystemUIDialogManager.Listener>()
Mockito.verify(dialogManager).registerListener(captor.capture())
captor.value.shouldHideAffordances(true)
assertThat(transition?.alpha).isEqualTo(0f)
captor.value.shouldHideAffordances(false)
assertThat(transition?.alpha).isEqualTo(1f)
}
private suspend fun givenTransitionToLockscreenFinished() {
transitionRepository.sendTransitionStep(
TransitionStep(
from = KeyguardState.AOD,
to = KeyguardState.LOCKSCREEN,
value = 1f,
transitionState = TransitionState.FINISHED,
ownerName = "givenTransitionToLockscreenFinished",
)
)
}
}