Unblur shade faster when launching apps

Fixes: 152694021
Test: manual, using Notify
Test: atest NotificationShadeDepthControllerTest
Test: atest NotificationShadeDepthControllerTest
Change-Id: Iec9f667bce5ccabd8c6fc1b8d4d000e629f6016a
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
index d7322a0..fd44f04 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationShadeDepthController.kt
@@ -32,6 +32,7 @@
 import com.android.systemui.Interpolators
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.BiometricUnlockController.MODE_WAKE_AND_UNLOCK
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
@@ -68,6 +69,7 @@
     private var notificationAnimator: Animator? = null
     private var updateScheduled: Boolean = false
     private var shadeExpansion = 0f
+    private var ignoreShadeBlurUntilHidden: Boolean = false
     @VisibleForTesting
     var shadeSpring = DepthAnimation()
     @VisibleForTesting
@@ -83,6 +85,26 @@
         }
 
     /**
+     * When launching an app from the shade, the animations progress should affect how blurry the
+     * shade is, overriding the expansion amount.
+     */
+    var notificationLaunchAnimationParams: ActivityLaunchAnimator.ExpandAnimationParameters? = null
+        set(value) {
+            field = value
+            if (value != null) {
+                scheduleUpdate()
+                return
+            }
+
+            if (shadeSpring.radius == 0) {
+                return
+            }
+            ignoreShadeBlurUntilHidden = true
+            shadeSpring.animateTo(0)
+            shadeSpring.finishIfRunning()
+        }
+
+    /**
      * Blur radius of the wake-up animation on this frame.
      */
     private var wakeAndUnlockBlurRadius = 0
@@ -99,9 +121,19 @@
     val updateBlurCallback = Choreographer.FrameCallback {
         updateScheduled = false
 
-        var shadeRadius = max(shadeSpring.radius, wakeAndUnlockBlurRadius)
-        shadeRadius = (shadeRadius * (1f - brightnessMirrorSpring.ratio)).toInt()
-        val blur = max(shadeRadius, globalActionsSpring.radius)
+        var shadeRadius = max(shadeSpring.radius, wakeAndUnlockBlurRadius).toFloat()
+        shadeRadius *= 1f - brightnessMirrorSpring.ratio
+        val launchProgress = notificationLaunchAnimationParams?.linearProgress ?: 0f
+        shadeRadius *= (1f - launchProgress) * (1f - launchProgress)
+
+        if (ignoreShadeBlurUntilHidden) {
+            if (shadeRadius == 0f) {
+                ignoreShadeBlurUntilHidden = false
+            } else {
+                shadeRadius = 0f
+            }
+        }
+        val blur = max(shadeRadius.toInt(), globalActionsSpring.radius)
         blurUtils.applyBlur(blurRoot?.viewRootImpl ?: root.viewRootImpl, blur)
         try {
             wallpaperManager.setWallpaperZoomOut(root.windowToken,
@@ -187,7 +219,6 @@
         if (statusBarStateController.state == StatusBarState.SHADE) {
             newBlur = blurUtils.blurRadiusOfRatio(shadeExpansion)
         }
-
         shadeSpring.animateTo(newBlur)
     }
 
@@ -212,6 +243,9 @@
             it.println("globalActionsRadius: ${globalActionsSpring.radius}")
             it.println("brightnessMirrorRadius: ${brightnessMirrorSpring.radius}")
             it.println("wakeAndUnlockBlur: $wakeAndUnlockBlurRadius")
+            it.println("notificationLaunchAnimationProgress: " +
+                    "${notificationLaunchAnimationParams?.linearProgress}")
+            it.println("ignoreShadeBlurUntilHidden: $ignoreShadeBlurUntilHidden")
         }
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
index 7c06157..6aef6b4 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimator.java
@@ -34,6 +34,7 @@
 
 import com.android.internal.policy.ScreenDecorationsUtils;
 import com.android.systemui.Interpolators;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.CollapsedStatusBarFragment;
@@ -57,6 +58,7 @@
     private final NotificationListContainer mNotificationContainer;
     private final float mWindowCornerRadius;
     private final NotificationShadeWindowViewController mNotificationShadeWindowViewController;
+    private final NotificationShadeDepthController mDepthController;
     private Callback mCallback;
     private final Runnable mTimeoutRunnable = () -> {
         setAnimationPending(false);
@@ -70,9 +72,11 @@
             NotificationShadeWindowViewController notificationShadeWindowViewController,
             Callback callback,
             NotificationPanelViewController notificationPanel,
+            NotificationShadeDepthController depthController,
             NotificationListContainer container) {
         mNotificationPanel = notificationPanel;
         mNotificationContainer = container;
+        mDepthController = depthController;
         mNotificationShadeWindowViewController = notificationShadeWindowViewController;
         mCallback = callback;
         mWindowCornerRadius = ScreenDecorationsUtils
@@ -212,7 +216,7 @@
                                 mWindowCornerRadius, progress);
                         applyParamsToWindow(primary);
                         applyParamsToNotification(mParams);
-                        applyParamsToNotificationList(mParams);
+                        applyParamsToNotificationShade(mParams);
                     }
                 });
                 anim.addListener(new AnimatorListenerAdapter() {
@@ -256,14 +260,15 @@
             if (!running) {
                 mCallback.onExpandAnimationFinished(mIsFullScreenLaunch);
                 applyParamsToNotification(null);
-                applyParamsToNotificationList(null);
+                applyParamsToNotificationShade(null);
             }
 
         }
 
-        private void applyParamsToNotificationList(ExpandAnimationParameters params) {
+        private void applyParamsToNotificationShade(ExpandAnimationParameters params) {
             mNotificationContainer.applyExpandAnimationParams(params);
             mNotificationPanel.applyExpandAnimationParams(params);
+            mDepthController.setNotificationLaunchAnimationParams(params);
         }
 
         private void applyParamsToNotification(ExpandAnimationParameters params) {
@@ -295,7 +300,7 @@
     };
 
     public static class ExpandAnimationParameters {
-        float linearProgress;
+        public float linearProgress;
         int[] startPosition;
         float startTranslationZ;
         int left;
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
index ae2c78b..34bca74 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBar.java
@@ -1235,6 +1235,7 @@
         // Set up the initial notification state.
         mActivityLaunchAnimator = new ActivityLaunchAnimator(
                 mNotificationShadeWindowViewController, this, mNotificationPanelViewController,
+                mNotificationShadeDepthControllerLazy.get(),
                 (NotificationListContainer) mStackScroller);
 
         // TODO: inject this.
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
index 1e3636b..6b7a3bf 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/NotificationShadeDepthControllerTest.kt
@@ -26,6 +26,7 @@
 import com.android.systemui.SysuiTestCase
 import com.android.systemui.dump.DumpManager
 import com.android.systemui.plugins.statusbar.StatusBarStateController
+import com.android.systemui.statusbar.notification.ActivityLaunchAnimator
 import com.android.systemui.statusbar.phone.BiometricUnlockController
 import com.android.systemui.statusbar.phone.NotificationShadeWindowController
 import com.android.systemui.statusbar.policy.KeyguardStateController
@@ -43,6 +44,7 @@
 import org.mockito.Mockito.anyString
 import org.mockito.Mockito.clearInvocations
 import org.mockito.Mockito.doThrow
+import org.mockito.Mockito.never
 import org.mockito.Mockito.verify
 import org.mockito.junit.MockitoJUnit
 
@@ -128,6 +130,23 @@
     }
 
     @Test
+    fun updateBlurCallback_setsBlur_whenExpanded() {
+        `when`(shadeSpring.radius).thenReturn(maxBlur)
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(maxBlur))
+    }
+
+    @Test
+    fun updateBlurCallback_appLaunchAnimation_overridesZoom() {
+        `when`(shadeSpring.radius).thenReturn(maxBlur)
+        val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters()
+        animProgress.linearProgress = 1f
+        notificationShadeDepthController.notificationLaunchAnimationParams = animProgress
+        notificationShadeDepthController.updateBlurCallback.doFrame(0)
+        verify(blurUtils).applyBlur(any(), eq(0))
+    }
+
+    @Test
     fun updateBlurCallback_invalidWindow() {
         doThrow(IllegalArgumentException("test exception")).`when`(wallpaperManager)
                 .setWallpaperZoomOut(any(), anyFloat())
@@ -159,6 +178,24 @@
         verify(blurUtils).applyBlur(safeEq(viewRootImpl), eq(0))
     }
 
+    @Test
+    fun setNotificationLaunchAnimationParams_schedulesFrame() {
+        val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters()
+        animProgress.linearProgress = 0.5f
+        notificationShadeDepthController.notificationLaunchAnimationParams = animProgress
+        verify(choreographer).postFrameCallback(
+                eq(notificationShadeDepthController.updateBlurCallback))
+    }
+
+    @Test
+    fun setNotificationLaunchAnimationParams_whennNull_ignoresIfShadeHasNoBlur() {
+        val animProgress = ActivityLaunchAnimator.ExpandAnimationParameters()
+        animProgress.linearProgress = 0.5f
+        `when`(shadeSpring.radius).thenReturn(0)
+        notificationShadeDepthController.notificationLaunchAnimationParams = animProgress
+        verify(shadeSpring, never()).animateTo(anyInt(), any())
+    }
+
     private fun <T : Any> safeEq(value: T): T {
         return eq(value) ?: value
     }
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
index a07cfc3..cdef49d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/ActivityLaunchAnimatorTest.java
@@ -19,7 +19,6 @@
 import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyLong;
 import static org.mockito.Mockito.doAnswer;
-import static org.mockito.Mockito.mock;
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
 
@@ -31,6 +30,7 @@
 import android.view.View;
 
 import com.android.systemui.SysuiTestCase;
+import com.android.systemui.statusbar.NotificationShadeDepthController;
 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow;
 import com.android.systemui.statusbar.notification.stack.NotificationListContainer;
 import com.android.systemui.statusbar.phone.NotificationPanelViewController;
@@ -39,8 +39,12 @@
 
 import org.junit.Assert;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnit;
+import org.mockito.junit.MockitoRule;
 
 @SmallTest
 @RunWith(AndroidTestingRunner.class)
@@ -48,14 +52,22 @@
 public class ActivityLaunchAnimatorTest extends SysuiTestCase {
 
     private ActivityLaunchAnimator mLaunchAnimator;
-    private ActivityLaunchAnimator.Callback mCallback = mock(ActivityLaunchAnimator.Callback.class);
-    private NotificationShadeWindowViewController mNotificationShadeWindowViewController = mock(
-            NotificationShadeWindowViewController.class);
-    private NotificationShadeWindowView mNotificationShadeWindowView = mock(
-            NotificationShadeWindowView.class);
-    private NotificationListContainer mNotificationContainer
-            = mock(NotificationListContainer.class);
-    private ExpandableNotificationRow mRow = mock(ExpandableNotificationRow.class);
+    @Mock
+    private ActivityLaunchAnimator.Callback mCallback;
+    @Mock
+    private NotificationShadeWindowViewController mNotificationShadeWindowViewController;
+    @Mock
+    private NotificationShadeWindowView mNotificationShadeWindowView;
+    @Mock
+    private NotificationListContainer mNotificationContainer;
+    @Mock
+    private ExpandableNotificationRow mRow;
+    @Mock
+    private NotificationShadeDepthController mNotificationShadeDepthController;
+    @Mock
+    private NotificationPanelViewController mNotificationPanelViewController;
+    @Rule
+    public MockitoRule rule = MockitoJUnit.rule();
 
     @Before
     public void setUp() throws Exception {
@@ -66,7 +78,8 @@
         mLaunchAnimator = new ActivityLaunchAnimator(
                 mNotificationShadeWindowViewController,
                 mCallback,
-                mock(NotificationPanelViewController.class),
+                mNotificationPanelViewController,
+                mNotificationShadeDepthController,
                 mNotificationContainer);
 
     }