Merge "Fade out UDFPS on shadeExpand & dialogProgress" into udc-qpr-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
09311d9d90
@@ -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(
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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) }
|
||||
}
|
||||
@@ -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)))
|
||||
|
||||
@@ -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 =
|
||||
|
||||
@@ -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,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -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",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user