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

Commit 31ade8ba authored by Chandru S's avatar Chandru S Committed by Ale Nijamkin
Browse files

Blur QS scene when bouncer is open over QS

Bug: 388068805
Test: unit tests
Test: verified manually
Flag: com.android.systemui.scene_container
Change-Id: I3b3879236ed295213abd9930413e1fb3bb9e23cd
parent fa1ff893
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -40,12 +40,14 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalConfiguration
@@ -194,7 +196,13 @@ private fun ContentScope.QuickSettingsScene(
    shadeSession: SaveableSession,
    jankMonitor: InteractionJankMonitor,
) {
    Box(modifier.fillMaxSize()) {
    val targetBlur by
        remember(layoutState) {
            derivedStateOf { viewModel.calculateBlur(layoutState.transitionState) }
        }
    val animatedBlurRadiusPx: Float by
        animateFloatAsState(targetValue = targetBlur, label = "QS-blurRadius")
    Box(modifier.blur(with(LocalDensity.current) { animatedBlurRadiusPx.toDp() }).fillMaxSize()) {
        // This is the background for the whole scene, as the elements don't necessarily provide
        // a background that extends to the edges.
        ShadePanelScrim(viewModel.isTransparencyEnabled)
+51 −0
Original line number Diff line number Diff line
@@ -20,9 +20,12 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.lifecycle.LifecycleOwner
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.EnableSceneContainer
import com.android.systemui.keyguard.ui.transitions.blurConfig
import com.android.systemui.kosmos.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
@@ -45,6 +48,7 @@ import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.android.systemui.window.data.repository.fakeWindowRootViewBlurRepository
import com.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.launch
@@ -84,6 +88,7 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
                    sceneInteractor = sceneInteractor,
                    mainDispatcher = testDispatcher,
                    windowRootViewBlurInteractor = windowRootViewBlurInteractor,
                    blurConfig = blurConfig,
                )
            underTest.activateIn(testScope)
            testScope.backgroundScope.launch { underTest.detectShadeModeChanges() }
@@ -113,6 +118,52 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
            assertThat(scene).isEqualTo(Scenes.Shade)
        }

    @Test
    fun isBlurred_whenBouncerOverlayShowingOverQuickSettingsAndBlurSupported_isTrue() =
        kosmos.runTest {
            assertThat(
                    underTest.calculateBlur(
                        transitionState =
                            TransitionState.Idle(
                                currentScene = Scenes.Lockscreen,
                                currentOverlays = setOf(Overlays.Bouncer),
                            )
                    )
                )
                .isEqualTo(0f)

            kosmos.fakeWindowRootViewBlurRepository.isBlurSupported.value = true
            runCurrent()
            assertThat(
                    underTest.calculateBlur(
                        transitionState =
                            TransitionState.Idle(
                                currentScene = Scenes.Lockscreen,
                                currentOverlays = setOf(Overlays.Bouncer),
                            )
                    )
                )
                .isEqualTo(0f)

            assertThat(
                    underTest.calculateBlur(
                        transitionState =
                            TransitionState.Idle(
                                currentScene = Scenes.QuickSettings,
                                currentOverlays = setOf(Overlays.Bouncer),
                            )
                    )
                )
                .isEqualTo(blurConfig.maxBlurRadiusPx)

            assertThat(
                    underTest.calculateBlur(
                        transitionState = TransitionState.Idle(currentScene = Scenes.QuickSettings)
                    )
                )
                .isEqualTo(0)
        }

    @Test
    fun shadeModeChange_dual_switchToOverlay() =
        kosmos.runTest {
+18 −0
Original line number Diff line number Diff line
@@ -19,8 +19,10 @@ package com.android.systemui.qs.ui.viewmodel
import androidx.compose.runtime.getValue
import androidx.lifecycle.LifecycleOwner
import com.android.app.tracing.coroutines.launchTraced as launch
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.systemui.Flags
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.keyguard.ui.transitions.BlurConfig
import com.android.systemui.lifecycle.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.qs.FooterActionsController
@@ -59,6 +61,7 @@ constructor(
    private val sceneInteractor: SceneInteractor,
    @Main private val mainDispatcher: CoroutineDispatcher,
    windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
    private val blurConfig: BlurConfig,
) : ExclusiveActivatable() {
    val qsContainerViewModel =
        qsContainerViewModelFactory.create(supportsBrightnessMirroring = true)
@@ -82,6 +85,21 @@ constructor(

    private val footerActionsControllerInitialized = AtomicBoolean(false)

    /**
     * Calculates the blur radius to apply to the scene UI.
     *
     * @param transitionState The current transition state of the scene (from its `ContentScope`)
     * @return The blur radius to apply to the scene UI, in pixels.
     */
    fun calculateBlur(transitionState: TransitionState): Float {
        return when {
            !isTransparencyEnabled -> 0f
            Scenes.QuickSettings != transitionState.currentScene -> 0f
            Overlays.Bouncer in transitionState.currentOverlays -> blurConfig.maxBlurRadiusPx
            else -> 0f
        }
    }

    fun getFooterActionsViewModel(lifecycleOwner: LifecycleOwner): FooterActionsViewModel {
        if (footerActionsControllerInitialized.compareAndSet(false, true)) {
            footerActionsController.init()
+2 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.systemui.qs.ui.viewmodel

import com.android.systemui.keyguard.ui.transitions.blurConfig
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testDispatcher
@@ -36,6 +37,7 @@ val Kosmos.quickSettingsSceneContentViewModel by Fixture {
        sceneInteractor = sceneInteractor,
        mainDispatcher = testDispatcher,
        windowRootViewBlurInteractor = windowRootViewBlurInteractor,
        blurConfig = blurConfig,
    )
}