Loading packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt +5 −4 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.res.R import com.android.systemui.res.R Loading @@ -64,9 +65,9 @@ fun AlternateBouncer( onHideAnimationFinished: () -> Unit, onHideAnimationFinished: () -> Unit, modifier: Modifier = Modifier, modifier: Modifier = Modifier, ) { ) { val alternateBouncerViewModel = val isVisible by rememberViewModel("AlternateBouncerViewModel") { alternateBouncerDependencies.viewModel } alternateBouncerDependencies.viewModel.isVisible.collectAsStateWithLifecycle(true) val isVisible by alternateBouncerViewModel.isVisible.collectAsStateWithLifecycle(true) val visibleState = remember { MutableTransitionState(isVisible) } val visibleState = remember { MutableTransitionState(isVisible) } // Feeds the isVisible value to the MutableTransitionState used by AnimatedVisibility below. // Feeds the isVisible value to the MutableTransitionState used by AnimatedVisibility below. Loading Loading @@ -98,7 +99,7 @@ fun AlternateBouncer( Modifier.background(color = Colors.AlternateBouncerBackgroundColor).pointerInput( Modifier.background(color = Colors.AlternateBouncerBackgroundColor).pointerInput( Unit Unit ) { ) { detectTapGestures(onTap = { alternateBouncerDependencies.viewModel.onTapped() }) detectTapGestures(onTap = { alternateBouncerViewModel.onTapped() }) }, }, ) { ) { StatusMessage(viewModel = alternateBouncerDependencies.messageAreaViewModel) StatusMessage(viewModel = alternateBouncerDependencies.messageAreaViewModel) Loading packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt +52 −0 Original line number Original line Diff line number Diff line Loading @@ -21,16 +21,21 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.internal.policy.IKeyguardDismissCallback import com.android.internal.policy.IKeyguardDismissCallback import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.FaceSensorInfo import com.android.systemui.biometrics.data.repository.fakeFacePropertyRepository import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.dismissCallbackRegistry import com.android.systemui.keyguard.dismissCallbackRegistry import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState 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.kosmos.testScope import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager import com.android.systemui.testKosmos import com.android.systemui.testKosmos Loading @@ -38,11 +43,15 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.eq import com.google.common.collect.Range import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyString import org.mockito.Mockito.mock import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.Mockito.verify import org.mockito.kotlin.never @RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class) @SmallTest @SmallTest Loading Loading @@ -154,6 +163,49 @@ class AlternateBouncerViewModelTest : SysuiTestCase() { assertThat(registerForDismissGestures).isFalse() assertThat(registerForDismissGestures).isFalse() } } @Test fun strongFaceAuthLockout_showPrimaryBouncer() = testScope.runTest { underTest.activateIn(this) setFaceAuthSensor(strength = SensorStrength.STRONG) runCurrent() kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true) runCurrent() verify(kosmos.statusBarKeyguardViewManager) .showPrimaryBouncer(anyBoolean(), anyString()) } @Test fun weakFaceAuthLockout_doNotShowPrimaryBouncer() = testScope.runTest { underTest.activateIn(this) setFaceAuthSensor(strength = SensorStrength.WEAK) runCurrent() kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true) runCurrent() verify(kosmos.statusBarKeyguardViewManager, never()) .showPrimaryBouncer(anyBoolean(), anyString()) } @Test fun convenienceFaceAuthLockout_doNotShowPrimaryBouncer() = testScope.runTest { underTest.activateIn(this) setFaceAuthSensor(strength = SensorStrength.CONVENIENCE) runCurrent() kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true) runCurrent() verify(kosmos.statusBarKeyguardViewManager, never()) .showPrimaryBouncer(anyBoolean(), anyString()) } private fun setFaceAuthSensor(strength: SensorStrength) { kosmos.fakeFacePropertyRepository.setSensorInfo(FaceSensorInfo(id = 0, strength = strength)) } private fun stepToAlternateBouncer( private fun stepToAlternateBouncer( value: Float, value: Float, state: TransitionState = TransitionState.RUNNING, state: TransitionState = TransitionState.RUNNING, Loading packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -54,7 +54,7 @@ constructor( */ */ val isFaceLockedOut: StateFlow<Boolean> = deviceEntryFaceAuthInteractor.isLockedOut val isFaceLockedOut: StateFlow<Boolean> = deviceEntryFaceAuthInteractor.isLockedOut private val isStrongFaceAuth: StateFlow<Boolean> = val isStrongFaceAuth: StateFlow<Boolean> = facePropertyRepository.sensorInfo facePropertyRepository.sensorInfo .map { it?.strength == SensorStrength.STRONG } .map { it?.strength == SensorStrength.STRONG } .stateIn( .stateIn( Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt +12 −0 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,9 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel import com.android.systemui.lifecycle.WindowLifecycleState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.viewModel import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.flag.SceneContainerFlag Loading Loading @@ -215,6 +217,16 @@ constructor( } } } } } } view.repeatWhenAttached { view.viewModel( traceName = "AlternateBouncerViewBinderViewModel", minWindowLifecycleState = WindowLifecycleState.ATTACHED, factory = { alternateBouncerDependencies.viewModel }, ) { // no-op - currently used to activate viewModel } } } } private fun optionallyAddUdfpsViews( private fun optionallyAddUdfpsViews( Loading packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt +28 −1 Original line number Original line Diff line number Diff line Loading @@ -20,18 +20,26 @@ package com.android.systemui.keyguard.ui.viewmodel import android.graphics.Color import android.graphics.Color import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import dagger.Lazy import dagger.Lazy import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch class AlternateBouncerViewModel class AlternateBouncerViewModel @Inject @Inject Loading @@ -41,7 +49,9 @@ constructor( private val dismissCallbackRegistry: DismissCallbackRegistry, private val dismissCallbackRegistry: DismissCallbackRegistry, alternateBouncerInteractor: Lazy<AlternateBouncerInteractor>, alternateBouncerInteractor: Lazy<AlternateBouncerInteractor>, private val primaryBouncerInteractor: PrimaryBouncerInteractor, private val primaryBouncerInteractor: PrimaryBouncerInteractor, ) { deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor, deviceEntryFaceAuthInteractor: SystemUIDeviceEntryFaceAuthInteractor, ) : ExclusiveActivatable() { // When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be: // When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be: private val alternateBouncerScrimAlpha = .66f private val alternateBouncerScrimAlpha = .66f Loading @@ -64,6 +74,19 @@ constructor( val registerForDismissGestures: Flow<Boolean> = val registerForDismissGestures: Flow<Boolean> = transitionToAlternateBouncerProgress.map { it == 1f }.distinctUntilChanged() transitionToAlternateBouncerProgress.map { it == 1f }.distinctUntilChanged() val strongFaceAuthLockout = deviceEntryBiometricsAllowedInteractor.isStrongFaceAuth.flatMapLatest { isStrongFaceAuth -> if (isStrongFaceAuth) { deviceEntryFaceAuthInteractor.isLockedOut.filter { it }.map {} // Unit } else { emptyFlow() } } override suspend fun onActivated() { coroutineScope { launch { strongFaceAuthLockout.collect { onStrongFaceAuthLockout() } } } } fun onTapped() { fun onTapped() { statusBarKeyguardViewManager.showPrimaryBouncer( statusBarKeyguardViewManager.showPrimaryBouncer( /* scrimmed */ true, /* scrimmed */ true, Loading @@ -80,4 +103,8 @@ constructor( dismissCallbackRegistry.notifyDismissCancelled() dismissCallbackRegistry.notifyDismissCancelled() primaryBouncerInteractor.setDismissAction(null, null) primaryBouncerInteractor.setDismissAction(null, null) } } private fun onStrongFaceAuthLockout() { statusBarKeyguardViewManager.showPrimaryBouncer(true, "strongFaceAuthLockout") } } } Loading
packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/AlternateBouncer.kt +5 −4 Original line number Original line Diff line number Diff line Loading @@ -55,6 +55,7 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerMessageAreaViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.lifecycle.rememberViewModel import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.res.R import com.android.systemui.res.R Loading @@ -64,9 +65,9 @@ fun AlternateBouncer( onHideAnimationFinished: () -> Unit, onHideAnimationFinished: () -> Unit, modifier: Modifier = Modifier, modifier: Modifier = Modifier, ) { ) { val alternateBouncerViewModel = val isVisible by rememberViewModel("AlternateBouncerViewModel") { alternateBouncerDependencies.viewModel } alternateBouncerDependencies.viewModel.isVisible.collectAsStateWithLifecycle(true) val isVisible by alternateBouncerViewModel.isVisible.collectAsStateWithLifecycle(true) val visibleState = remember { MutableTransitionState(isVisible) } val visibleState = remember { MutableTransitionState(isVisible) } // Feeds the isVisible value to the MutableTransitionState used by AnimatedVisibility below. // Feeds the isVisible value to the MutableTransitionState used by AnimatedVisibility below. Loading Loading @@ -98,7 +99,7 @@ fun AlternateBouncer( Modifier.background(color = Colors.AlternateBouncerBackgroundColor).pointerInput( Modifier.background(color = Colors.AlternateBouncerBackgroundColor).pointerInput( Unit Unit ) { ) { detectTapGestures(onTap = { alternateBouncerDependencies.viewModel.onTapped() }) detectTapGestures(onTap = { alternateBouncerViewModel.onTapped() }) }, }, ) { ) { StatusMessage(viewModel = alternateBouncerDependencies.messageAreaViewModel) StatusMessage(viewModel = alternateBouncerDependencies.messageAreaViewModel) Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModelTest.kt +52 −0 Original line number Original line Diff line number Diff line Loading @@ -21,16 +21,21 @@ import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest import com.android.internal.policy.IKeyguardDismissCallback import com.android.internal.policy.IKeyguardDismissCallback import com.android.systemui.SysuiTestCase import com.android.systemui.SysuiTestCase import com.android.systemui.biometrics.data.repository.FaceSensorInfo import com.android.systemui.biometrics.data.repository.fakeFacePropertyRepository import com.android.systemui.biometrics.shared.model.SensorStrength import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor import com.android.systemui.bouncer.domain.interactor.primaryBouncerInteractor import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.concurrency.fakeExecutor import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectLastValue import com.android.systemui.coroutines.collectValues import com.android.systemui.coroutines.collectValues import com.android.systemui.keyguard.data.repository.fakeDeviceEntryFaceAuthRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository import com.android.systemui.keyguard.dismissCallbackRegistry import com.android.systemui.keyguard.dismissCallbackRegistry import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.keyguard.shared.model.KeyguardState 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.kosmos.testScope import com.android.systemui.kosmos.testScope import com.android.systemui.lifecycle.activateIn import com.android.systemui.plugins.ActivityStarter import com.android.systemui.plugins.ActivityStarter import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager import com.android.systemui.statusbar.phone.statusBarKeyguardViewManager import com.android.systemui.testKosmos import com.android.systemui.testKosmos Loading @@ -38,11 +43,15 @@ import com.android.systemui.util.mockito.any import com.android.systemui.util.mockito.eq import com.android.systemui.util.mockito.eq import com.google.common.collect.Range import com.google.common.collect.Range import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat import kotlinx.coroutines.test.runCurrent import kotlinx.coroutines.test.runTest import kotlinx.coroutines.test.runTest import org.junit.Test import org.junit.Test import org.junit.runner.RunWith import org.junit.runner.RunWith import org.mockito.ArgumentMatchers.anyBoolean import org.mockito.ArgumentMatchers.anyString import org.mockito.Mockito.mock import org.mockito.Mockito.mock import org.mockito.Mockito.verify import org.mockito.Mockito.verify import org.mockito.kotlin.never @RunWith(AndroidJUnit4::class) @RunWith(AndroidJUnit4::class) @SmallTest @SmallTest Loading Loading @@ -154,6 +163,49 @@ class AlternateBouncerViewModelTest : SysuiTestCase() { assertThat(registerForDismissGestures).isFalse() assertThat(registerForDismissGestures).isFalse() } } @Test fun strongFaceAuthLockout_showPrimaryBouncer() = testScope.runTest { underTest.activateIn(this) setFaceAuthSensor(strength = SensorStrength.STRONG) runCurrent() kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true) runCurrent() verify(kosmos.statusBarKeyguardViewManager) .showPrimaryBouncer(anyBoolean(), anyString()) } @Test fun weakFaceAuthLockout_doNotShowPrimaryBouncer() = testScope.runTest { underTest.activateIn(this) setFaceAuthSensor(strength = SensorStrength.WEAK) runCurrent() kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true) runCurrent() verify(kosmos.statusBarKeyguardViewManager, never()) .showPrimaryBouncer(anyBoolean(), anyString()) } @Test fun convenienceFaceAuthLockout_doNotShowPrimaryBouncer() = testScope.runTest { underTest.activateIn(this) setFaceAuthSensor(strength = SensorStrength.CONVENIENCE) runCurrent() kosmos.fakeDeviceEntryFaceAuthRepository.setLockedOut(true) runCurrent() verify(kosmos.statusBarKeyguardViewManager, never()) .showPrimaryBouncer(anyBoolean(), anyString()) } private fun setFaceAuthSensor(strength: SensorStrength) { kosmos.fakeFacePropertyRepository.setSensorInfo(FaceSensorInfo(id = 0, strength = strength)) } private fun stepToAlternateBouncer( private fun stepToAlternateBouncer( value: Float, value: Float, state: TransitionState = TransitionState.RUNNING, state: TransitionState = TransitionState.RUNNING, Loading
packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryBiometricsAllowedInteractor.kt +1 −1 Original line number Original line Diff line number Diff line Loading @@ -54,7 +54,7 @@ constructor( */ */ val isFaceLockedOut: StateFlow<Boolean> = deviceEntryFaceAuthInteractor.isLockedOut val isFaceLockedOut: StateFlow<Boolean> = deviceEntryFaceAuthInteractor.isLockedOut private val isStrongFaceAuth: StateFlow<Boolean> = val isStrongFaceAuth: StateFlow<Boolean> = facePropertyRepository.sensorInfo facePropertyRepository.sensorInfo .map { it?.strength == SensorStrength.STRONG } .map { it?.strength == SensorStrength.STRONG } .stateIn( .stateIn( Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/binder/AlternateBouncerViewBinder.kt +12 −0 Original line number Original line Diff line number Diff line Loading @@ -39,7 +39,9 @@ import com.android.systemui.keyguard.ui.view.DeviceEntryIconView import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerDependencies import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerUdfpsIconViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel import com.android.systemui.keyguard.ui.viewmodel.AlternateBouncerWindowViewModel import com.android.systemui.lifecycle.WindowLifecycleState import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.repeatWhenAttached import com.android.systemui.lifecycle.viewModel import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.log.TouchHandlingViewLogger import com.android.systemui.res.R import com.android.systemui.res.R import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.flag.SceneContainerFlag Loading Loading @@ -215,6 +217,16 @@ constructor( } } } } } } view.repeatWhenAttached { view.viewModel( traceName = "AlternateBouncerViewBinderViewModel", minWindowLifecycleState = WindowLifecycleState.ATTACHED, factory = { alternateBouncerDependencies.viewModel }, ) { // no-op - currently used to activate viewModel } } } } private fun optionallyAddUdfpsViews( private fun optionallyAddUdfpsViews( Loading
packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/AlternateBouncerViewModel.kt +28 −1 Original line number Original line Diff line number Diff line Loading @@ -20,18 +20,26 @@ package com.android.systemui.keyguard.ui.viewmodel import android.graphics.Color import android.graphics.Color import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.AlternateBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.bouncer.domain.interactor.PrimaryBouncerInteractor import com.android.systemui.deviceentry.domain.interactor.DeviceEntryBiometricsAllowedInteractor import com.android.systemui.deviceentry.domain.interactor.SystemUIDeviceEntryFaceAuthInteractor import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.DismissCallbackRegistry import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.keyguard.shared.model.KeyguardState.ALTERNATE_BOUNCER import com.android.systemui.lifecycle.ExclusiveActivatable import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.scene.shared.flag.SceneContainerFlag import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import com.android.systemui.statusbar.phone.StatusBarKeyguardViewManager import dagger.Lazy import dagger.Lazy import javax.inject.Inject import javax.inject.Inject import kotlinx.coroutines.coroutineScope import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.Flow import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.distinctUntilChanged import kotlinx.coroutines.flow.emptyFlow import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.flatMapLatest import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.flowOf import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.map import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.launch class AlternateBouncerViewModel class AlternateBouncerViewModel @Inject @Inject Loading @@ -41,7 +49,9 @@ constructor( private val dismissCallbackRegistry: DismissCallbackRegistry, private val dismissCallbackRegistry: DismissCallbackRegistry, alternateBouncerInteractor: Lazy<AlternateBouncerInteractor>, alternateBouncerInteractor: Lazy<AlternateBouncerInteractor>, private val primaryBouncerInteractor: PrimaryBouncerInteractor, private val primaryBouncerInteractor: PrimaryBouncerInteractor, ) { deviceEntryBiometricsAllowedInteractor: DeviceEntryBiometricsAllowedInteractor, deviceEntryFaceAuthInteractor: SystemUIDeviceEntryFaceAuthInteractor, ) : ExclusiveActivatable() { // When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be: // When we're fully transitioned to the AlternateBouncer, the alpha of the scrim should be: private val alternateBouncerScrimAlpha = .66f private val alternateBouncerScrimAlpha = .66f Loading @@ -64,6 +74,19 @@ constructor( val registerForDismissGestures: Flow<Boolean> = val registerForDismissGestures: Flow<Boolean> = transitionToAlternateBouncerProgress.map { it == 1f }.distinctUntilChanged() transitionToAlternateBouncerProgress.map { it == 1f }.distinctUntilChanged() val strongFaceAuthLockout = deviceEntryBiometricsAllowedInteractor.isStrongFaceAuth.flatMapLatest { isStrongFaceAuth -> if (isStrongFaceAuth) { deviceEntryFaceAuthInteractor.isLockedOut.filter { it }.map {} // Unit } else { emptyFlow() } } override suspend fun onActivated() { coroutineScope { launch { strongFaceAuthLockout.collect { onStrongFaceAuthLockout() } } } } fun onTapped() { fun onTapped() { statusBarKeyguardViewManager.showPrimaryBouncer( statusBarKeyguardViewManager.showPrimaryBouncer( /* scrimmed */ true, /* scrimmed */ true, Loading @@ -80,4 +103,8 @@ constructor( dismissCallbackRegistry.notifyDismissCancelled() dismissCallbackRegistry.notifyDismissCancelled() primaryBouncerInteractor.setDismissAction(null, null) primaryBouncerInteractor.setDismissAction(null, null) } } private fun onStrongFaceAuthLockout() { statusBarKeyguardViewManager.showPrimaryBouncer(true, "strongFaceAuthLockout") } } }