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

Commit 54cfb429 authored by Beverly Tai's avatar Beverly Tai Committed by Android (Google) Code Review
Browse files

Merge "Update lockscreenAlpha depending on DozeTransitionFlows" into main

parents 00bf08c1 605f3ba7
Loading
Loading
Loading
Loading
+178 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2025 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.ui.viewmodel

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.flags.DisableSceneContainer
import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionState.RUNNING
import com.android.systemui.keyguard.shared.model.TransitionState.STARTED
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.kosmos.testScope
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Test
import org.junit.runner.RunWith

@DisableSceneContainer
@SmallTest
@RunWith(AndroidJUnit4::class)
class DozingTransitionFlowsTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val testScope = kosmos.testScope
    private val underTest by lazy { kosmos.dozingTransitionFlows }

    @Test
    fun lockscreenAlpha_dozing_dozePulsing() =
        testScope.runTest {
            val lockscreenAlpha by collectLastValue(underTest.lockscreenAlpha)
            // Last startedKeyguardTransitionStep is to DOZING
            kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(
                lockscreenToDozingStep(0f, STARTED)
            )
            runCurrent()
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE_PULSING)
            )
            runCurrent()
            assertThat(lockscreenAlpha).isEqualTo(1f)
        }

    @Test
    fun lockscreenAlpha_dozing_dozePulsingAuthUI() =
        testScope.runTest {
            val lockscreenAlpha by collectLastValue(underTest.lockscreenAlpha)
            // Last startedKeyguardTransitionStep is to DOZING
            kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(
                lockscreenToDozingStep(0f, STARTED)
            )
            runCurrent()
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE_PULSING_AUTH_UI)
            )
            runCurrent()
            assertThat(lockscreenAlpha).isEqualTo(1f)
        }

    @Test
    fun lockscreenAlpha_keyguardStateDozing_dozeTransitionModelDoze() =
        testScope.runTest {
            val lockscreenAlpha by collectLastValue(underTest.lockscreenAlpha)
            // Last startedKeyguardTransitionStep is to DOZING
            kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(
                lockscreenToDozingStep(0f, STARTED)
            )
            runCurrent()
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE)
            )
            runCurrent()
            assertThat(lockscreenAlpha).isEqualTo(0f)
        }

    @Test
    fun lockscreenAlpha_keyguardStateDozing_dozeTransitionModelDozePulsingWithoutUI() =
        testScope.runTest {
            val lockscreenAlpha by collectLastValue(underTest.lockscreenAlpha)
            // Last startedKeyguardTransitionStep is to DOZING
            kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(
                lockscreenToDozingStep(0f, STARTED)
            )
            runCurrent()
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE_PULSING_WITHOUT_UI)
            )
            runCurrent()
            assertThat(lockscreenAlpha).isEqualTo(0f)
        }

    @Test
    fun lockscreenAlpha_keyguardStateDozing_dozeTransitionModelUnhandledStates() =
        testScope.runTest {
            val lockscreenAlpha by collectLastValue(underTest.lockscreenAlpha)
            // Last startedKeyguardTransitionStep is to DOZING
            kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(
                lockscreenToDozingStep(0f, STARTED)
            )
            runCurrent()
            val unhandledStates =
                listOf(
                    DozeStateModel.DOZE_AOD_PAUSED,
                    DozeStateModel.DOZE_AOD_PAUSING,
                    DozeStateModel.UNINITIALIZED,
                    DozeStateModel.INITIALIZED,
                    DozeStateModel.FINISH,
                    DozeStateModel.DOZE_PULSE_DONE,
                )
            for (unhandledState in unhandledStates) {
                kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                    DozeTransitionModel(to = unhandledState)
                )
                runCurrent()
                assertThat(lockscreenAlpha).isNull()
            }
        }

    @Test
    fun lockscreenAlpha_notKeyguardStateDozing_nothingEmits() =
        testScope.runTest {
            val lockscreenAlpha by collectLastValue(underTest.lockscreenAlpha)
            // Last startedKeyguardTransitionStep is to AOD (not DOZING)
            kosmos.fakeKeyguardTransitionRepository.sendTransitionStep(
                lockscreenToAodStep(0f, STARTED)
            )
            runCurrent()
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE_PULSING)
            )
            runCurrent()
            assertThat(lockscreenAlpha).isNull()
            kosmos.fakeKeyguardRepository.setDozeTransitionModel(
                DozeTransitionModel(to = DozeStateModel.DOZE_PULSING_BRIGHT)
            )
            runCurrent()
            assertThat(lockscreenAlpha).isNull()
        }

    private fun lockscreenToDozingStep(value: Float, transitionState: TransitionState = RUNNING) =
        TransitionStep(
            from = KeyguardState.LOCKSCREEN,
            to = KeyguardState.DOZING,
            value = value,
            transitionState = transitionState,
            ownerName = "dozingViewModelTest",
        )

    private fun lockscreenToAodStep(value: Float, transitionState: TransitionState = RUNNING) =
        TransitionStep(
            from = KeyguardState.LOCKSCREEN,
            to = KeyguardState.AOD,
            value = value,
            transitionState = transitionState,
            ownerName = "dozingViewModelTest",
        )
}
+1 −1
Original line number Diff line number Diff line
@@ -203,7 +203,7 @@ public class DozeServiceHostTest extends SysuiTestCase {
                        DozeLog.REASON_SENSOR_DOUBLE_TAP,
                        DozeLog.REASON_SENSOR_TAP,
                        DozeLog.REASON_SENSOR_UDFPS_LONG_PRESS,
                        DozeLog.REASON_USUDFPS_PULSE));
                        DozeLog.PULSE_REASON_FINGERPRINT_PULSE));

        doAnswer(invocation -> {
            DozeHost.PulseCallback callback = invocation.getArgument(0);
+17 −3
Original line number Diff line number Diff line
@@ -15,6 +15,7 @@
 */
package com.android.keyguard

import android.R
import android.app.NotificationManager.zenModeFromInterruptionFilter
import android.content.BroadcastReceiver
import android.content.Context
@@ -43,13 +44,13 @@ import com.android.systemui.dagger.qualifiers.DisplaySpecific
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.flags.FeatureFlagsClassic
import com.android.systemui.flags.Flags.REGION_SAMPLING
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState.AOD
import com.android.systemui.keyguard.shared.model.KeyguardState.DOZING
import com.android.systemui.keyguard.shared.model.KeyguardState.LOCKSCREEN
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.ui.viewmodel.DozingToLockscreenTransitionViewModel
import com.android.systemui.lifecycle.repeatWhenAttached
import com.android.systemui.log.core.Logger
import com.android.systemui.plugins.clocks.AlarmData
@@ -75,6 +76,7 @@ import com.android.systemui.statusbar.policy.ZenModeController
import com.android.systemui.statusbar.policy.domain.interactor.ZenModeInteractor
import com.android.systemui.util.annotations.DeprecatedSysuiVisibleForTesting
import com.android.systemui.util.concurrency.DelayableExecutor
import dagger.Lazy
import java.util.Locale
import java.util.TimeZone
import java.util.concurrent.Executor
@@ -94,7 +96,6 @@ import kotlinx.coroutines.flow.merge
open class ClockEventController
@Inject
constructor(
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardTransitionInteractor: KeyguardTransitionInteractor,
    private val broadcastDispatcher: BroadcastDispatcher,
    private val batteryController: BatteryController,
@@ -110,6 +111,7 @@ constructor(
    private val zenModeController: ZenModeController,
    private val zenModeInteractor: ZenModeInteractor,
    private val userTracker: UserTracker,
    private val dozingToLockscreenViewModel: Lazy<DozingToLockscreenTransitionViewModel>,
) {
    var loggers =
        listOf(
@@ -257,7 +259,7 @@ constructor(

    private fun isDarkTheme(): Boolean {
        val isLightTheme = TypedValue()
        context.theme.resolveAttribute(android.R.attr.isLightTheme, isLightTheme, true)
        context.theme.resolveAttribute(R.attr.isLightTheme, isLightTheme, true)
        return isLightTheme.data == 0
    }

@@ -478,6 +480,9 @@ constructor(
                    listenForAnyStateToAodTransition(this)
                    listenForAnyStateToLockscreenTransition(this)
                    listenForAnyStateToDozingTransition(this)
                    if (com.android.systemui.Flags.newDozingKeyguardStates()) {
                        listenForDozingToLockscreen(this)
                    }
                }
            }
        smallTimeListener?.update(shouldTimeListenerRun)
@@ -624,10 +629,19 @@ constructor(
                .transition(Edge.create(to = LOCKSCREEN))
                .filter { it.transitionState == TransitionState.STARTED }
                .filter { it.from != AOD }
                .filter {
                    !com.android.systemui.Flags.newDozingKeyguardStates() || it.from != DOZING
                }
                .collect { handleDoze(0f) }
        }
    }

    private fun listenForDozingToLockscreen(scope: CoroutineScope): Job {
        return scope.launch {
            dozingToLockscreenViewModel.get().clockDozeAmount.collect { handleDoze(it) }
        }
    }

    /**
     * When keyguard is displayed due to pulsing notifications when AOD is off, we should make sure
     * clock is in dozing state instead of LS state
+8 −2
Original line number Diff line number Diff line
@@ -73,8 +73,14 @@ constructor(
     * Whether the fingerprint sensor is present under the display as opposed to being on the power
     * button or behind/rear of the phone.
     */
    val isSensorUnderDisplay =
        fingerprintPropertyRepository.sensorType.map(FingerprintSensorType::isUdfps)
    val isSensorUnderDisplay: StateFlow<Boolean> =
        fingerprintPropertyRepository.sensorType
            .map(FingerprintSensorType::isUdfps)
            .stateIn(
                scope = applicationScope,
                started = SharingStarted.Eagerly,
                initialValue = fingerprintPropertyRepository.sensorType.value.isUdfps(),
            )

    /** True if it is ultrasonic udfps sensor, otherwise false. */
    val isUltrasonic: StateFlow<Boolean> =
+5 −0
Original line number Diff line number Diff line
@@ -147,6 +147,11 @@ public interface DozeHost {
         * Called when ultrasonic fingerprint auth events want the screen on to show info.
         */
        default void onUltrasonicUdfpsPulseWhileScreenOff(FingerprintAuthenticationStatus state) {}

        /**
         * Called when fingerprint auth events want the screen on to show info.
         */
        default void onFingerprintPulseWhileScreenOff(FingerprintAuthenticationStatus state) {}
    }

    interface PulseCallback {
Loading