Loading packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +2 −2 Original line number Diff line number Diff line Loading @@ -1849,7 +1849,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, .alpha(1) .translationX(0) .translationY(0) .setDuration(300) .setDuration(450) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .setUpdateListener(animation -> { float animatedValue = animation.getAnimatedFraction(); Loading Loading @@ -1878,7 +1878,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, .alpha(0) .translationX(mGlobalActionsLayout.getAnimationOffsetX()) .translationY(mGlobalActionsLayout.getAnimationOffsetY()) .setDuration(300) .setDuration(550) .withEndAction(this::completeDismiss) .setInterpolator(new LogAccelerateInterpolator()) .setUpdateListener(animation -> { Loading packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +68 −49 Original line number Diff line number Diff line Loading @@ -67,32 +67,9 @@ class NotificationShadeDepthController @Inject constructor( private var updateScheduled: Boolean = false private var shadeExpansion = 0f @VisibleForTesting var shadeSpring = SpringAnimation(this, object : FloatPropertyCompat<NotificationShadeDepthController>("shadeBlurRadius") { override fun setValue(rect: NotificationShadeDepthController?, value: Float) { shadeBlurRadius = value.toInt() } override fun getValue(rect: NotificationShadeDepthController?): Float { return shadeBlurRadius.toFloat() } }) private val zoomInterpolator = Interpolators.ACCELERATE_DECELERATE /** * Radius that we're animating to. */ private var pendingShadeBlurRadius = -1 /** * Shade blur radius on the current frame. */ private var shadeBlurRadius = 0 set(value) { if (field == value) return field = value scheduleUpdate() } var shadeSpring = DepthAnimation() @VisibleForTesting var globalActionsSpring = DepthAnimation() /** * Blur radius of the wake-up animation on this frame. Loading @@ -103,7 +80,6 @@ class NotificationShadeDepthController @Inject constructor( field = value scheduleUpdate() } private var globalDialogVisibility = 0f /** * Callback that updates the window blur value and is called only once per frame. Loading @@ -111,12 +87,9 @@ class NotificationShadeDepthController @Inject constructor( private val updateBlurCallback = Choreographer.FrameCallback { updateScheduled = false val blur = max(shadeBlurRadius, max(wakeAndUnlockBlurRadius, blurUtils.blurRadiusOfRatio(globalDialogVisibility))) val blur = max(max(shadeSpring.radius, wakeAndUnlockBlurRadius), globalActionsSpring.radius) blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur) val rawZoom = max(blurUtils.ratioOfBlurRadius(blur), globalDialogVisibility) wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomInterpolator.getInterpolation(rawZoom)) wallpaperManager.setWallpaperZoomOut(root.windowToken, blurUtils.ratioOfBlurRadius(blur)) notificationShadeWindowController.setBackgroundBlurRadius(blur) } Loading Loading @@ -163,8 +136,9 @@ class NotificationShadeDepthController @Inject constructor( } override fun onDozingChanged(isDozing: Boolean) { if (isDozing && shadeSpring.isRunning) { shadeSpring.skipToEnd() if (isDozing) { shadeSpring.finishIfRunning() globalActionsSpring.finishIfRunning() } } } Loading @@ -174,10 +148,6 @@ class NotificationShadeDepthController @Inject constructor( if (WAKE_UP_ANIMATION_ENABLED) { keyguardStateController.addCallback(keyguardStateCallback) } shadeSpring.spring = SpringForce(0.0f) shadeSpring.spring.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY shadeSpring.spring.stiffness = SpringForce.STIFFNESS_LOW shadeSpring.addEndListener { _, _, _, _ -> pendingShadeBlurRadius = -1 } statusBarStateController.addCallback(statusBarStateCallback) } Loading @@ -198,11 +168,7 @@ class NotificationShadeDepthController @Inject constructor( newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion) } if (pendingShadeBlurRadius == newBlur) { return } pendingShadeBlurRadius = newBlur shadeSpring.animateToFinalPosition(newBlur.toFloat()) shadeSpring.animateTo(newBlur) } private fun scheduleUpdate(viewToBlur: View? = null) { Loading @@ -215,19 +181,72 @@ class NotificationShadeDepthController @Inject constructor( } fun updateGlobalDialogVisibility(visibility: Float, dialogView: View) { if (visibility == globalDialogVisibility) { return } globalDialogVisibility = visibility scheduleUpdate(dialogView) globalActionsSpring.animateTo(blurUtils.blurRadiusOfRatio(visibility), dialogView) } override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { IndentingPrintWriter(pw, " ").let { it.println("StatusBarWindowBlurController:") it.increaseIndent() it.println("shadeBlurRadius: $shadeBlurRadius") it.println("shadeRadius: ${shadeSpring.radius}") it.println("globalActionsRadius: ${globalActionsSpring.radius}") it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius") } } /** * Animation helper that smoothly animates the depth using a spring and deals with frame * invalidation. */ inner class DepthAnimation() { /** * Blur radius visible on the UI, in pixels. */ var radius = 0 private set /** * Radius that we're animating to. */ private var pendingRadius = -1 /** * View on {@link Surface} that wants depth. */ private var view: View? = null private var springAnimation = SpringAnimation(this, object : FloatPropertyCompat<DepthAnimation>("blurRadius") { override fun setValue(rect: DepthAnimation?, value: Float) { radius = value.toInt() scheduleUpdate(view) } override fun getValue(rect: DepthAnimation?): Float { return radius.toFloat() } }) init { springAnimation.spring = SpringForce(0.0f) springAnimation.spring.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY springAnimation.spring.stiffness = SpringForce.STIFFNESS_MEDIUM springAnimation.addEndListener { _, _, _, _ -> pendingRadius = -1 } } fun animateTo(newRadius: Int, viewToBlur: View? = null) { if (pendingRadius == newRadius && view == viewToBlur) { return } view = viewToBlur pendingRadius = newRadius springAnimation.animateToFinalPosition(newRadius.toFloat()) } fun finishIfRunning() { if (springAnimation.isRunning) { springAnimation.skipToEnd() } } } } packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +13 −8 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.testing.TestableLooper.RunWithLooper import android.view.Choreographer import android.view.View import android.view.ViewRootImpl import androidx.dynamicanimation.animation.SpringAnimation import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager Loading @@ -35,10 +34,14 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.* import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyString import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) Loading @@ -56,7 +59,8 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var root: View @Mock private lateinit var viewRootImpl: ViewRootImpl @Mock private lateinit var shadeSpring: SpringAnimation @Mock private lateinit var shadeSpring: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var globalActionsSpring: NotificationShadeDepthController.DepthAnimation @JvmField @Rule val mockitoRule = MockitoJUnit.rule() private lateinit var statusBarStateListener: StatusBarStateController.StateListener Loading @@ -76,6 +80,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { keyguardStateController, choreographer, wallpaperManager, notificationShadeWindowController, dumpManager) notificationShadeDepthController.shadeSpring = shadeSpring notificationShadeDepthController.globalActionsSpring = globalActionsSpring notificationShadeDepthController.root = root val captor = ArgumentCaptor.forClass(StatusBarStateController.StateListener::class.java) Loading @@ -92,7 +97,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { fun onPanelExpansionChanged_apliesBlur_ifShade() { notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, false /* tracking */) verify(shadeSpring).animateToFinalPosition(eq(maxBlur.toFloat())) verify(shadeSpring).animateTo(eq(maxBlur), any()) } @Test Loading @@ -102,13 +107,13 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { statusBarState = StatusBarState.KEYGUARD statusBarStateListener.onStateChanged(statusBarState) verify(shadeSpring).animateToFinalPosition(eq(0f)) verify(shadeSpring).animateTo(eq(0), any()) } @Test fun updateGlobalDialogVisibility_schedulesUpdate() { fun updateGlobalDialogVisibility_appliesBlur() { notificationShadeDepthController.updateGlobalDialogVisibility(0.5f, root) verify(choreographer).postFrameCallback(any()) verify(globalActionsSpring).animateTo(eq(maxBlur / 2), safeEq(root)) } private fun <T : Any> safeEq(value: T): T { Loading Loading
packages/SystemUI/src/com/android/systemui/globalactions/GlobalActionsDialog.java +2 −2 Original line number Diff line number Diff line Loading @@ -1849,7 +1849,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, .alpha(1) .translationX(0) .translationY(0) .setDuration(300) .setDuration(450) .setInterpolator(Interpolators.FAST_OUT_SLOW_IN) .setUpdateListener(animation -> { float animatedValue = animation.getAnimatedFraction(); Loading Loading @@ -1878,7 +1878,7 @@ public class GlobalActionsDialog implements DialogInterface.OnDismissListener, .alpha(0) .translationX(mGlobalActionsLayout.getAnimationOffsetX()) .translationY(mGlobalActionsLayout.getAnimationOffsetY()) .setDuration(300) .setDuration(550) .withEndAction(this::completeDismiss) .setInterpolator(new LogAccelerateInterpolator()) .setUpdateListener(animation -> { Loading
packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt +68 −49 Original line number Diff line number Diff line Loading @@ -67,32 +67,9 @@ class NotificationShadeDepthController @Inject constructor( private var updateScheduled: Boolean = false private var shadeExpansion = 0f @VisibleForTesting var shadeSpring = SpringAnimation(this, object : FloatPropertyCompat<NotificationShadeDepthController>("shadeBlurRadius") { override fun setValue(rect: NotificationShadeDepthController?, value: Float) { shadeBlurRadius = value.toInt() } override fun getValue(rect: NotificationShadeDepthController?): Float { return shadeBlurRadius.toFloat() } }) private val zoomInterpolator = Interpolators.ACCELERATE_DECELERATE /** * Radius that we're animating to. */ private var pendingShadeBlurRadius = -1 /** * Shade blur radius on the current frame. */ private var shadeBlurRadius = 0 set(value) { if (field == value) return field = value scheduleUpdate() } var shadeSpring = DepthAnimation() @VisibleForTesting var globalActionsSpring = DepthAnimation() /** * Blur radius of the wake-up animation on this frame. Loading @@ -103,7 +80,6 @@ class NotificationShadeDepthController @Inject constructor( field = value scheduleUpdate() } private var globalDialogVisibility = 0f /** * Callback that updates the window blur value and is called only once per frame. Loading @@ -111,12 +87,9 @@ class NotificationShadeDepthController @Inject constructor( private val updateBlurCallback = Choreographer.FrameCallback { updateScheduled = false val blur = max(shadeBlurRadius, max(wakeAndUnlockBlurRadius, blurUtils.blurRadiusOfRatio(globalDialogVisibility))) val blur = max(max(shadeSpring.radius, wakeAndUnlockBlurRadius), globalActionsSpring.radius) blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur) val rawZoom = max(blurUtils.ratioOfBlurRadius(blur), globalDialogVisibility) wallpaperManager.setWallpaperZoomOut(root.windowToken, zoomInterpolator.getInterpolation(rawZoom)) wallpaperManager.setWallpaperZoomOut(root.windowToken, blurUtils.ratioOfBlurRadius(blur)) notificationShadeWindowController.setBackgroundBlurRadius(blur) } Loading Loading @@ -163,8 +136,9 @@ class NotificationShadeDepthController @Inject constructor( } override fun onDozingChanged(isDozing: Boolean) { if (isDozing && shadeSpring.isRunning) { shadeSpring.skipToEnd() if (isDozing) { shadeSpring.finishIfRunning() globalActionsSpring.finishIfRunning() } } } Loading @@ -174,10 +148,6 @@ class NotificationShadeDepthController @Inject constructor( if (WAKE_UP_ANIMATION_ENABLED) { keyguardStateController.addCallback(keyguardStateCallback) } shadeSpring.spring = SpringForce(0.0f) shadeSpring.spring.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY shadeSpring.spring.stiffness = SpringForce.STIFFNESS_LOW shadeSpring.addEndListener { _, _, _, _ -> pendingShadeBlurRadius = -1 } statusBarStateController.addCallback(statusBarStateCallback) } Loading @@ -198,11 +168,7 @@ class NotificationShadeDepthController @Inject constructor( newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion) } if (pendingShadeBlurRadius == newBlur) { return } pendingShadeBlurRadius = newBlur shadeSpring.animateToFinalPosition(newBlur.toFloat()) shadeSpring.animateTo(newBlur) } private fun scheduleUpdate(viewToBlur: View? = null) { Loading @@ -215,19 +181,72 @@ class NotificationShadeDepthController @Inject constructor( } fun updateGlobalDialogVisibility(visibility: Float, dialogView: View) { if (visibility == globalDialogVisibility) { return } globalDialogVisibility = visibility scheduleUpdate(dialogView) globalActionsSpring.animateTo(blurUtils.blurRadiusOfRatio(visibility), dialogView) } override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>) { IndentingPrintWriter(pw, " ").let { it.println("StatusBarWindowBlurController:") it.increaseIndent() it.println("shadeBlurRadius: $shadeBlurRadius") it.println("shadeRadius: ${shadeSpring.radius}") it.println("globalActionsRadius: ${globalActionsSpring.radius}") it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius") } } /** * Animation helper that smoothly animates the depth using a spring and deals with frame * invalidation. */ inner class DepthAnimation() { /** * Blur radius visible on the UI, in pixels. */ var radius = 0 private set /** * Radius that we're animating to. */ private var pendingRadius = -1 /** * View on {@link Surface} that wants depth. */ private var view: View? = null private var springAnimation = SpringAnimation(this, object : FloatPropertyCompat<DepthAnimation>("blurRadius") { override fun setValue(rect: DepthAnimation?, value: Float) { radius = value.toInt() scheduleUpdate(view) } override fun getValue(rect: DepthAnimation?): Float { return radius.toFloat() } }) init { springAnimation.spring = SpringForce(0.0f) springAnimation.spring.dampingRatio = SpringForce.DAMPING_RATIO_NO_BOUNCY springAnimation.spring.stiffness = SpringForce.STIFFNESS_MEDIUM springAnimation.addEndListener { _, _, _, _ -> pendingRadius = -1 } } fun animateTo(newRadius: Int, viewToBlur: View? = null) { if (pendingRadius == newRadius && view == viewToBlur) { return } view = viewToBlur pendingRadius = newRadius springAnimation.animateToFinalPosition(newRadius.toFloat()) } fun finishIfRunning() { if (springAnimation.isRunning) { springAnimation.skipToEnd() } } } }
packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt +13 −8 Original line number Diff line number Diff line Loading @@ -22,7 +22,6 @@ import android.testing.TestableLooper.RunWithLooper import android.view.Choreographer import android.view.View import android.view.ViewRootImpl import androidx.dynamicanimation.animation.SpringAnimation import androidx.test.filters.SmallTest import com.android.systemui.SysuiTestCase import com.android.systemui.dump.DumpManager Loading @@ -35,10 +34,14 @@ import org.junit.Rule import org.junit.Test import org.junit.runner.RunWith import org.mockito.ArgumentCaptor import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.eq import org.mockito.Mock import org.mockito.Mockito.* import org.mockito.Mockito.`when` import org.mockito.Mockito.any import org.mockito.Mockito.anyFloat import org.mockito.Mockito.anyString import org.mockito.Mockito.clearInvocations import org.mockito.Mockito.verify import org.mockito.junit.MockitoJUnit @RunWith(AndroidTestingRunner::class) Loading @@ -56,7 +59,8 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { @Mock private lateinit var dumpManager: DumpManager @Mock private lateinit var root: View @Mock private lateinit var viewRootImpl: ViewRootImpl @Mock private lateinit var shadeSpring: SpringAnimation @Mock private lateinit var shadeSpring: NotificationShadeDepthController.DepthAnimation @Mock private lateinit var globalActionsSpring: NotificationShadeDepthController.DepthAnimation @JvmField @Rule val mockitoRule = MockitoJUnit.rule() private lateinit var statusBarStateListener: StatusBarStateController.StateListener Loading @@ -76,6 +80,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { keyguardStateController, choreographer, wallpaperManager, notificationShadeWindowController, dumpManager) notificationShadeDepthController.shadeSpring = shadeSpring notificationShadeDepthController.globalActionsSpring = globalActionsSpring notificationShadeDepthController.root = root val captor = ArgumentCaptor.forClass(StatusBarStateController.StateListener::class.java) Loading @@ -92,7 +97,7 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { fun onPanelExpansionChanged_apliesBlur_ifShade() { notificationShadeDepthController.onPanelExpansionChanged(1f /* expansion */, false /* tracking */) verify(shadeSpring).animateToFinalPosition(eq(maxBlur.toFloat())) verify(shadeSpring).animateTo(eq(maxBlur), any()) } @Test Loading @@ -102,13 +107,13 @@ class NotificationShadeDepthControllerTest : SysuiTestCase() { statusBarState = StatusBarState.KEYGUARD statusBarStateListener.onStateChanged(statusBarState) verify(shadeSpring).animateToFinalPosition(eq(0f)) verify(shadeSpring).animateTo(eq(0), any()) } @Test fun updateGlobalDialogVisibility_schedulesUpdate() { fun updateGlobalDialogVisibility_appliesBlur() { notificationShadeDepthController.updateGlobalDialogVisibility(0.5f, root) verify(choreographer).postFrameCallback(any()) verify(globalActionsSpring).animateTo(eq(maxBlur / 2), safeEq(root)) } private fun <T : Any> safeEq(value: T): T { Loading