Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 01d160af authored by Matt Pietal's avatar Matt Pietal
Browse files

Transitions - Add more source data, refine existing transitions

Data sources - Listen for events from the BiometricUnlockController
and KeyguardStateController#isBouncerShowing

Repositories - Add isBouncerShowing and WakeAndUnlock events into
KeyguardRepository

Interactors - Refine keyguard transitions so that states are more
accurate

BiometricUnlockController - Allow multiple listeners so that events
can make it into the KeyguardRepository. Cleanup redundant callback.

Test: ClockEventControllerTest KeyguardRepositoryImplTest
KeyguardTransitionRepositoryTest KeyguardTransitionInteractorTest
BiometricsUnlockControllerTest CentralSurfacesImplTest
Bug: 195430376

Change-Id: I983277fd9764d88c078bbf6da117cec3dd12dede
parent 847d0f53
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -228,7 +228,7 @@ open class ClockEventController @Inject constructor(
                listenForDozing(this)
                if (featureFlags.isEnabled(DOZING_MIGRATION_1)) {
                    listenForDozeAmountTransition(this)
                    listenForGoneToAodTransition(this)
                    listenForAnyStateToAodTransition(this)
                } else {
                    listenForDozeAmount(this)
                }
@@ -286,10 +286,10 @@ open class ClockEventController @Inject constructor(
     * dozing.
     */
    @VisibleForTesting
    internal fun listenForGoneToAodTransition(scope: CoroutineScope): Job {
    internal fun listenForAnyStateToAodTransition(scope: CoroutineScope): Job {
        return scope.launch {
            keyguardTransitionInteractor.goneToAodTransition.filter {
                it.transitionState == TransitionState.STARTED
            keyguardTransitionInteractor.anyStateToAodTransition.filter {
                it.transitionState == TransitionState.FINISHED
            }.collect {
                dozeAmount = 1f
                clock?.animations?.doze(dozeAmount)
+65 −0
Original line number Diff line number Diff line
@@ -23,9 +23,12 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.WakefulnessLifecycle.Wakefulness
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.WakeAndUnlockMode
import com.android.systemui.statusbar.policy.KeyguardStateController
import javax.inject.Inject
import kotlinx.coroutines.channels.awaitClose
@@ -65,6 +68,9 @@ interface KeyguardRepository {
     */
    val isKeyguardShowing: Flow<Boolean>

    /** Observable for whether the bouncer is showing. */
    val isBouncerShowing: Flow<Boolean>

    /**
     * Observable for whether we are in doze state.
     *
@@ -95,6 +101,9 @@ interface KeyguardRepository {
    /** Observable for device wake/sleep state */
    val wakefulnessState: Flow<WakefulnessModel>

    /** Observable for biometric unlock modes */
    val biometricUnlockState: Flow<BiometricUnlockModel>

    /**
     * Returns `true` if the keyguard is showing; `false` otherwise.
     *
@@ -125,6 +134,7 @@ constructor(
    private val keyguardStateController: KeyguardStateController,
    dozeHost: DozeHost,
    wakefulnessLifecycle: WakefulnessLifecycle,
    biometricUnlockController: BiometricUnlockController,
) : KeyguardRepository {
    private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
    override val animateBottomAreaDozingTransitions =
@@ -159,6 +169,29 @@ constructor(
        awaitClose { keyguardStateController.removeCallback(callback) }
    }

    override val isBouncerShowing: Flow<Boolean> = conflatedCallbackFlow {
        val callback =
            object : KeyguardStateController.Callback {
                override fun onBouncerShowingChanged() {
                    trySendWithFailureLogging(
                        keyguardStateController.isBouncerShowing,
                        TAG,
                        "updated isBouncerShowing"
                    )
                }
            }

        keyguardStateController.addCallback(callback)
        // Adding the callback does not send an initial update.
        trySendWithFailureLogging(
            keyguardStateController.isBouncerShowing,
            TAG,
            "initial isBouncerShowing"
        )

        awaitClose { keyguardStateController.removeCallback(callback) }
    }

    override val isDozing: Flow<Boolean> =
        conflatedCallbackFlow {
                val callback =
@@ -248,6 +281,24 @@ constructor(
        awaitClose { wakefulnessLifecycle.removeObserver(callback) }
    }

    override val biometricUnlockState: Flow<BiometricUnlockModel> = conflatedCallbackFlow {
        val callback =
            object : BiometricUnlockController.BiometricModeListener {
                override fun onModeChanged(@WakeAndUnlockMode mode: Int) {
                    trySendWithFailureLogging(biometricModeIntToObject(mode), TAG, "biometric mode")
                }
            }

        biometricUnlockController.addBiometricModeListener(callback)
        trySendWithFailureLogging(
            biometricModeIntToObject(biometricUnlockController.getMode()),
            TAG,
            "initial biometric mode"
        )

        awaitClose { biometricUnlockController.removeBiometricModeListener(callback) }
    }

    override fun setAnimateDozingTransitions(animate: Boolean) {
        _animateBottomAreaDozingTransitions.value = animate
    }
@@ -279,6 +330,20 @@ constructor(
        }
    }

    private fun biometricModeIntToObject(@WakeAndUnlockMode value: Int): BiometricUnlockModel {
        return when (value) {
            0 -> BiometricUnlockModel.NONE
            1 -> BiometricUnlockModel.WAKE_AND_UNLOCK
            2 -> BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
            3 -> BiometricUnlockModel.SHOW_BOUNCER
            4 -> BiometricUnlockModel.ONLY_WAKE
            5 -> BiometricUnlockModel.UNLOCK_COLLAPSING
            6 -> BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
            7 -> BiometricUnlockModel.DISMISS_BOUNCER
            else -> throw IllegalArgumentException("Invalid BiometricUnlockModel value: $value")
        }
    }

    companion object {
        private const val TAG = "KeyguardRepositoryImpl"
    }
+81 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2022 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.animation.ValueAnimator
import com.android.systemui.animation.Interpolators
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_FROM_DREAM
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel.WAKE_AND_UNLOCK_PULSING
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.launch

@SysUISingleton
class AodToGoneTransitionInteractor
@Inject
constructor(
    @Application private val scope: CoroutineScope,
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionRepository: KeyguardTransitionRepository,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor("AOD->GONE") {

    private val wakeAndUnlockModes =
        setOf(WAKE_AND_UNLOCK, WAKE_AND_UNLOCK_FROM_DREAM, WAKE_AND_UNLOCK_PULSING)

    override fun start() {
        scope.launch {
            keyguardInteractor.biometricUnlockState
                .sample(keyguardTransitionInteractor.finishedKeyguardState, { a, b -> Pair(a, b) })
                .collect { pair ->
                    val (biometricUnlockState, keyguardState) = pair
                    if (
                        keyguardState == KeyguardState.AOD &&
                            wakeAndUnlockModes.contains(biometricUnlockState)
                    ) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
                                KeyguardState.AOD,
                                KeyguardState.GONE,
                                getAnimator(),
                            )
                        )
                    }
                }
        }
    }

    private fun getAnimator(): ValueAnimator {
        return ValueAnimator().apply {
            setInterpolator(Interpolators.LINEAR)
            setDuration(TRANSITION_DURATION_MS)
        }
    }

    companion object {
        private const val TRANSITION_DURATION_MS = 500L
    }
}
+12 −1
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ package com.android.systemui.keyguard.domain.interactor

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import javax.inject.Inject
import kotlinx.coroutines.flow.Flow
@@ -39,10 +41,19 @@ constructor(
    val dozeAmount: Flow<Float> = repository.dozeAmount
    /** Whether the system is in doze mode. */
    val isDozing: Flow<Boolean> = repository.isDozing
    /** Whether the keyguard is showing to not. */
    /** Whether the keyguard is showing or not. */
    val isKeyguardShowing: Flow<Boolean> = repository.isKeyguardShowing
    /** Whether the bouncer is showing or not. */
    val isBouncerShowing: Flow<Boolean> = repository.isBouncerShowing
    /** The device wake/sleep state */
    val wakefulnessState: Flow<WakefulnessModel> = repository.wakefulnessState
    /** Observable for the [StatusBarState] */
    val statusBarState: Flow<StatusBarState> = repository.statusBarState
    /**
     * Observable for [BiometricUnlockModel] when biometrics like face or any fingerprint (rear,
     * side, under display) is used to unlock the device.
     */
    val biometricUnlockState: Flow<BiometricUnlockModel> = repository.biometricUnlockState

    fun isKeyguardShowing(): Boolean {
        return repository.isKeyguardShowing()
+4 −2
Original line number Diff line number Diff line
@@ -41,11 +41,13 @@ constructor(
        }

        scope.launch {
            interactor.finishedKeyguardState.collect { logger.i("Finished transition to", it) }
            interactor.finishedKeyguardTransitionStep.collect {
                logger.i("Finished transition", it)
            }
        }

        scope.launch {
            interactor.startedKeyguardState.collect { logger.i("Started transition to", it) }
            interactor.startedKeyguardTransitionStep.collect { logger.i("Started transition", it) }
        }
    }
}
Loading