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

Commit 2a314ee8 authored by Matt Pietal's avatar Matt Pietal
Browse files

Transitions - Add dozing information

Dozing is separate state, apart from AOD, where low power sensors are
enabled but the screen is not active. Begin accounting for this state
during transitions.

Also, use the class name for logging.

Also, recover dreaming state after a crash.

Test: atest KeyguardRepositoryImplTest
KeyguardTransitionRepositoryTest
Bug: 195430376
Fixes: 259782960

Change-Id: Id887c886c4a1df4d4c466b5ea9f4c4507bfcd50e
parent 73c69416
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -116,6 +116,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
                KeyguardState.LOCKSCREEN,
                0f,
                TransitionState.STARTED,
                KeyguardTransitionRepositoryImpl::class.simpleName!!,
            )
        )
        emitTransition(
@@ -124,6 +125,7 @@ class KeyguardTransitionRepositoryImpl @Inject constructor() : KeyguardTransitio
                KeyguardState.LOCKSCREEN,
                1f,
                TransitionState.FINISHED,
                KeyguardTransitionRepositoryImpl::class.simpleName!!,
            )
        )
    }
+7 −12
Original line number Diff line number Diff line
@@ -41,17 +41,14 @@ constructor(

    override fun start() {
        listenForTransitionToAodFromLockscreen()
        listenForTransitionToLockscreenFromAod()
        listenForTransitionToLockscreenFromDozeStates()
    }

    private fun listenForTransitionToAodFromLockscreen() {
        scope.launch {
            keyguardInteractor
                .dozeTransitionTo(DozeStateModel.DOZE_AOD)
                .sample(
                    keyguardTransitionInteractor.startedKeyguardTransitionStep,
                    { a, b -> Pair(a, b) }
                )
                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
                .collect { pair ->
                    val (dozeToAod, lastStartedStep) = pair
                    if (lastStartedStep.to == KeyguardState.LOCKSCREEN) {
@@ -68,21 +65,19 @@ constructor(
        }
    }

    private fun listenForTransitionToLockscreenFromAod() {
    private fun listenForTransitionToLockscreenFromDozeStates() {
        val canGoToLockscreen = setOf(KeyguardState.AOD, KeyguardState.DOZING)
        scope.launch {
            keyguardInteractor
                .dozeTransitionTo(DozeStateModel.FINISH)
                .sample(
                    keyguardTransitionInteractor.startedKeyguardTransitionStep,
                    { a, b -> Pair(a, b) }
                )
                .sample(keyguardTransitionInteractor.startedKeyguardTransitionStep, ::Pair)
                .collect { pair ->
                    val (dozeToAod, lastStartedStep) = pair
                    if (lastStartedStep.to == KeyguardState.AOD) {
                    if (canGoToLockscreen.contains(lastStartedStep.to)) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
                                KeyguardState.AOD,
                                lastStartedStep.to,
                                KeyguardState.LOCKSCREEN,
                                getAnimator(),
                            )
+2 −8
Original line number Diff line number Diff line
@@ -21,9 +21,7 @@ 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.BiometricUnlockModel.Companion.isWakeAndUnlock
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.sample
@@ -42,9 +40,6 @@ constructor(
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor(AodToGoneTransitionInteractor::class.simpleName!!) {

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

    override fun start() {
        scope.launch {
            keyguardInteractor.biometricUnlockState
@@ -52,8 +47,7 @@ constructor(
                .collect { pair ->
                    val (biometricUnlockState, keyguardState) = pair
                    if (
                        keyguardState == KeyguardState.AOD &&
                            wakeAndUnlockModes.contains(biometricUnlockState)
                        keyguardState == KeyguardState.AOD && isWakeAndUnlock(biometricUnlockState)
                    ) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
+0 −76
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.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.keyguard.shared.model.WakefulnessModel.Companion.isSleepingOrStartingToSleep
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 DreamingToAodTransitionInteractor
@Inject
constructor(
    @Application private val scope: CoroutineScope,
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionRepository: KeyguardTransitionRepository,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor("DREAMING->AOD") {

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

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

    companion object {
        private const val TRANSITION_DURATION_MS = 300L
    }
}
+180 −0
Original line number Diff line number Diff line
@@ -21,7 +21,9 @@ 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.Companion.isWakeAndUnlock
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeStateModel.Companion.isDozeOff
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionInfo
import com.android.systemui.util.kotlin.sample
@@ -32,41 +34,77 @@ import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.launch

@SysUISingleton
class DreamingLockscreenTransitionInteractor
class DreamingTransitionInteractor
@Inject
constructor(
    @Application private val scope: CoroutineScope,
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionRepository: KeyguardTransitionRepository,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor(DreamingLockscreenTransitionInteractor::class.simpleName!!) {
) : TransitionInteractor(DreamingTransitionInteractor::class.simpleName!!) {

    private val canDreamFrom =
        setOf(KeyguardState.LOCKSCREEN, KeyguardState.GONE, KeyguardState.DOZING)

    override fun start() {
        listenForEntryToDreaming()
        listenForDreamingToLockscreen()
        listenForDreamingToGone()
        listenForDreamingToDozing()
    }

    private fun listenForEntryToDreaming() {
        scope.launch {
            keyguardInteractor.isDreaming
                .sample(
                    combine(
                        keyguardInteractor.dozeTransitionModel,
                        keyguardTransitionInteractor.finishedKeyguardState
                    ) { a, b -> Pair(a, b) },
                    { a, bc -> Triple(a, bc.first, bc.second) }
                        keyguardTransitionInteractor.finishedKeyguardState,
                        ::Pair
                    ),
                    ::toTriple
                )
                .collect { triple ->
                    val (isDreaming, dozeTransitionModel, keyguardState) = triple
                    // Dozing/AOD and dreaming have overlapping events. If the state remains in
                    // FINISH, it means that doze mode is not running and DREAMING is ok to
                    // commence.
                    if (dozeTransitionModel.to == DozeStateModel.FINISH) {
                        if (isDreaming && keyguardState == KeyguardState.LOCKSCREEN) {
                    if (
                        isDozeOff(dozeTransitionModel.to) &&
                            isDreaming &&
                            canDreamFrom.contains(keyguardState)
                    ) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
                                    KeyguardState.LOCKSCREEN,
                                keyguardState,
                                KeyguardState.DREAMING,
                                getAnimator(),
                            )
                        )
                        } else if (!isDreaming && keyguardState == KeyguardState.DREAMING) {
                    }
                }
        }
    }

    private fun listenForDreamingToLockscreen() {
        scope.launch {
            keyguardInteractor.isDreaming
                .sample(
                    combine(
                        keyguardInteractor.dozeTransitionModel,
                        keyguardTransitionInteractor.startedKeyguardTransitionStep,
                        ::Pair,
                    ),
                    ::toTriple
                )
                .collect { triple ->
                    val (isDreaming, dozeTransitionModel, lastStartedTransition) = triple
                    if (
                        isDozeOff(dozeTransitionModel.to) &&
                            !isDreaming &&
                            lastStartedTransition.to == KeyguardState.DREAMING
                    ) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
@@ -79,6 +117,54 @@ constructor(
                }
        }
    }

    private fun listenForDreamingToGone() {
        scope.launch {
            keyguardInteractor.biometricUnlockState
                .sample(keyguardTransitionInteractor.finishedKeyguardState, ::Pair)
                .collect { pair ->
                    val (biometricUnlockState, keyguardState) = pair
                    if (
                        keyguardState == KeyguardState.DREAMING &&
                            isWakeAndUnlock(biometricUnlockState)
                    ) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
                                KeyguardState.DREAMING,
                                KeyguardState.GONE,
                                getAnimator(),
                            )
                        )
                    }
                }
        }
    }

    private fun listenForDreamingToDozing() {
        scope.launch {
            combine(
                    keyguardInteractor.dozeTransitionModel,
                    keyguardTransitionInteractor.finishedKeyguardState,
                    ::Pair
                )
                .collect { pair ->
                    val (dozeTransitionModel, keyguardState) = pair
                    if (
                        dozeTransitionModel.to == DozeStateModel.DOZE &&
                            keyguardState == KeyguardState.DREAMING
                    ) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
                                KeyguardState.DREAMING,
                                KeyguardState.DOZING,
                                getAnimator(),
                            )
                        )
                    }
                }
        }
    }

    private fun getAnimator(): ValueAnimator {
Loading