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

Commit 363df2ec authored by Tracy Zhou's avatar Tracy Zhou
Browse files

Blur ambient AOD wallpaper (Reland)

Bouncer: blur + zoomout. AOD: blur + no zoomout. Previous change (ag/31846198) introduced performance regressions due to separating the signals, which actually changed the behavior from overrding to max(wake, lock). Hence we are going back to using one siganl for wake and unlock, while adding a boolean variable to keep track of where the signal comes from.

Not a lockscreen expert, so the performance fix is mostly from the logic point of view. Let me know if you have any concerns about how signals from these two channels may overlap.

Bug: 397818296
Test: verified the behavior and ran the lockscreen suite for performance
Flag: com.android.systemui.shared.ambient_aod

Change-Id: Iacb68352bf839b9c487684f9f87fdb3105fa85fb
parent f73ddc1c
Loading
Loading
Loading
Loading
+15 −9
Original line number Original line Diff line number Diff line
@@ -34,7 +34,6 @@ import com.android.systemui.kosmos.testScope
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.res.R
import com.android.systemui.res.R
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shared.Flags as SharedFlags
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.phone.ScrimController
@@ -44,11 +43,10 @@ import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
import com.android.systemui.testKosmos
import com.android.systemui.testKosmos
import com.android.systemui.util.WallpaperController
import com.android.systemui.util.WallpaperController
import com.android.systemui.util.mockito.eq
import com.android.systemui.util.mockito.eq
import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor
import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
import com.android.wm.shell.appzoomout.AppZoomOut
import com.android.wm.shell.appzoomout.AppZoomOut
import com.google.common.truth.Truth.assertThat
import com.google.common.truth.Truth.assertThat
import java.util.Optional
import java.util.function.Consumer
import org.junit.Before
import org.junit.Before
import org.junit.Rule
import org.junit.Rule
import org.junit.Test
import org.junit.Test
@@ -69,6 +67,8 @@ import org.mockito.Mockito.reset
import org.mockito.Mockito.verify
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import org.mockito.Mockito.`when`
import org.mockito.junit.MockitoJUnit
import org.mockito.junit.MockitoJUnit
import java.util.Optional
import java.util.function.Consumer


@RunWith(AndroidJUnit4::class)
@RunWith(AndroidJUnit4::class)
@RunWithLooper
@RunWithLooper
@@ -76,6 +76,7 @@ import org.mockito.junit.MockitoJUnit
class NotificationShadeDepthControllerTest : SysuiTestCase() {
class NotificationShadeDepthControllerTest : SysuiTestCase() {
    private val kosmos = testKosmos()
    private val kosmos = testKosmos()


    private val applicationScope = kosmos.testScope.backgroundScope
    @Mock private lateinit var windowRootViewBlurInteractor: WindowRootViewBlurInteractor
    @Mock private lateinit var windowRootViewBlurInteractor: WindowRootViewBlurInteractor
    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var statusBarStateController: StatusBarStateController
    @Mock private lateinit var blurUtils: BlurUtils
    @Mock private lateinit var blurUtils: BlurUtils
@@ -84,6 +85,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() {
    @Mock private lateinit var keyguardInteractor: KeyguardInteractor
    @Mock private lateinit var keyguardInteractor: KeyguardInteractor
    @Mock private lateinit var choreographer: Choreographer
    @Mock private lateinit var choreographer: Choreographer
    @Mock private lateinit var wallpaperController: WallpaperController
    @Mock private lateinit var wallpaperController: WallpaperController
    @Mock private lateinit var wallpaperInteractor: WallpaperInteractor
    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock private lateinit var notificationShadeWindowController: NotificationShadeWindowController
    @Mock private lateinit var dumpManager: DumpManager
    @Mock private lateinit var dumpManager: DumpManager
    @Mock private lateinit var appZoomOutOptional: Optional<AppZoomOut>
    @Mock private lateinit var appZoomOutOptional: Optional<AppZoomOut>
@@ -128,12 +130,14 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() {
                keyguardInteractor,
                keyguardInteractor,
                choreographer,
                choreographer,
                wallpaperController,
                wallpaperController,
                wallpaperInteractor,
                notificationShadeWindowController,
                notificationShadeWindowController,
                dozeParameters,
                dozeParameters,
                context,
                context,
                ResourcesSplitShadeStateController(),
                ResourcesSplitShadeStateController(),
                windowRootViewBlurInteractor,
                windowRootViewBlurInteractor,
                appZoomOutOptional,
                appZoomOutOptional,
                applicationScope,
                dumpManager,
                dumpManager,
                configurationController,
                configurationController,
            )
            )
@@ -310,19 +314,21 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() {
    }
    }


    @Test
    @Test
    @DisableFlags(SharedFlags.FLAG_AMBIENT_AOD)
    fun onDozeAmountChanged_doesNotApplyBlurWithAmbientAod() {
    fun onDozeAmountChanged_appliesBlur() {
        notificationShadeDepthController.wallpaperSupportsAmbientMode = false

        statusBarStateListener.onDozeAmountChanged(1f, 1f)
        statusBarStateListener.onDozeAmountChanged(1f, 1f)
        notificationShadeDepthController.updateBlurCallback.doFrame(0)
        notificationShadeDepthController.updateBlurCallback.doFrame(0)
        verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
        verify(blurUtils).applyBlur(any(), eq(0), eq(false))
    }
    }


    @Test
    @Test
    @EnableFlags(SharedFlags.FLAG_AMBIENT_AOD)
    fun onDozeAmountChanged_appliesBlurWithAmbientAod() {
    fun onDozeAmountChanged_doesNotApplyBlurWithAmbientAod() {
        notificationShadeDepthController.wallpaperSupportsAmbientMode = true

        statusBarStateListener.onDozeAmountChanged(1f, 1f)
        statusBarStateListener.onDozeAmountChanged(1f, 1f)
        notificationShadeDepthController.updateBlurCallback.doFrame(0)
        notificationShadeDepthController.updateBlurCallback.doFrame(0)
        verify(blurUtils).applyBlur(any(), eq(0), eq(false))
        verify(blurUtils).applyBlur(any(), eq(maxBlur), eq(false))
    }
    }


    @Test
    @Test
+45 −15
Original line number Original line Diff line number Diff line
@@ -38,13 +38,13 @@ import com.android.systemui.Flags
import com.android.systemui.Flags.spatialModelAppPushback
import com.android.systemui.Flags.spatialModelAppPushback
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.animation.ShadeInterpolation
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.dump.DumpManager
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.ShadeDisplayAware
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionChangeEvent
import com.android.systemui.shade.ShadeExpansionListener
import com.android.systemui.shade.ShadeExpansionListener
import com.android.systemui.shared.Flags.ambientAod
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.phone.DozeParameters
@@ -53,6 +53,7 @@ import com.android.systemui.statusbar.policy.ConfigurationController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.systemui.statusbar.policy.SplitShadeStateController
import com.android.systemui.util.WallpaperController
import com.android.systemui.util.WallpaperController
import com.android.systemui.wallpapers.domain.interactor.WallpaperInteractor
import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
import com.android.systemui.window.domain.interactor.WindowRootViewBlurInteractor
import com.android.wm.shell.appzoomout.AppZoomOut
import com.android.wm.shell.appzoomout.AppZoomOut
import java.io.PrintWriter
import java.io.PrintWriter
@@ -78,12 +79,14 @@ constructor(
    private val keyguardInteractor: KeyguardInteractor,
    private val keyguardInteractor: KeyguardInteractor,
    private val choreographer: Choreographer,
    private val choreographer: Choreographer,
    private val wallpaperController: WallpaperController,
    private val wallpaperController: WallpaperController,
    private val wallpaperInteractor: WallpaperInteractor,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val notificationShadeWindowController: NotificationShadeWindowController,
    private val dozeParameters: DozeParameters,
    private val dozeParameters: DozeParameters,
    @ShadeDisplayAware private val context: Context,
    @ShadeDisplayAware private val context: Context,
    private val splitShadeStateController: SplitShadeStateController,
    private val splitShadeStateController: SplitShadeStateController,
    private val windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
    private val windowRootViewBlurInteractor: WindowRootViewBlurInteractor,
    private val appZoomOutOptional: Optional<AppZoomOut>,
    private val appZoomOutOptional: Optional<AppZoomOut>,
    @Application private val applicationScope: CoroutineScope,
    dumpManager: DumpManager,
    dumpManager: DumpManager,
    configurationController: ConfigurationController,
    configurationController: ConfigurationController,
) : ShadeExpansionListener, Dumpable {
) : ShadeExpansionListener, Dumpable {
@@ -113,6 +116,8 @@ constructor(
    private var prevTimestamp: Long = -1
    private var prevTimestamp: Long = -1
    private var prevShadeDirection = 0
    private var prevShadeDirection = 0
    private var prevShadeVelocity = 0f
    private var prevShadeVelocity = 0f
    private var prevDozeAmount: Float = 0f
    @VisibleForTesting var wallpaperSupportsAmbientMode: Boolean = false
    // tracks whether app launch transition is in progress. This involves two independent factors
    // tracks whether app launch transition is in progress. This involves two independent factors
    // that control blur, shade expansion and app launch animation from outside sysui.
    // that control blur, shade expansion and app launch animation from outside sysui.
    // They can complete out of order, this flag will be reset by the animation that finishes later.
    // They can complete out of order, this flag will be reset by the animation that finishes later.
@@ -228,8 +233,10 @@ constructor(
            scheduleUpdate()
            scheduleUpdate()
        }
        }


    /** Blur radius of the wake-up animation on this frame. */
    private data class WakeAndUnlockBlurData(val radius: Float, val useZoom: Boolean = true)
    private var wakeAndUnlockBlurRadius = 0f

    /** Blur radius of the wake and unlock animation on this frame, and whether to zoom out. */
    private var wakeAndUnlockBlurData = WakeAndUnlockBlurData(0f)
        set(value) {
        set(value) {
            if (field == value) return
            if (field == value) return
            field = value
            field = value
@@ -256,14 +263,18 @@ constructor(
            ShadeInterpolation.getNotificationScrimAlpha(qsPanelExpansion) * shadeExpansion
            ShadeInterpolation.getNotificationScrimAlpha(qsPanelExpansion) * shadeExpansion
        combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio))
        combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(qsExpandedRatio))
        combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
        combinedBlur = max(combinedBlur, blurUtils.blurRadiusOfRatio(transitionToFullShadeProgress))
        var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius)
        var shadeRadius = max(combinedBlur, wakeAndUnlockBlurData.radius)


        if (areBlursDisabledForAppLaunch || blursDisabledForUnlock) {
        if (areBlursDisabledForAppLaunch || blursDisabledForUnlock) {
            shadeRadius = 0f
            shadeRadius = 0f
        }
        }


        var blur = shadeRadius.toInt()
        var blur = shadeRadius.toInt()
        val zoomOut = blurRadiusToZoomOut(blurRadius = shadeRadius)
        // If the blur comes from waking up, we don't want to zoom out the background
        val zoomOut =
            if (shadeRadius != wakeAndUnlockBlurData.radius|| wakeAndUnlockBlurData.useZoom)
                blurRadiusToZoomOut(blurRadius = shadeRadius)
            else 0f
        // Make blur be 0 if it is necessary to stop blur effect.
        // Make blur be 0 if it is necessary to stop blur effect.
        if (scrimsVisible) {
        if (scrimsVisible) {
            if (!Flags.notificationShadeBlur()) {
            if (!Flags.notificationShadeBlur()) {
@@ -348,14 +359,14 @@ constructor(
                        startDelay = keyguardStateController.keyguardFadingAwayDelay
                        startDelay = keyguardStateController.keyguardFadingAwayDelay
                        interpolator = Interpolators.FAST_OUT_SLOW_IN
                        interpolator = Interpolators.FAST_OUT_SLOW_IN
                        addUpdateListener { animation: ValueAnimator ->
                        addUpdateListener { animation: ValueAnimator ->
                            wakeAndUnlockBlurRadius =
                            wakeAndUnlockBlurData =
                                blurUtils.blurRadiusOfRatio(animation.animatedValue as Float)
                                WakeAndUnlockBlurData(blurUtils.blurRadiusOfRatio(animation.animatedValue as Float))
                        }
                        }
                        addListener(
                        addListener(
                            object : AnimatorListenerAdapter() {
                            object : AnimatorListenerAdapter() {
                                override fun onAnimationEnd(animation: Animator) {
                                override fun onAnimationEnd(animation: Animator) {
                                    keyguardAnimator = null
                                    keyguardAnimator = null
                                    wakeAndUnlockBlurRadius = 0f
                                    wakeAndUnlockBlurData = WakeAndUnlockBlurData(0f)
                                }
                                }
                            }
                            }
                        )
                        )
@@ -391,12 +402,20 @@ constructor(
            }
            }


            override fun onDozeAmountChanged(linear: Float, eased: Float) {
            override fun onDozeAmountChanged(linear: Float, eased: Float) {
                wakeAndUnlockBlurRadius =
                prevDozeAmount = eased
                    if (ambientAod()) {
                updateWakeBlurRadius(prevDozeAmount)
            }
        }

    private fun updateWakeBlurRadius(ratio: Float) {
        wakeAndUnlockBlurData = WakeAndUnlockBlurData(getNewWakeBlurRadius(ratio), false)
    }

    private fun getNewWakeBlurRadius(ratio: Float): Float {
        return if (!wallpaperSupportsAmbientMode) {
            0f
            0f
        } else {
        } else {
                        blurUtils.blurRadiusOfRatio(eased)
            blurUtils.blurRadiusOfRatio(ratio)
                    }
        }
        }
    }
    }


@@ -421,6 +440,16 @@ constructor(
                }
                }
            }
            }
        )
        )
        applicationScope.launch {
            wallpaperInteractor.wallpaperSupportsAmbientMode.collect { supported ->
                wallpaperSupportsAmbientMode = supported
                if (getNewWakeBlurRadius(prevDozeAmount) == wakeAndUnlockBlurData.radius
                    && !wakeAndUnlockBlurData.useZoom) {
                    // Update wake and unlock radius only if the previous value comes from wake-up.
                    updateWakeBlurRadius(prevDozeAmount)
                }
            }
        }
        initBlurListeners()
        initBlurListeners()
    }
    }


@@ -611,7 +640,8 @@ constructor(
            it.println("shouldApplyShadeBlur: ${shouldApplyShadeBlur()}")
            it.println("shouldApplyShadeBlur: ${shouldApplyShadeBlur()}")
            it.println("shadeAnimation: ${shadeAnimation.radius}")
            it.println("shadeAnimation: ${shadeAnimation.radius}")
            it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
            it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
            it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
            it.println("wakeAndUnlockBlurRadius: ${wakeAndUnlockBlurData.radius}")
            it.println("wakeAndUnlockBlurUsesZoom: ${wakeAndUnlockBlurData.useZoom}")
            it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
            it.println("blursDisabledForAppLaunch: $blursDisabledForAppLaunch")
            it.println("appLaunchTransitionIsInProgress: $appLaunchTransitionIsInProgress")
            it.println("appLaunchTransitionIsInProgress: $appLaunchTransitionIsInProgress")
            it.println("qsPanelExpansion: $qsPanelExpansion")
            it.println("qsPanelExpansion: $qsPanelExpansion")