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 Original line Diff line number Diff line
@@ -40,12 +40,14 @@ import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.getValue
import androidx.compose.runtime.remember
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.snapshotFlow
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.CompositingStrategy
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.platform.LocalConfiguration
import androidx.compose.ui.platform.LocalConfiguration
@@ -194,7 +196,13 @@ private fun ContentScope.QuickSettingsScene(
    shadeSession: SaveableSession,
    shadeSession: SaveableSession,
    jankMonitor: InteractionJankMonitor,
    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
        // This is the background for the whole scene, as the elements don't necessarily provide
        // a background that extends to the edges.
        // a background that extends to the edges.
        ShadePanelScrim(viewModel.isTransparencyEnabled)
        ShadePanelScrim(viewModel.isTransparencyEnabled)
+51 −0
Original line number Original line Diff line number Diff line
@@ -20,9 +20,12 @@ import android.testing.TestableLooper.RunWithLooper
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleOwner
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import androidx.test.filters.SmallTest
import com.android.compose.animation.scene.content.state.TransitionState
import com.android.systemui.SysuiTestCase
import com.android.systemui.SysuiTestCase
import com.android.systemui.flags.EnableSceneContainer
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.collectLastValue
import com.android.systemui.kosmos.runCurrent
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.runTest
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testScope
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.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
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.android.systemui.window.domain.interactor.windowRootViewBlurInteractor
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.launch
import kotlinx.coroutines.launch
@@ -84,6 +88,7 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
                    sceneInteractor = sceneInteractor,
                    sceneInteractor = sceneInteractor,
                    mainDispatcher = testDispatcher,
                    mainDispatcher = testDispatcher,
                    windowRootViewBlurInteractor = windowRootViewBlurInteractor,
                    windowRootViewBlurInteractor = windowRootViewBlurInteractor,
                    blurConfig = blurConfig,
                )
                )
            underTest.activateIn(testScope)
            underTest.activateIn(testScope)
            testScope.backgroundScope.launch { underTest.detectShadeModeChanges() }
            testScope.backgroundScope.launch { underTest.detectShadeModeChanges() }
@@ -113,6 +118,52 @@ class QuickSettingsSceneContentViewModelTest : SysuiTestCase() {
            assertThat(scene).isEqualTo(Scenes.Shade)
            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
    @Test
    fun shadeModeChange_dual_switchToOverlay() =
    fun shadeModeChange_dual_switchToOverlay() =
        kosmos.runTest {
        kosmos.runTest {
+18 −0
Original line number Original line Diff line number Diff line
@@ -19,8 +19,10 @@ package com.android.systemui.qs.ui.viewmodel
import androidx.compose.runtime.getValue
import androidx.compose.runtime.getValue
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.LifecycleOwner
import com.android.app.tracing.coroutines.launchTraced as launch
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.Flags
import com.android.systemui.dagger.qualifiers.Main
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.ExclusiveActivatable
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.lifecycle.Hydrator
import com.android.systemui.qs.FooterActionsController
import com.android.systemui.qs.FooterActionsController
@@ -59,6 +61,7 @@ constructor(
    private val sceneInteractor: SceneInteractor,
    private val sceneInteractor: SceneInteractor,
    @Main private val mainDispatcher: CoroutineDispatcher,
    @Main private val mainDispatcher: CoroutineDispatcher,
    windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
    windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
    private val blurConfig: BlurConfig,
) : ExclusiveActivatable() {
) : ExclusiveActivatable() {
    val qsContainerViewModel =
    val qsContainerViewModel =
        qsContainerViewModelFactory.create(supportsBrightnessMirroring = true)
        qsContainerViewModelFactory.create(supportsBrightnessMirroring = true)
@@ -82,6 +85,21 @@ constructor(


    private val footerActionsControllerInitialized = AtomicBoolean(false)
    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 {
    fun getFooterActionsViewModel(lifecycleOwner: LifecycleOwner): FooterActionsViewModel {
        if (footerActionsControllerInitialized.compareAndSet(false, true)) {
        if (footerActionsControllerInitialized.compareAndSet(false, true)) {
            footerActionsController.init()
            footerActionsController.init()
+2 −0
Original line number Original line Diff line number Diff line
@@ -16,6 +16,7 @@


package com.android.systemui.qs.ui.viewmodel
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
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.Kosmos.Fixture
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.kosmos.testDispatcher
@@ -36,6 +37,7 @@ val Kosmos.quickSettingsSceneContentViewModel by Fixture {
        sceneInteractor = sceneInteractor,
        sceneInteractor = sceneInteractor,
        mainDispatcher = testDispatcher,
        mainDispatcher = testDispatcher,
        windowRootViewBlurInteractor = windowRootViewBlurInteractor,
        windowRootViewBlurInteractor = windowRootViewBlurInteractor,
        blurConfig = blurConfig,
    )
    )
}
}