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

Commit 7dee55af authored by Matt Pietal's avatar Matt Pietal
Browse files

Transitions - Add doze transition information

Add a new DozeMachine.Part in order to emit granular doze state to the
KeyguardRepository. Use that new information to make better decisions
about when to transition state to/from dreaming.

Upcoming: Support for pulsing and dozing (non-AOD) states

Bug: 195430376
Test: atest KeyguardRepositoryImplTest
Change-Id: If759ba0d286eca907af615b9e2e56cadef224f4d
parent eed2d8f0
Loading
Loading
Loading
Loading
+48 −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.doze

import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.statusbar.policy.CallbackController
import javax.inject.Inject

/** Receives doze transition events, and passes those events to registered callbacks. */
@SysUISingleton
class DozeTransitionListener @Inject constructor() :
    DozeMachine.Part, CallbackController<DozeTransitionCallback> {
    val callbacks = mutableSetOf<DozeTransitionCallback>()
    var oldState = DozeMachine.State.UNINITIALIZED
    var newState = DozeMachine.State.UNINITIALIZED

    override fun transitionTo(oldState: DozeMachine.State, newState: DozeMachine.State) {
        this.oldState = oldState
        this.newState = newState
        callbacks.forEach { it.onDozeTransition(oldState, newState) }
    }

    override fun addCallback(callback: DozeTransitionCallback) {
        callbacks.add(callback)
    }

    override fun removeCallback(callback: DozeTransitionCallback) {
        callbacks.remove(callback)
    }
}

interface DozeTransitionCallback {
    fun onDozeTransition(oldState: DozeMachine.State, newState: DozeMachine.State)
}
+4 −2
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import com.android.systemui.doze.DozeScreenStatePreventingAdapter;
import com.android.systemui.doze.DozeSensors;
import com.android.systemui.doze.DozeSuppressor;
import com.android.systemui.doze.DozeSuspendScreenStatePreventingAdapter;
import com.android.systemui.doze.DozeTransitionListener;
import com.android.systemui.doze.DozeTriggers;
import com.android.systemui.doze.DozeUi;
import com.android.systemui.doze.DozeWallpaperState;
@@ -83,7 +84,7 @@ public abstract class DozeModule {
            DozeUi dozeUi, DozeScreenState dozeScreenState,
            DozeScreenBrightness dozeScreenBrightness, DozeWallpaperState dozeWallpaperState,
            DozeDockHandler dozeDockHandler, DozeAuthRemover dozeAuthRemover,
            DozeSuppressor dozeSuppressor) {
            DozeSuppressor dozeSuppressor, DozeTransitionListener dozeTransitionListener) {
        return new DozeMachine.Part[]{
                dozePauser,
                dozeFalsingManagerAdapter,
@@ -94,7 +95,8 @@ public abstract class DozeModule {
                dozeWallpaperState,
                dozeDockHandler,
                dozeAuthRemover,
                dozeSuppressor
                dozeSuppressor,
                dozeTransitionListener
        };
    }

+59 −0
Original line number Diff line number Diff line
@@ -23,9 +23,14 @@ import com.android.systemui.common.coroutine.ConflatedCallbackFlow.conflatedCall
import com.android.systemui.common.shared.model.Position
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.doze.DozeHost
import com.android.systemui.doze.DozeMachine
import com.android.systemui.doze.DozeTransitionCallback
import com.android.systemui.doze.DozeTransitionListener
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.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.keyguard.shared.model.WakefulnessModel
import com.android.systemui.plugins.statusbar.StatusBarStateController
@@ -108,6 +113,9 @@ interface KeyguardRepository {
     */
    val dozeAmount: Flow<Float>

    /** Doze state information, as it transitions */
    val dozeTransitionModel: Flow<DozeTransitionModel>

    /** Observable for the [StatusBarState] */
    val statusBarState: Flow<StatusBarState>

@@ -154,6 +162,7 @@ constructor(
    biometricUnlockController: BiometricUnlockController,
    private val keyguardStateController: KeyguardStateController,
    private val keyguardUpdateMonitor: KeyguardUpdateMonitor,
    private val dozeTransitionListener: DozeTransitionListener,
) : KeyguardRepository {
    private val _animateBottomAreaDozingTransitions = MutableStateFlow(false)
    override val animateBottomAreaDozingTransitions =
@@ -286,6 +295,37 @@ constructor(
        awaitClose { statusBarStateController.removeCallback(callback) }
    }

    override val dozeTransitionModel: Flow<DozeTransitionModel> = conflatedCallbackFlow {
        val callback =
            object : DozeTransitionCallback {
                override fun onDozeTransition(
                    oldState: DozeMachine.State,
                    newState: DozeMachine.State
                ) {
                    trySendWithFailureLogging(
                        DozeTransitionModel(
                            from = dozeMachineStateToModel(oldState),
                            to = dozeMachineStateToModel(newState),
                        ),
                        TAG,
                        "doze transition model"
                    )
                }
            }

        dozeTransitionListener.addCallback(callback)
        trySendWithFailureLogging(
            DozeTransitionModel(
                from = dozeMachineStateToModel(dozeTransitionListener.oldState),
                to = dozeMachineStateToModel(dozeTransitionListener.newState),
            ),
            TAG,
            "initial doze transition model"
        )

        awaitClose { dozeTransitionListener.removeCallback(callback) }
    }

    override fun isKeyguardShowing(): Boolean {
        return keyguardStateController.isShowing
    }
@@ -407,6 +447,25 @@ constructor(
        }
    }

    private fun dozeMachineStateToModel(state: DozeMachine.State): DozeStateModel {
        return when (state) {
            DozeMachine.State.UNINITIALIZED -> DozeStateModel.UNINITIALIZED
            DozeMachine.State.INITIALIZED -> DozeStateModel.INITIALIZED
            DozeMachine.State.DOZE -> DozeStateModel.DOZE
            DozeMachine.State.DOZE_SUSPEND_TRIGGERS -> DozeStateModel.DOZE_SUSPEND_TRIGGERS
            DozeMachine.State.DOZE_AOD -> DozeStateModel.DOZE_AOD
            DozeMachine.State.DOZE_REQUEST_PULSE -> DozeStateModel.DOZE_REQUEST_PULSE
            DozeMachine.State.DOZE_PULSING -> DozeStateModel.DOZE_PULSING
            DozeMachine.State.DOZE_PULSING_BRIGHT -> DozeStateModel.DOZE_PULSING_BRIGHT
            DozeMachine.State.DOZE_PULSE_DONE -> DozeStateModel.DOZE_PULSE_DONE
            DozeMachine.State.FINISH -> DozeStateModel.FINISH
            DozeMachine.State.DOZE_AOD_PAUSED -> DozeStateModel.DOZE_AOD_PAUSED
            DozeMachine.State.DOZE_AOD_PAUSING -> DozeStateModel.DOZE_AOD_PAUSING
            DozeMachine.State.DOZE_AOD_DOCKED -> DozeStateModel.DOZE_AOD_DOCKED
            else -> throw IllegalArgumentException("Invalid DozeMachine.State: state")
        }
    }

    companion object {
        private const val TAG = "KeyguardRepositoryImpl"
    }
+27 −19
Original line number Diff line number Diff line
@@ -21,10 +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.DozeStateModel
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.keyguard.shared.model.WakefulnessModel.Companion.isWakingOrStartingToWake
import com.android.systemui.util.kotlin.sample
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -39,27 +38,24 @@ constructor(
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionRepository: KeyguardTransitionRepository,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor("AOD<->LOCKSCREEN") {
) : TransitionInteractor(AodLockscreenTransitionInteractor::class.simpleName!!) {

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

    private fun listenForTransitionToAodFromLockscreen() {
        scope.launch {
            /*
             * Listening to the startedKeyguardTransitionStep (last started step) allows this code
             * to interrupt an active transition, as long as they were either going to LOCKSCREEN or
             * AOD state. One example is when the user presses the power button in the middle of an
             * active transition.
             */
            keyguardInteractor.wakefulnessState
            keyguardInteractor
                .dozeTransitionTo(DozeStateModel.DOZE_AOD)
                .sample(
                    keyguardTransitionInteractor.startedKeyguardTransitionStep,
                    { a, b -> Pair(a, b) }
                )
                .collect { pair ->
                    val (wakefulnessState, lastStartedStep) = pair
                    if (
                        isSleepingOrStartingToSleep(wakefulnessState) &&
                            lastStartedStep.to == KeyguardState.LOCKSCREEN
                    ) {
                    val (dozeToAod, lastStartedStep) = pair
                    if (lastStartedStep.to == KeyguardState.LOCKSCREEN) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
@@ -68,10 +64,22 @@ constructor(
                                getAnimator(),
                            )
                        )
                    } else if (
                        isWakingOrStartingToWake(wakefulnessState) &&
                            lastStartedStep.to == KeyguardState.AOD
                    ) {
                    }
                }
        }
    }

    private fun listenForTransitionToLockscreenFromAod() {
        scope.launch {
            keyguardInteractor
                .dozeTransitionTo(DozeStateModel.FINISH)
                .sample(
                    keyguardTransitionInteractor.startedKeyguardTransitionStep,
                    { a, b -> Pair(a, b) }
                )
                .collect { pair ->
                    val (dozeToAod, lastStartedStep) = pair
                    if (lastStartedStep.to == KeyguardState.AOD) {
                        keyguardTransitionRepository.startTransition(
                            TransitionInfo(
                                name,
+1 −1
Original line number Diff line number Diff line
@@ -40,7 +40,7 @@ constructor(
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionRepository: KeyguardTransitionRepository,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
) : TransitionInteractor("AOD->GONE") {
) : TransitionInteractor(AodToGoneTransitionInteractor::class.simpleName!!) {

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