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

Commit 531f2156 authored by Sherry Zhou's avatar Sherry Zhou Committed by Android (Google) Code Review
Browse files

Merge "Add lockscreen alpha transitions within KTF in Flexiglass" into main

parents db641f91 74040562
Loading
Loading
Loading
Loading
+16 −2
Original line number Diff line number Diff line
@@ -19,7 +19,13 @@ package com.android.systemui.keyguard.ui.composable
import android.view.View
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalView
import com.android.compose.animation.scene.ContentScope
import com.android.internal.jank.Cuj
@@ -33,6 +39,7 @@ import com.android.systemui.keyguard.ui.composable.blueprint.ComposableLockscree
import com.android.systemui.keyguard.ui.viewmodel.LockscreenBehindScrimViewModel
import com.android.systemui.keyguard.ui.viewmodel.LockscreenContentViewModel
import com.android.systemui.keyguard.ui.viewmodel.LockscreenFrontScrimViewModel
import com.android.systemui.keyguard.ui.viewmodel.ViewStateAccessor
import com.android.systemui.lifecycle.rememberViewModel
import com.android.systemui.notifications.ui.composable.NotificationLockscreenScrim
import com.android.systemui.plugins.keyguard.ui.composable.elements.LockscreenElementKeys
@@ -60,13 +67,17 @@ class LockscreenContent(
    @Composable
    fun ContentScope.Content(modifier: Modifier = Modifier) {
        val view = LocalView.current
        var lockscreenAlpha by remember { mutableFloatStateOf(0f) }
        val viewModel =
            rememberViewModel("LockscreenContent-viewModel") {
                viewModelFactory.create(
                    keyguardTransitionAnimationCallback =
                        KeyguardTransitionAnimationCallbackImpl(view, interactionJankMonitor)
                        KeyguardTransitionAnimationCallbackImpl(view, interactionJankMonitor),
                    viewState = ViewStateAccessor(alpha = { lockscreenAlpha }),
                )
            }

        LaunchedEffect(viewModel.alpha) { lockscreenAlpha = viewModel.alpha }
        val notificationLockscreenScrimViewModel =
            rememberViewModel("LockscreenContent-notificationScrimViewModel") {
                notificationScrimViewModelFactory.create()
@@ -96,7 +107,10 @@ class LockscreenContent(
            )
            Content(
                viewModel,
                modifier.sysuiResTag("keyguard_root_view").element(LockscreenElementKeys.Root),
                modifier
                    .sysuiResTag("keyguard_root_view")
                    .element(LockscreenElementKeys.Root)
                    .graphicsLayer { alpha = viewModel.alpha },
            )
            NotificationLockscreenScrim(notificationLockscreenScrimViewModel)
            LockscreenFrontScrim(lockscreenFrontScrimViewModel)
+5 −1
Original line number Diff line number Diff line
@@ -48,6 +48,7 @@ class LockscreenContentViewModelTest(flags: FlagsParameterization) : SysuiTestCa

    private lateinit var underTest: LockscreenContentViewModel
    private val activationJob = Job()
    private val viewState: ViewStateAccessor = ViewStateAccessor({ 0f })

    companion object {
        @JvmStatic
@@ -66,7 +67,10 @@ class LockscreenContentViewModelTest(flags: FlagsParameterization) : SysuiTestCa
        with(kosmos) {
            shadeRepository.setShadeLayoutWide(false)
            underTest =
                lockscreenContentViewModelFactory.create(fakeKeyguardTransitionAnimationCallback)
                lockscreenContentViewModelFactory.create(
                    fakeKeyguardTransitionAnimationCallback,
                    viewState,
                )
            underTest.activateIn(testScope, activationJob)
        }
    }
+139 −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.compose.runtime.getValue
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.lifecycle.HydratedActivatable
import com.android.systemui.minmode.MinModeManager
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.ui.viewmodel.NotificationShadeWindowModel
import com.android.systemui.util.kotlin.BooleanFlowOperators.anyOf
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.util.Optional
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.merge
import kotlinx.coroutines.flow.onStart

class LockscreenAlphaViewModel
@AssistedInject
constructor(
    transitionInteractor: KeyguardTransitionInteractor,
    minModeManager: Optional<MinModeManager>,
    notificationShadeWindowModel: NotificationShadeWindowModel,
    private val alternateBouncerToAodTransitionViewModel: AlternateBouncerToAodTransitionViewModel,
    private val alternateBouncerToGoneTransitionViewModel:
        AlternateBouncerToGoneTransitionViewModel,
    private val alternateBouncerToLockscreenTransitionViewModel:
        AlternateBouncerToLockscreenTransitionViewModel,
    private val alternateBouncerToOccludedTransitionViewModel:
        AlternateBouncerToOccludedTransitionViewModel,
    private val aodToLockscreenTransitionViewModel: AodToLockscreenTransitionViewModel,
    private val aodToOccludedTransitionViewModel: AodToOccludedTransitionViewModel,
    private val dozingToLockscreenTransitionViewModel: DozingToLockscreenTransitionViewModel,
    private val dozingToOccludedTransitionViewModel: DozingToOccludedTransitionViewModel,
    private val lockscreenToAodTransitionViewModel: LockscreenToAodTransitionViewModel,
    private val lockscreenToDozingTransitionViewModel: LockscreenToDozingTransitionViewModel,
    private val lockscreenToOccludedTransitionViewModel: LockscreenToOccludedTransitionViewModel,
    private val occludedToAlternateBouncerTransitionViewModel:
        OccludedToAlternateBouncerTransitionViewModel,
    private val occludedToAodTransitionViewModel: OccludedToAodTransitionViewModel,
    private val occludedToDozingTransitionViewModel: OccludedToDozingTransitionViewModel,
    private val occludedToLockscreenTransitionViewModel: OccludedToLockscreenTransitionViewModel,
    private val offToLockscreenTransitionViewModel: OffToLockscreenTransitionViewModel,
    private val keyguardInteractor: KeyguardInteractor,
    @Assisted private val viewStateAccessor: ViewStateAccessor,
) : HydratedActivatable() {
    /**
     * The `alpha` property depends on this property. To prevent a NullPointerException, ensure
     * `hideKeyguard` is initialized before `alpha`.
     */
    private val hideKeyguard: Flow<Boolean> =
        anyOf(
            if (minModeManager.isPresent) {
                minModeManager.get().isMinModeInForegroundFlow
            } else {
                flowOf(false)
            },
            notificationShadeWindowModel.isKeyguardOccluded,
            transitionInteractor
                .transitionValue(KeyguardState.OFF)
                .map { it > 1f - offToLockscreenTransitionViewModel.alphaStartAt }
                .onStart { emit(false) },
            transitionInteractor
                .transitionValue(
                    content = Scenes.Gone,
                    stateWithoutSceneContainer = KeyguardState.GONE,
                )
                .map { it == 1f }
                .onStart { emit(false) },
        )

    /** Alpha value applied to all LockscreenElements. */
    val alpha: Float by
        alpha(viewState = viewStateAccessor).hydratedStateOf(traceName = "alpha", initialValue = 0f)

    /** An observable for the alpha level for the entire keyguard root view. */
    private fun alpha(viewState: ViewStateAccessor): Flow<Float> {
        return combine(
                hideKeyguard,
                // The transitions are mutually exclusive, so they are safe to merge to get the last
                // value emitted by any of them. Do not add flows that cannot make this guarantee.
                merge(
                        keyguardInteractor.dismissAlpha,
                        alternateBouncerToAodTransitionViewModel.lockscreenAlpha(viewState),
                        alternateBouncerToGoneTransitionViewModel.lockscreenAlpha(viewState),
                        alternateBouncerToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
                        alternateBouncerToOccludedTransitionViewModel.lockscreenAlpha,
                        aodToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
                        aodToOccludedTransitionViewModel.lockscreenAlpha(viewState),
                        dozingToLockscreenTransitionViewModel.lockscreenAlpha(viewState),
                        dozingToOccludedTransitionViewModel.lockscreenAlpha(viewState),
                        lockscreenToAodTransitionViewModel.lockscreenAlpha(viewState),
                        lockscreenToAodTransitionViewModel.lockscreenAlphaOnFold,
                        lockscreenToDozingTransitionViewModel.lockscreenAlpha,
                        lockscreenToOccludedTransitionViewModel.lockscreenAlpha,
                        occludedToAlternateBouncerTransitionViewModel.lockscreenAlpha,
                        occludedToAodTransitionViewModel.lockscreenAlpha,
                        occludedToDozingTransitionViewModel.lockscreenAlpha,
                        occludedToLockscreenTransitionViewModel.lockscreenAlpha,
                        offToLockscreenTransitionViewModel.lockscreenAlpha,
                    )
                    .onStart { emit(0f) },
            ) { hideKeyguard, alpha ->
                if (hideKeyguard) {
                    0f
                } else {
                    alpha
                }
            }
            .distinctUntilChanged()
    }

    @AssistedFactory
    interface Factory {
        fun create(viewStateAccessor: ViewStateAccessor): LockscreenAlphaViewModel
    }
}
+14 −2
Original line number Diff line number Diff line
@@ -45,8 +45,10 @@ constructor(
    deviceEntryUdfpsInteractor: DeviceEntryUdfpsInteractor,
    private val keyguardTransitionAnimationCallbackDelegator:
        KeyguardTransitionAnimationCallbackDelegator,
    @Assisted private val keyguardTransitionAnimationCallback: KeyguardTransitionAnimationCallback,
    private val wallpaperFocalAreaInteractor: WallpaperFocalAreaInteractor,
    private val lockscreenAlphaViewModelFactory: LockscreenAlphaViewModel.Factory,
    @Assisted private val keyguardTransitionAnimationCallback: KeyguardTransitionAnimationCallback,
    @Assisted private val viewStateAccessor: ViewStateAccessor,
) : ExclusiveActivatable() {

    private val hydrator = Hydrator("LockscreenContentViewModel.hydrator")
@@ -80,10 +82,19 @@ constructor(
            initialValue = deviceEntryUdfpsInteractor.isUdfpsSupported.value,
        )

    /** Alpha value applied to all LockscreenElements. */
    val alpha: Float
        get() = lockscreenAlphaViewModel.alpha

    private val lockscreenAlphaViewModel: LockscreenAlphaViewModel by lazy {
        lockscreenAlphaViewModelFactory.create(viewStateAccessor)
    }

    override suspend fun onActivated(): Nothing {
        coroutineScope {
            try {
                launch { hydrator.activate() }
                launch { lockscreenAlphaViewModel.activate() }

                keyguardTransitionAnimationCallbackDelegator.delegate =
                    keyguardTransitionAnimationCallback
@@ -114,7 +125,8 @@ constructor(
    @AssistedFactory
    interface Factory {
        fun create(
            keyguardTransitionAnimationCallback: KeyguardTransitionAnimationCallback
            keyguardTransitionAnimationCallback: KeyguardTransitionAnimationCallback,
            viewState: ViewStateAccessor,
        ): LockscreenContentViewModel
    }
}
+59 −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 com.android.systemui.keyguard.domain.interactor.keyguardInteractor
import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.minModeManager
import com.android.systemui.shade.ui.viewmodel.notificationShadeWindowModel
import java.util.Optional

val Kosmos.lockscreenAlphaViewModelFactory by Fixture {
    object : LockscreenAlphaViewModel.Factory {
        override fun create(viewStateAccessor: ViewStateAccessor): LockscreenAlphaViewModel {
            return LockscreenAlphaViewModel(
                transitionInteractor = keyguardTransitionInteractor,
                alternateBouncerToAodTransitionViewModel = alternateBouncerToAodTransitionViewModel,
                minModeManager = Optional.of(minModeManager),
                notificationShadeWindowModel = notificationShadeWindowModel,
                alternateBouncerToGoneTransitionViewModel =
                    alternateBouncerToGoneTransitionViewModel,
                alternateBouncerToLockscreenTransitionViewModel =
                    alternateBouncerToLockscreenTransitionViewModel,
                alternateBouncerToOccludedTransitionViewModel =
                    alternateBouncerToOccludedTransitionViewModel,
                aodToLockscreenTransitionViewModel = aodToLockscreenTransitionViewModel,
                aodToOccludedTransitionViewModel = aodToOccludedTransitionViewModel,
                dozingToLockscreenTransitionViewModel = dozingToLockscreenTransitionViewModel,
                dozingToOccludedTransitionViewModel = dozingToOccludedTransitionViewModel,
                lockscreenToAodTransitionViewModel = lockscreenToAodTransitionViewModel,
                lockscreenToDozingTransitionViewModel = lockscreenToDozingTransitionViewModel,
                lockscreenToOccludedTransitionViewModel = lockscreenToOccludedTransitionViewModel,
                occludedToAlternateBouncerTransitionViewModel =
                    occludedToAlternateBouncerTransitionViewModel,
                occludedToAodTransitionViewModel = occludedToAodTransitionViewModel,
                occludedToDozingTransitionViewModel = occludedToDozingTransitionViewModel,
                occludedToLockscreenTransitionViewModel = occludedToLockscreenTransitionViewModel,
                offToLockscreenTransitionViewModel = offToLockscreenTransitionViewModel,
                keyguardInteractor = keyguardInteractor,
                viewStateAccessor = viewStateAccessor,
            )
        }
    }
}
Loading