Loading packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt +2 −2 Original line number Diff line number Diff line Loading @@ -38,8 +38,8 @@ open class BlurUtils @Inject constructor( @Main private val resources: Resources, dumpManager: DumpManager ) : Dumpable { private val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) private val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) private val blurSupportedSysProp = SystemProperties .getBoolean("ro.surface_flinger.supports_background_blur", false) private val blurDisabledSysProp = SystemProperties Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +141 −8 Original line number Diff line number Diff line Loading @@ -20,7 +20,9 @@ import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.app.WallpaperManager import android.os.SystemClock import android.util.Log import android.util.MathUtils import android.view.Choreographer import android.view.View import androidx.annotation.VisibleForTesting Loading @@ -44,6 +46,7 @@ import java.io.PrintWriter import javax.inject.Inject import javax.inject.Singleton import kotlin.math.max import kotlin.math.sign /** * Controller responsible for statusbar window blur. Loading @@ -61,6 +64,11 @@ class NotificationShadeDepthController @Inject constructor( ) : PanelExpansionListener, Dumpable { companion object { private const val WAKE_UP_ANIMATION_ENABLED = true private const val VELOCITY_SCALE = 100f private const val MAX_VELOCITY = 3000f private const val MIN_VELOCITY = -MAX_VELOCITY private const val INTERACTION_BLUR_FRACTION = 0.4f private const val ANIMATION_BLUR_FRACTION = 1f - INTERACTION_BLUR_FRACTION private const val TAG = "DepthController" } Loading @@ -71,8 +79,19 @@ class NotificationShadeDepthController @Inject constructor( private var updateScheduled: Boolean = false private var shadeExpansion = 0f private var ignoreShadeBlurUntilHidden: Boolean = false private var isClosed: Boolean = true private var isOpen: Boolean = false private var isBlurred: Boolean = false private var prevTracking: Boolean = false private var prevTimestamp: Long = -1 private var prevShadeDirection = 0 private var prevShadeVelocity = 0f @VisibleForTesting var shadeSpring = DepthAnimation() var shadeAnimation = DepthAnimation() @VisibleForTesting var globalActionsSpring = DepthAnimation() var showingHomeControls: Boolean = false Loading @@ -98,12 +117,15 @@ class NotificationShadeDepthController @Inject constructor( return } if (shadeSpring.radius == 0) { if (shadeSpring.radius == 0 && shadeAnimation.radius == 0) { return } ignoreShadeBlurUntilHidden = true shadeSpring.animateTo(0) shadeSpring.finishIfRunning() shadeAnimation.animateTo(0) shadeAnimation.finishIfRunning() } /** Loading Loading @@ -132,8 +154,11 @@ class NotificationShadeDepthController @Inject constructor( @VisibleForTesting val updateBlurCallback = Choreographer.FrameCallback { updateScheduled = false var shadeRadius = max(shadeSpring.radius, wakeAndUnlockBlurRadius).toFloat() val normalizedBlurRadius = MathUtils.constrain(shadeAnimation.radius, blurUtils.minBlurRadius, blurUtils.maxBlurRadius) val combinedBlur = (shadeSpring.radius * INTERACTION_BLUR_FRACTION + normalizedBlurRadius * ANIMATION_BLUR_FRACTION).toInt() var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius).toFloat() shadeRadius *= 1f - brightnessMirrorSpring.ratio val launchProgress = notificationLaunchAnimationParams?.linearProgress ?: 0f shadeRadius *= (1f - launchProgress) * (1f - launchProgress) Loading Loading @@ -208,12 +233,15 @@ class NotificationShadeDepthController @Inject constructor( private val statusBarStateCallback = object : StatusBarStateController.StateListener { override fun onStateChanged(newState: Int) { updateShadeAnimationBlur( shadeExpansion, prevTracking, prevShadeVelocity, prevShadeDirection) updateShadeBlur() } override fun onDozingChanged(isDozing: Boolean) { if (isDozing) { shadeSpring.finishIfRunning() shadeAnimation.finishIfRunning() globalActionsSpring.finishIfRunning() brightnessMirrorSpring.finishIfRunning() } Loading @@ -234,24 +262,110 @@ class NotificationShadeDepthController @Inject constructor( // Stop blur effect when scrims is opaque to avoid unnecessary GPU composition. visibility -> scrimsVisible = visibility == ScrimController.OPAQUE } shadeAnimation.setStiffness(SpringForce.STIFFNESS_LOW) shadeAnimation.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY) } /** * Update blurs when pulling down the shade */ override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) { if (expansion == shadeExpansion) { val timestamp = SystemClock.elapsedRealtimeNanos() if (shadeExpansion == expansion && prevTracking == tracking) { prevTimestamp = timestamp return } var deltaTime = 1f if (prevTimestamp < 0) { prevTimestamp = timestamp } else { deltaTime = MathUtils.constrain( ((timestamp - prevTimestamp) / 1E9).toFloat(), 0.00001f, 1f) } val diff = expansion - shadeExpansion val shadeDirection = sign(diff).toInt() val shadeVelocity = MathUtils.constrain( VELOCITY_SCALE * diff / deltaTime, MIN_VELOCITY, MAX_VELOCITY) updateShadeAnimationBlur(expansion, tracking, shadeVelocity, shadeDirection) prevShadeDirection = shadeDirection prevShadeVelocity = shadeVelocity shadeExpansion = expansion prevTracking = tracking prevTimestamp = timestamp updateShadeBlur() } private fun updateShadeAnimationBlur( expansion: Float, tracking: Boolean, velocity: Float, direction: Int ) { if (isOnKeyguardNotDismissing()) { if (expansion > 0f) { // Blur view if user starts animating in the shade. if (isClosed) { animateBlur(true, velocity) isClosed = false } // If we were blurring out and the user stopped the animation, blur view. if (tracking && !isBlurred) { animateBlur(true, 0f) } // If shade is being closed and the user isn't interacting with it, un-blur. if (!tracking && direction < 0 && isBlurred) { animateBlur(false, velocity) } if (expansion == 1f) { if (!isOpen) { isOpen = true // If shade is open and view is not blurred, blur. if (!isBlurred) { animateBlur(true, velocity) } } } else { isOpen = false } // Automatic animation when the user closes the shade. } else if (!isClosed) { isClosed = true // If shade is closed and view is not blurred, blur. if (isBlurred) { animateBlur(false, velocity) } } } else { animateBlur(false, 0f) isClosed = true isOpen = false } } private fun animateBlur(blur: Boolean, velocity: Float) { isBlurred = blur val targetBlurNormalized = if (blur && isOnKeyguardNotDismissing()) { 1f } else { 0f } shadeAnimation.setStartVelocity(velocity) shadeAnimation.animateTo(blurUtils.blurRadiusOfRatio(targetBlurNormalized)) } private fun updateShadeBlur() { var newBlur = 0 val state = statusBarStateController.state if ((state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) && !keyguardStateController.isKeyguardFadingAway) { if (isOnKeyguardNotDismissing()) { newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion) } shadeSpring.animateTo(newBlur) Loading @@ -266,6 +380,12 @@ class NotificationShadeDepthController @Inject constructor( choreographer.postFrameCallback(updateBlurCallback) } private fun isOnKeyguardNotDismissing(): Boolean { val state = statusBarStateController.state return (state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) && !keyguardStateController.isKeyguardFadingAway } fun updateGlobalDialogVisibility(visibility: Float, dialogView: View?) { globalActionsSpring.animateTo(blurUtils.blurRadiusOfRatio(visibility), dialogView) } Loading @@ -275,6 +395,7 @@ class NotificationShadeDepthController @Inject constructor( it.println("StatusBarWindowBlurController:") it.increaseIndent() it.println("shadeRadius: ${shadeSpring.radius}") it.println("shadeAnimation: ${shadeAnimation.radius}") it.println("globalActionsRadius: ${globalActionsSpring.radius}") it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}") it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius") Loading Loading @@ -343,5 +464,17 @@ class NotificationShadeDepthController @Inject constructor( springAnimation.skipToEnd() } } fun setStiffness(stiffness: Float) { springAnimation.spring.stiffness = stiffness } fun setDampingRatio(dampingRation: Float) { springAnimation.spring.dampingRatio = dampingRation } fun setStartVelocity(velocity: Float) { springAnimation.setStartVelocity(velocity) } } } packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +55 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Mock private lateinit var root: View @Mock private lateinit var viewRootImpl: ViewRootImpl @Mock private lateinit var shadeSpring: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var shadeAnimation: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var globalActionsSpring: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var brightnessSpring: NotificationShadeDepthController.DepthAnimation @JvmField @Rule val mockitoRule = MockitoJUnit.rule() Loading @@ -80,11 +81,15 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { `when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer -> (answer.arguments[0] as Float * maxBlur).toInt() } `when`(blurUtils.minBlurRadius).thenReturn(0) `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur) notificationShadeDepthController = NotificationShadeDepthController( statusBarStateController, blurUtils, biometricUnlockController, keyguardStateController, choreographer, wallpaperManager, notificationShadeWindowController, dumpManager) notificationShadeDepthController.shadeSpring = shadeSpring notificationShadeDepthController.shadeAnimation = shadeAnimation notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring notificationShadeDepthController.globalActionsSpring = globalActionsSpring notificationShadeDepthController.root = root Loading @@ -104,16 +109,61 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, false /* tracking */) verify(shadeSpring).animateTo(eq(maxBlur), any()) verify(shadeAnimation).animateTo(eq(maxBlur), any()) } @Test fun onPanelExpansionChanged_animatesBlurIn_ifShade() { notificationShadeDepthController.onPanelExpansionChanged(0.01f /* expansion */, false /* tracking */) verify(shadeAnimation).animateTo(eq(maxBlur), any()) } @Test fun onPanelExpansionChanged_animatesBlurOut_ifShade() { onPanelExpansionChanged_animatesBlurIn_ifShade() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(0f /* expansion */, false /* tracking */) verify(shadeAnimation).animateTo(eq(0), any()) } @Test fun onPanelExpansionChanged_animatesBlurOut_ifFlick() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, true /* tracking */) verify(shadeAnimation, never()).animateTo(anyInt(), any()) notificationShadeDepthController.onPanelExpansionChanged(0.9f /* expansion */, true /* tracking */) verify(shadeAnimation, never()).animateTo(anyInt(), any()) notificationShadeDepthController.onPanelExpansionChanged(0.8f /* expansion */, false /* tracking */) verify(shadeAnimation).animateTo(eq(0), any()) } @Test fun onPanelExpansionChanged_animatesBlurIn_ifFlickCancelled() { onPanelExpansionChanged_animatesBlurOut_ifFlick() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(0.6f /* expansion */, true /* tracking */) verify(shadeAnimation).animateTo(eq(maxBlur), any()) } @Test fun onStateChanged_reevalutesBlurs_ifSameRadiusAndNewState() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(shadeSpring) clearInvocations(shadeAnimation) statusBarState = StatusBarState.KEYGUARD statusBarStateListener.onStateChanged(statusBarState) verify(shadeSpring).animateTo(eq(0), any()) verify(shadeAnimation).animateTo(eq(0), any()) } @Test Loading Loading @@ -147,6 +197,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun updateBlurCallback_setsBlur_whenExpanded() { `when`(shadeSpring.radius).thenReturn(maxBlur) `when`(shadeAnimation.radius).thenReturn(maxBlur) notificationShadeDepthController.updateBlurCallback.doFrame(0) verify(blurUtils).applyBlur(any(), eq(maxBlur)) } Loading @@ -154,6 +205,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun updateBlurCallback_appLaunchAnimation_overridesZoom() { `when`(shadeSpring.radius).thenReturn(maxBlur) `when`(shadeAnimation.radius).thenReturn(maxBlur) val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters() animProgress.linearProgress = 1f notificationShadeDepthController.notificationLaunchAnimationParams = animProgress Loading Loading @@ -187,6 +239,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { `when`(brightnessSpring.ratio).thenReturn(1f) // And shade is blurred `when`(shadeSpring.radius).thenReturn(maxBlur) `when`(shadeAnimation.radius).thenReturn(maxBlur) notificationShadeDepthController.updateBlurCallback.doFrame(0) verify(notificationShadeWindowController).setBackgroundBlurRadius(0) Loading @@ -207,8 +260,10 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters() animProgress.linearProgress = 0.5f `when`(shadeSpring.radius).thenReturn(0) `when`(shadeAnimation.radius).thenReturn(0) notificationShadeDepthController.notificationLaunchAnimationParams = animProgress verify(shadeSpring, never()).animateTo(anyInt(), any()) verify(shadeAnimation, never()).animateTo(anyInt(), any()) } private fun <T : Any> safeEq(value: T): T { Loading Loading
packages/SystemUI/src/com/android/systemui/statusbar/BlurUtils.kt +2 −2 Original line number Diff line number Diff line Loading @@ -38,8 +38,8 @@ open class BlurUtils @Inject constructor( @Main private val resources: Resources, dumpManager: DumpManager ) : Dumpable { private val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) private val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) val minBlurRadius = resources.getDimensionPixelSize(R.dimen.min_window_blur_radius) val maxBlurRadius = resources.getDimensionPixelSize(R.dimen.max_window_blur_radius) private val blurSupportedSysProp = SystemProperties .getBoolean("ro.surface_flinger.supports_background_blur", false) private val blurDisabledSysProp = SystemProperties Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +141 −8 Original line number Diff line number Diff line Loading @@ -20,7 +20,9 @@ import android.animation.Animator import android.animation.AnimatorListenerAdapter import android.animation.ValueAnimator import android.app.WallpaperManager import android.os.SystemClock import android.util.Log import android.util.MathUtils import android.view.Choreographer import android.view.View import androidx.annotation.VisibleForTesting Loading @@ -44,6 +46,7 @@ import java.io.PrintWriter import javax.inject.Inject import javax.inject.Singleton import kotlin.math.max import kotlin.math.sign /** * Controller responsible for statusbar window blur. Loading @@ -61,6 +64,11 @@ class NotificationShadeDepthController @Inject constructor( ) : PanelExpansionListener, Dumpable { companion object { private const val WAKE_UP_ANIMATION_ENABLED = true private const val VELOCITY_SCALE = 100f private const val MAX_VELOCITY = 3000f private const val MIN_VELOCITY = -MAX_VELOCITY private const val INTERACTION_BLUR_FRACTION = 0.4f private const val ANIMATION_BLUR_FRACTION = 1f - INTERACTION_BLUR_FRACTION private const val TAG = "DepthController" } Loading @@ -71,8 +79,19 @@ class NotificationShadeDepthController @Inject constructor( private var updateScheduled: Boolean = false private var shadeExpansion = 0f private var ignoreShadeBlurUntilHidden: Boolean = false private var isClosed: Boolean = true private var isOpen: Boolean = false private var isBlurred: Boolean = false private var prevTracking: Boolean = false private var prevTimestamp: Long = -1 private var prevShadeDirection = 0 private var prevShadeVelocity = 0f @VisibleForTesting var shadeSpring = DepthAnimation() var shadeAnimation = DepthAnimation() @VisibleForTesting var globalActionsSpring = DepthAnimation() var showingHomeControls: Boolean = false Loading @@ -98,12 +117,15 @@ class NotificationShadeDepthController @Inject constructor( return } if (shadeSpring.radius == 0) { if (shadeSpring.radius == 0 && shadeAnimation.radius == 0) { return } ignoreShadeBlurUntilHidden = true shadeSpring.animateTo(0) shadeSpring.finishIfRunning() shadeAnimation.animateTo(0) shadeAnimation.finishIfRunning() } /** Loading Loading @@ -132,8 +154,11 @@ class NotificationShadeDepthController @Inject constructor( @VisibleForTesting val updateBlurCallback = Choreographer.FrameCallback { updateScheduled = false var shadeRadius = max(shadeSpring.radius, wakeAndUnlockBlurRadius).toFloat() val normalizedBlurRadius = MathUtils.constrain(shadeAnimation.radius, blurUtils.minBlurRadius, blurUtils.maxBlurRadius) val combinedBlur = (shadeSpring.radius * INTERACTION_BLUR_FRACTION + normalizedBlurRadius * ANIMATION_BLUR_FRACTION).toInt() var shadeRadius = max(combinedBlur, wakeAndUnlockBlurRadius).toFloat() shadeRadius *= 1f - brightnessMirrorSpring.ratio val launchProgress = notificationLaunchAnimationParams?.linearProgress ?: 0f shadeRadius *= (1f - launchProgress) * (1f - launchProgress) Loading Loading @@ -208,12 +233,15 @@ class NotificationShadeDepthController @Inject constructor( private val statusBarStateCallback = object : StatusBarStateController.StateListener { override fun onStateChanged(newState: Int) { updateShadeAnimationBlur( shadeExpansion, prevTracking, prevShadeVelocity, prevShadeDirection) updateShadeBlur() } override fun onDozingChanged(isDozing: Boolean) { if (isDozing) { shadeSpring.finishIfRunning() shadeAnimation.finishIfRunning() globalActionsSpring.finishIfRunning() brightnessMirrorSpring.finishIfRunning() } Loading @@ -234,24 +262,110 @@ class NotificationShadeDepthController @Inject constructor( // Stop blur effect when scrims is opaque to avoid unnecessary GPU composition. visibility -> scrimsVisible = visibility == ScrimController.OPAQUE } shadeAnimation.setStiffness(SpringForce.STIFFNESS_LOW) shadeAnimation.setDampingRatio(SpringForce.DAMPING_RATIO_NO_BOUNCY) } /** * Update blurs when pulling down the shade */ override fun onPanelExpansionChanged(expansion: Float, tracking: Boolean) { if (expansion == shadeExpansion) { val timestamp = SystemClock.elapsedRealtimeNanos() if (shadeExpansion == expansion && prevTracking == tracking) { prevTimestamp = timestamp return } var deltaTime = 1f if (prevTimestamp < 0) { prevTimestamp = timestamp } else { deltaTime = MathUtils.constrain( ((timestamp - prevTimestamp) / 1E9).toFloat(), 0.00001f, 1f) } val diff = expansion - shadeExpansion val shadeDirection = sign(diff).toInt() val shadeVelocity = MathUtils.constrain( VELOCITY_SCALE * diff / deltaTime, MIN_VELOCITY, MAX_VELOCITY) updateShadeAnimationBlur(expansion, tracking, shadeVelocity, shadeDirection) prevShadeDirection = shadeDirection prevShadeVelocity = shadeVelocity shadeExpansion = expansion prevTracking = tracking prevTimestamp = timestamp updateShadeBlur() } private fun updateShadeAnimationBlur( expansion: Float, tracking: Boolean, velocity: Float, direction: Int ) { if (isOnKeyguardNotDismissing()) { if (expansion > 0f) { // Blur view if user starts animating in the shade. if (isClosed) { animateBlur(true, velocity) isClosed = false } // If we were blurring out and the user stopped the animation, blur view. if (tracking && !isBlurred) { animateBlur(true, 0f) } // If shade is being closed and the user isn't interacting with it, un-blur. if (!tracking && direction < 0 && isBlurred) { animateBlur(false, velocity) } if (expansion == 1f) { if (!isOpen) { isOpen = true // If shade is open and view is not blurred, blur. if (!isBlurred) { animateBlur(true, velocity) } } } else { isOpen = false } // Automatic animation when the user closes the shade. } else if (!isClosed) { isClosed = true // If shade is closed and view is not blurred, blur. if (isBlurred) { animateBlur(false, velocity) } } } else { animateBlur(false, 0f) isClosed = true isOpen = false } } private fun animateBlur(blur: Boolean, velocity: Float) { isBlurred = blur val targetBlurNormalized = if (blur && isOnKeyguardNotDismissing()) { 1f } else { 0f } shadeAnimation.setStartVelocity(velocity) shadeAnimation.animateTo(blurUtils.blurRadiusOfRatio(targetBlurNormalized)) } private fun updateShadeBlur() { var newBlur = 0 val state = statusBarStateController.state if ((state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) && !keyguardStateController.isKeyguardFadingAway) { if (isOnKeyguardNotDismissing()) { newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion) } shadeSpring.animateTo(newBlur) Loading @@ -266,6 +380,12 @@ class NotificationShadeDepthController @Inject constructor( choreographer.postFrameCallback(updateBlurCallback) } private fun isOnKeyguardNotDismissing(): Boolean { val state = statusBarStateController.state return (state == StatusBarState.SHADE || state == StatusBarState.SHADE_LOCKED) && !keyguardStateController.isKeyguardFadingAway } fun updateGlobalDialogVisibility(visibility: Float, dialogView: View?) { globalActionsSpring.animateTo(blurUtils.blurRadiusOfRatio(visibility), dialogView) } Loading @@ -275,6 +395,7 @@ class NotificationShadeDepthController @Inject constructor( it.println("StatusBarWindowBlurController:") it.increaseIndent() it.println("shadeRadius: ${shadeSpring.radius}") it.println("shadeAnimation: ${shadeAnimation.radius}") it.println("globalActionsRadius: ${globalActionsSpring.radius}") it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}") it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius") Loading Loading @@ -343,5 +464,17 @@ class NotificationShadeDepthController @Inject constructor( springAnimation.skipToEnd() } } fun setStiffness(stiffness: Float) { springAnimation.spring.stiffness = stiffness } fun setDampingRatio(dampingRation: Float) { springAnimation.spring.dampingRatio = dampingRation } fun setStartVelocity(velocity: Float) { springAnimation.setStartVelocity(velocity) } } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +55 −0 Original line number Diff line number Diff line Loading @@ -64,6 +64,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Mock private lateinit var root: View @Mock private lateinit var viewRootImpl: ViewRootImpl @Mock private lateinit var shadeSpring: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var shadeAnimation: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var globalActionsSpring: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var brightnessSpring: NotificationShadeDepthController.DepthAnimation @JvmField @Rule val mockitoRule = MockitoJUnit.rule() Loading @@ -80,11 +81,15 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { `when`(blurUtils.blurRadiusOfRatio(anyFloat())).then { answer -> (answer.arguments[0] as Float * maxBlur).toInt() } `when`(blurUtils.minBlurRadius).thenReturn(0) `when`(blurUtils.maxBlurRadius).thenReturn(maxBlur) notificationShadeDepthController = NotificationShadeDepthController( statusBarStateController, blurUtils, biometricUnlockController, keyguardStateController, choreographer, wallpaperManager, notificationShadeWindowController, dumpManager) notificationShadeDepthController.shadeSpring = shadeSpring notificationShadeDepthController.shadeAnimation = shadeAnimation notificationShadeDepthController.brightnessMirrorSpring = brightnessSpring notificationShadeDepthController.globalActionsSpring = globalActionsSpring notificationShadeDepthController.root = root Loading @@ -104,16 +109,61 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, false /* tracking */) verify(shadeSpring).animateTo(eq(maxBlur), any()) verify(shadeAnimation).animateTo(eq(maxBlur), any()) } @Test fun onPanelExpansionChanged_animatesBlurIn_ifShade() { notificationShadeDepthController.onPanelExpansionChanged(0.01f /* expansion */, false /* tracking */) verify(shadeAnimation).animateTo(eq(maxBlur), any()) } @Test fun onPanelExpansionChanged_animatesBlurOut_ifShade() { onPanelExpansionChanged_animatesBlurIn_ifShade() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(0f /* expansion */, false /* tracking */) verify(shadeAnimation).animateTo(eq(0), any()) } @Test fun onPanelExpansionChanged_animatesBlurOut_ifFlick() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, true /* tracking */) verify(shadeAnimation, never()).animateTo(anyInt(), any()) notificationShadeDepthController.onPanelExpansionChanged(0.9f /* expansion */, true /* tracking */) verify(shadeAnimation, never()).animateTo(anyInt(), any()) notificationShadeDepthController.onPanelExpansionChanged(0.8f /* expansion */, false /* tracking */) verify(shadeAnimation).animateTo(eq(0), any()) } @Test fun onPanelExpansionChanged_animatesBlurIn_ifFlickCancelled() { onPanelExpansionChanged_animatesBlurOut_ifFlick() clearInvocations(shadeAnimation) notificationShadeDepthController.onPanelExpansionChanged(0.6f /* expansion */, true /* tracking */) verify(shadeAnimation).animateTo(eq(maxBlur), any()) } @Test fun onStateChanged_reevalutesBlurs_ifSameRadiusAndNewState() { onPanelExpansionChanged_apliesBlur_ifShade() clearInvocations(shadeSpring) clearInvocations(shadeAnimation) statusBarState = StatusBarState.KEYGUARD statusBarStateListener.onStateChanged(statusBarState) verify(shadeSpring).animateTo(eq(0), any()) verify(shadeAnimation).animateTo(eq(0), any()) } @Test Loading Loading @@ -147,6 +197,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun updateBlurCallback_setsBlur_whenExpanded() { `when`(shadeSpring.radius).thenReturn(maxBlur) `when`(shadeAnimation.radius).thenReturn(maxBlur) notificationShadeDepthController.updateBlurCallback.doFrame(0) verify(blurUtils).applyBlur(any(), eq(maxBlur)) } Loading @@ -154,6 +205,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Test fun updateBlurCallback_appLaunchAnimation_overridesZoom() { `when`(shadeSpring.radius).thenReturn(maxBlur) `when`(shadeAnimation.radius).thenReturn(maxBlur) val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters() animProgress.linearProgress = 1f notificationShadeDepthController.notificationLaunchAnimationParams = animProgress Loading Loading @@ -187,6 +239,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { `when`(brightnessSpring.ratio).thenReturn(1f) // And shade is blurred `when`(shadeSpring.radius).thenReturn(maxBlur) `when`(shadeAnimation.radius).thenReturn(maxBlur) notificationShadeDepthController.updateBlurCallback.doFrame(0) verify(notificationShadeWindowController).setBackgroundBlurRadius(0) Loading @@ -207,8 +260,10 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters() animProgress.linearProgress = 0.5f `when`(shadeSpring.radius).thenReturn(0) `when`(shadeAnimation.radius).thenReturn(0) notificationShadeDepthController.notificationLaunchAnimationParams = animProgress verify(shadeSpring, never()).animateTo(anyInt(), any()) verify(shadeAnimation, never()).animateTo(anyInt(), any()) } private fun <T : Any> safeEq(value: T): T { Loading