Loading packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt +7 −1 Original line number Diff line number Diff line Loading @@ -235,7 +235,13 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() { .isEqualTo( listOf( // The initial transition will also get sent when collect started TransitionStep(OFF, LOCKSCREEN, 0f, STARTED), TransitionStep( OFF, LOCKSCREEN, 0f, STARTED, ownerName = "KeyguardTransitionRepository(boot)" ), steps[0], steps[3], steps[6] Loading packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt +9 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,15 @@ constructor( authenticationInteractor.getAuthenticationMethod().isSecure } /** * Whether the lockscreen is enabled for the current user. This is `true` whenever the user has * chosen any secure authentication method and even if they set the lockscreen to be dismissed * when the user swipes on it. */ suspend fun isLockscreenEnabled(): Boolean { return repository.isLockscreenEnabled() } /** * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically * dismissed once the authentication challenge is completed. For example, completing a biometric Loading packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt +39 −29 Original line number Diff line number Diff line Loading @@ -88,6 +88,12 @@ interface KeyguardTransitionRepository { */ suspend fun startTransition(info: TransitionInfo): UUID? /** * Emits STARTED and FINISHED transition steps to the given state. This is used during boot to * seed the repository with the appropriate initial state. */ suspend fun emitInitialStepsFromOff(to: KeyguardState) /** * Allows manual control of a transition. When calling [startTransition], the consumer must pass * in a null animator. In return, it will get a unique [UUID] that will be validated to allow Loading Loading @@ -141,9 +147,17 @@ constructor( private var updateTransitionId: UUID? = null init { // Seed with transitions signaling a boot into lockscreen state. If updating this, please // also update FakeKeyguardTransitionRepository. initialTransitionSteps.forEach(::emitTransition) // Start with a FINISHED transition in OFF. KeyguardBootInteractor will transition from OFF // to either GONE or LOCKSCREEN once we're booted up and can determine which state we should // start in. emitTransition( TransitionStep( KeyguardState.OFF, KeyguardState.OFF, 1f, TransitionState.FINISHED, ) ) } override suspend fun startTransition(info: TransitionInfo): UUID? { Loading Loading @@ -251,6 +265,28 @@ constructor( lastStep = nextStep } override suspend fun emitInitialStepsFromOff(to: KeyguardState) { emitTransition( TransitionStep( KeyguardState.OFF, to, 0f, TransitionState.STARTED, ownerName = "KeyguardTransitionRepository(boot)", ) ) emitTransition( TransitionStep( KeyguardState.OFF, to, 1f, TransitionState.FINISHED, ownerName = "KeyguardTransitionRepository(boot)", ), ) } private fun logAndTrace(step: TransitionStep, isManual: Boolean) { if (step.transitionState == TransitionState.RUNNING) { return Loading @@ -271,31 +307,5 @@ constructor( companion object { private const val TAG = "KeyguardTransitionRepository" /** * Transition steps to seed the repository with, so that all of the transition interactor * flows emit reasonable initial values. */ val initialTransitionSteps: List<TransitionStep> = listOf( TransitionStep( KeyguardState.OFF, KeyguardState.OFF, 1f, TransitionState.FINISHED, ), TransitionStep( KeyguardState.OFF, KeyguardState.LOCKSCREEN, 0f, TransitionState.STARTED, ), TransitionStep( KeyguardState.OFF, KeyguardState.LOCKSCREEN, 1f, TransitionState.FINISHED, ), ) } } packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +5 −5 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ constructor( listenForTransitionToCamera(scope, keyguardInteractor) } private val canDismissLockScreen: Flow<Boolean> = private val canTransitionToGoneOnWake: Flow<Boolean> = combine( keyguardInteractor.isKeyguardShowing, keyguardInteractor.isKeyguardDismissible, Loading @@ -87,7 +87,7 @@ constructor( keyguardInteractor.biometricUnlockState, keyguardInteractor.isKeyguardOccluded, communalInteractor.isIdleOnCommunal, canDismissLockScreen, canTransitionToGoneOnWake, keyguardInteractor.primaryBouncerShowing, ) .collect { Loading @@ -96,12 +96,12 @@ constructor( biometricUnlockState, occluded, isIdleOnCommunal, canDismissLockScreen, canTransitionToGoneOnWake, primaryBouncerShowing) -> startTransitionTo( if (isWakeAndUnlock(biometricUnlockState.mode)) { KeyguardState.GONE } else if (canDismissLockScreen) { } else if (canTransitionToGoneOnWake) { KeyguardState.GONE } else if (primaryBouncerShowing) { KeyguardState.PRIMARY_BOUNCER Loading Loading @@ -129,7 +129,7 @@ constructor( .sample( communalInteractor.isIdleOnCommunal, keyguardInteractor.biometricUnlockState, canDismissLockScreen, canTransitionToGoneOnWake, keyguardInteractor.primaryBouncerShowing, ) .collect { Loading packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.domain.interactor import android.util.Log import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch /** Handles initialization of the KeyguardTransitionRepository on boot. */ @SysUISingleton class KeyguardTransitionBootInteractor @Inject constructor( @Application val scope: CoroutineScope, val deviceEntryInteractor: DeviceEntryInteractor, val deviceProvisioningInteractor: DeviceProvisioningInteractor, val keyguardTransitionInteractor: KeyguardTransitionInteractor, val repository: KeyguardTransitionRepository, ) : CoreStartable { /** * Whether the lockscreen should be showing when the device starts up for the first time. If not * then we'll seed the repository with a transition from OFF -> GONE. */ @OptIn(ExperimentalCoroutinesApi::class) private val showLockscreenOnBoot = deviceProvisioningInteractor.isDeviceProvisioned.map { provisioned -> (provisioned || deviceEntryInteractor.isAuthenticationRequired()) && deviceEntryInteractor.isLockscreenEnabled() } override fun start() { scope.launch { val state = if (showLockscreenOnBoot.first()) { KeyguardState.LOCKSCREEN } else { KeyguardState.GONE } if ( keyguardTransitionInteractor.currentTransitionInfoInternal.value.from != KeyguardState.OFF ) { Log.e( "KeyguardTransitionInteractor", "showLockscreenOnBoot emitted, but we've already " + "transitioned to a state other than OFF. We'll respect that " + "transition, but this should not happen." ) } else { repository.emitInitialStepsFromOff(state) } } } } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionInteractorTest.kt +7 −1 Original line number Diff line number Diff line Loading @@ -235,7 +235,13 @@ class KeyguardTransitionInteractorTest : SysuiTestCase() { .isEqualTo( listOf( // The initial transition will also get sent when collect started TransitionStep(OFF, LOCKSCREEN, 0f, STARTED), TransitionStep( OFF, LOCKSCREEN, 0f, STARTED, ownerName = "KeyguardTransitionRepository(boot)" ), steps[0], steps[3], steps[6] Loading
packages/SystemUI/src/com/android/systemui/deviceentry/domain/interactor/DeviceEntryInteractor.kt +9 −0 Original line number Diff line number Diff line Loading @@ -239,6 +239,15 @@ constructor( authenticationInteractor.getAuthenticationMethod().isSecure } /** * Whether the lockscreen is enabled for the current user. This is `true` whenever the user has * chosen any secure authentication method and even if they set the lockscreen to be dismissed * when the user swipes on it. */ suspend fun isLockscreenEnabled(): Boolean { return repository.isLockscreenEnabled() } /** * Whether lockscreen bypass is enabled. When enabled, the lockscreen will be automatically * dismissed once the authentication challenge is completed. For example, completing a biometric Loading
packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardTransitionRepository.kt +39 −29 Original line number Diff line number Diff line Loading @@ -88,6 +88,12 @@ interface KeyguardTransitionRepository { */ suspend fun startTransition(info: TransitionInfo): UUID? /** * Emits STARTED and FINISHED transition steps to the given state. This is used during boot to * seed the repository with the appropriate initial state. */ suspend fun emitInitialStepsFromOff(to: KeyguardState) /** * Allows manual control of a transition. When calling [startTransition], the consumer must pass * in a null animator. In return, it will get a unique [UUID] that will be validated to allow Loading Loading @@ -141,9 +147,17 @@ constructor( private var updateTransitionId: UUID? = null init { // Seed with transitions signaling a boot into lockscreen state. If updating this, please // also update FakeKeyguardTransitionRepository. initialTransitionSteps.forEach(::emitTransition) // Start with a FINISHED transition in OFF. KeyguardBootInteractor will transition from OFF // to either GONE or LOCKSCREEN once we're booted up and can determine which state we should // start in. emitTransition( TransitionStep( KeyguardState.OFF, KeyguardState.OFF, 1f, TransitionState.FINISHED, ) ) } override suspend fun startTransition(info: TransitionInfo): UUID? { Loading Loading @@ -251,6 +265,28 @@ constructor( lastStep = nextStep } override suspend fun emitInitialStepsFromOff(to: KeyguardState) { emitTransition( TransitionStep( KeyguardState.OFF, to, 0f, TransitionState.STARTED, ownerName = "KeyguardTransitionRepository(boot)", ) ) emitTransition( TransitionStep( KeyguardState.OFF, to, 1f, TransitionState.FINISHED, ownerName = "KeyguardTransitionRepository(boot)", ), ) } private fun logAndTrace(step: TransitionStep, isManual: Boolean) { if (step.transitionState == TransitionState.RUNNING) { return Loading @@ -271,31 +307,5 @@ constructor( companion object { private const val TAG = "KeyguardTransitionRepository" /** * Transition steps to seed the repository with, so that all of the transition interactor * flows emit reasonable initial values. */ val initialTransitionSteps: List<TransitionStep> = listOf( TransitionStep( KeyguardState.OFF, KeyguardState.OFF, 1f, TransitionState.FINISHED, ), TransitionStep( KeyguardState.OFF, KeyguardState.LOCKSCREEN, 0f, TransitionState.STARTED, ), TransitionStep( KeyguardState.OFF, KeyguardState.LOCKSCREEN, 1f, TransitionState.FINISHED, ), ) } }
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt +5 −5 Original line number Diff line number Diff line Loading @@ -66,7 +66,7 @@ constructor( listenForTransitionToCamera(scope, keyguardInteractor) } private val canDismissLockScreen: Flow<Boolean> = private val canTransitionToGoneOnWake: Flow<Boolean> = combine( keyguardInteractor.isKeyguardShowing, keyguardInteractor.isKeyguardDismissible, Loading @@ -87,7 +87,7 @@ constructor( keyguardInteractor.biometricUnlockState, keyguardInteractor.isKeyguardOccluded, communalInteractor.isIdleOnCommunal, canDismissLockScreen, canTransitionToGoneOnWake, keyguardInteractor.primaryBouncerShowing, ) .collect { Loading @@ -96,12 +96,12 @@ constructor( biometricUnlockState, occluded, isIdleOnCommunal, canDismissLockScreen, canTransitionToGoneOnWake, primaryBouncerShowing) -> startTransitionTo( if (isWakeAndUnlock(biometricUnlockState.mode)) { KeyguardState.GONE } else if (canDismissLockScreen) { } else if (canTransitionToGoneOnWake) { KeyguardState.GONE } else if (primaryBouncerShowing) { KeyguardState.PRIMARY_BOUNCER Loading Loading @@ -129,7 +129,7 @@ constructor( .sample( communalInteractor.isIdleOnCommunal, keyguardInteractor.biometricUnlockState, canDismissLockScreen, canTransitionToGoneOnWake, keyguardInteractor.primaryBouncerShowing, ) .collect { Loading
packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardTransitionBootInteractor.kt 0 → 100644 +81 −0 Original line number Diff line number Diff line /* * Copyright (C) 2024 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.domain.interactor import android.util.Log import com.android.systemui.CoreStartable import com.android.systemui.dagger.SysUISingleton import com.android.systemui.dagger.qualifiers.Application import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository import com.android.systemui.keyguard.shared.model.KeyguardState import com.android.systemui.statusbar.policy.domain.interactor.DeviceProvisioningInteractor import javax.inject.Inject import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.flow.first import kotlinx.coroutines.flow.map import kotlinx.coroutines.launch /** Handles initialization of the KeyguardTransitionRepository on boot. */ @SysUISingleton class KeyguardTransitionBootInteractor @Inject constructor( @Application val scope: CoroutineScope, val deviceEntryInteractor: DeviceEntryInteractor, val deviceProvisioningInteractor: DeviceProvisioningInteractor, val keyguardTransitionInteractor: KeyguardTransitionInteractor, val repository: KeyguardTransitionRepository, ) : CoreStartable { /** * Whether the lockscreen should be showing when the device starts up for the first time. If not * then we'll seed the repository with a transition from OFF -> GONE. */ @OptIn(ExperimentalCoroutinesApi::class) private val showLockscreenOnBoot = deviceProvisioningInteractor.isDeviceProvisioned.map { provisioned -> (provisioned || deviceEntryInteractor.isAuthenticationRequired()) && deviceEntryInteractor.isLockscreenEnabled() } override fun start() { scope.launch { val state = if (showLockscreenOnBoot.first()) { KeyguardState.LOCKSCREEN } else { KeyguardState.GONE } if ( keyguardTransitionInteractor.currentTransitionInfoInternal.value.from != KeyguardState.OFF ) { Log.e( "KeyguardTransitionInteractor", "showLockscreenOnBoot emitted, but we've already " + "transitioned to a state other than OFF. We'll respect that " + "transition, but this should not happen." ) } else { repository.emitInitialStepsFromOff(state) } } } }