First part of Fixing heads-up notification motion in split shade

This change makes dragging down HUN much better, without all shade breaking during the motion. Also when swiping up HUN now scrims (or other shade elements) are not showing up.

Changes:
- Refactoring logic for calculating transition distance in getMaxPanelHeight to getMaxPanelTransitionDistance and substituting it where appropriate. The most important part is setExpandedHeight which uses that value to calculate expansion fraction. With usual splitShadeTransitionDistance that fraction for HUN would over 1 and almost everything is visible immediately when starting to drag HUN up or down. That’s why when HUN is visible we want to ensure transition distance is bigger and dragging starts at around 0.4 of expansion when no elements are visible.

- HeadsUpTouchHelper was calculating panel scrim min fraction using maxPanelHeight which for split shade returned distance smaller than starting height and panel scrim min fraction was over 1. The fix is to move panel scrim min calculation to NPVC and make it dependent on scrimTransitionDistance. It must be different from getMaxPanelTransitionDistance because scrim expansion fraction is calculated based on scrimTransitionDistance in ScrimShadeTransitionController and resulting fraction would be bigger than minScrimFraction

There are still several bugs with HUN but it’s already looking better now and I’ll file separate bugs for other issues.

Test: NotificationPanelViewControllerTest
Test: swipe up HUN and observer shade elements stay invisible
Fixes: 232349737
Fixes: 234940017
Change-Id: Ie36a9fe8627f0f49168d30db1931aac723e15929
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
index 91c6a9c..28868e1 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationPanelViewController.java
@@ -449,6 +449,8 @@
     private boolean mQsTouchAboveFalsingThreshold;
     private int mQsFalsingThreshold;
 
+    /** Indicates drag starting height when swiping down or up on heads-up notifications */
+    private int mHeadsUpStartHeight;
     private HeadsUpTouchHelper mHeadsUpTouchHelper;
     private boolean mListenForHeadsUp;
     private int mNavigationBarBottomHeight;
@@ -651,6 +653,8 @@
 
     /** The drag distance required to fully expand the split shade. */
     private int mSplitShadeFullTransitionDistance;
+    /** The drag distance required to fully transition scrims. */
+    private int mSplitShadeScrimTransitionDistance;
 
     private final NotificationListContainer mNotificationListContainer;
     private final NotificationStackSizeCalculator mNotificationStackSizeCalculator;
@@ -1064,6 +1068,8 @@
         mLockscreenNotificationQSPadding = mResources.getDimensionPixelSize(
                 R.dimen.notification_side_paddings);
         mUdfpsMaxYBurnInOffset = mResources.getDimensionPixelSize(R.dimen.udfps_burn_in_offset_y);
+        mSplitShadeScrimTransitionDistance = mResources.getDimensionPixelSize(
+                R.dimen.split_shade_scrim_transition_distance);
     }
 
     private void updateViewControllers(KeyguardStatusView keyguardStatusView,
@@ -1354,7 +1360,7 @@
         mQsSizeChangeAnimator.setInterpolator(Interpolators.FAST_OUT_SLOW_IN);
         mQsSizeChangeAnimator.addUpdateListener(animation -> {
             requestScrollerTopPaddingUpdate(false /* animate */);
-            requestPanelHeightUpdate();
+            updateExpandedHeightToMaxHeight();
             int height = (int) mQsSizeChangeAnimator.getAnimatedValue();
             mQs.setHeightOverride(height);
         });
@@ -2134,7 +2140,7 @@
             mMetricsLogger.count(COUNTER_PANEL_OPEN_QS, 1);
             setQsExpandImmediate(true);
             setShowShelfOnly(true);
-            requestPanelHeightUpdate();
+            updateExpandedHeightToMaxHeight();
 
             // Normally, we start listening when the panel is expanded, but here we need to start
             // earlier so the state is already up to date when dragging down.
@@ -2346,7 +2352,7 @@
         // Reset scroll position and apply that position to the expanded height.
         float height = mQsExpansionHeight;
         setQsExpansion(height);
-        requestPanelHeightUpdate();
+        updateExpandedHeightToMaxHeight();
         mNotificationStackScrollLayoutController.checkSnoozeLeavebehind();
 
         // When expanding QS, let's authenticate the user if possible,
@@ -2362,7 +2368,7 @@
         if (changed) {
             mQsExpanded = expanded;
             updateQsState();
-            requestPanelHeightUpdate();
+            updateExpandedHeightToMaxHeight();
             mFalsingCollector.setQsExpanded(expanded);
             mCentralSurfaces.setQsExpanded(expanded);
             mNotificationsQSContainerController.setQsExpanded(expanded);
@@ -3086,16 +3092,7 @@
         int maxHeight;
         if (mQsExpandImmediate || mQsExpanded || mIsExpanding && mQsExpandedWhenExpandingStarted
                 || mPulsing || mSplitShadeEnabled) {
-            if (mSplitShadeEnabled && mBarState == SHADE) {
-                // Max panel height is used to calculate the fraction of the shade expansion.
-                // Traditionally the value is based on the number of notifications.
-                // On split-shade, we want the required distance to be a specific and constant
-                // value, to make sure the expansion motion has the expected speed.
-                // We also only want this on non-lockscreen for now.
-                maxHeight = mSplitShadeFullTransitionDistance;
-            } else {
-                maxHeight = calculatePanelHeightQsExpanded();
-            }
+            maxHeight = calculatePanelHeightQsExpanded();
         } else {
             maxHeight = calculatePanelHeightShade();
         }
@@ -3455,6 +3452,31 @@
     }
 
     @Override
+    public int getMaxPanelTransitionDistance() {
+        // Traditionally the value is based on the number of notifications. On split-shade, we want
+        // the required distance to be a specific and constant value, to make sure the expansion
+        // motion has the expected speed. We also only want this on non-lockscreen for now.
+        if (mSplitShadeEnabled && mBarState == SHADE) {
+            boolean transitionFromHeadsUp =
+                    mHeadsUpManager.isTrackingHeadsUp() || mExpandingFromHeadsUp;
+            // heads-up starting height is too close to mSplitShadeFullTransitionDistance and
+            // when dragging HUN transition is already 90% complete. It makes shade become
+            // immediately visible when starting to drag. We want to set distance so that
+            // nothing is immediately visible when dragging (important for HUN swipe up motion) -
+            // 0.4 expansion fraction is a good starting point.
+            if (transitionFromHeadsUp) {
+                double maxDistance = Math.max(mSplitShadeFullTransitionDistance,
+                        mHeadsUpStartHeight * 2.5);
+                return (int) Math.min(getMaxPanelHeight(), maxDistance);
+            } else {
+                return mSplitShadeFullTransitionDistance;
+            }
+        } else {
+            return getMaxPanelHeight();
+        }
+    }
+
+    @Override
     protected boolean isTrackingBlocked() {
         return mConflictingQsExpansionGesture && mQsExpanded || mBlockingExpansionForCurrentTouch;
     }
@@ -3654,10 +3676,35 @@
     }
 
     /**
+     * Called when heads-up notification is being dragged up or down to indicate what's the starting
+     * height for shade motion
+     */
+    public void setHeadsUpDraggingStartingHeight(int startHeight) {
+        mHeadsUpStartHeight = startHeight;
+        float scrimMinFraction;
+        if (mSplitShadeEnabled) {
+            boolean highHun = mHeadsUpStartHeight * 2.5 > mSplitShadeScrimTransitionDistance;
+            // if HUN height is higher than 40% of predefined transition distance, it means HUN
+            // is too high for regular transition. In that case we need to calculate transition
+            // distance - here we take scrim transition distance as equal to shade transition
+            // distance. It doesn't result in perfect motion - usually scrim transition distance
+            // should be longer - but it's good enough for HUN case.
+            float transitionDistance =
+                    highHun ? getMaxPanelTransitionDistance() : mSplitShadeFullTransitionDistance;
+            scrimMinFraction = mHeadsUpStartHeight / transitionDistance;
+        } else {
+            int transitionDistance = getMaxPanelHeight();
+            scrimMinFraction = transitionDistance > 0f
+                    ? (float) mHeadsUpStartHeight / transitionDistance : 0f;
+        }
+        setPanelScrimMinFraction(scrimMinFraction);
+    }
+
+    /**
      * Sets the minimum fraction for the panel expansion offset. This may be non-zero in certain
      * cases, such as if there's a heads-up notification.
      */
-    public void setPanelScrimMinFraction(float minFraction) {
+    private void setPanelScrimMinFraction(float minFraction) {
         mMinFraction = minFraction;
         mDepthController.setPanelPullDownMinFraction(mMinFraction);
         mScrimController.setPanelScrimMinFraction(mMinFraction);
@@ -4391,7 +4438,7 @@
             if (mKeyguardShowing) {
                 updateMaxDisplayedNotifications(true);
             }
-            requestPanelHeightUpdate();
+            updateExpandedHeightToMaxHeight();
         }
 
         @Override
@@ -4524,7 +4571,7 @@
             if (mQsExpanded && mQsFullyExpanded) {
                 mQsExpansionHeight = mQsMaxExpansionHeight;
                 requestScrollerTopPaddingUpdate(false /* animate */);
-                requestPanelHeightUpdate();
+                updateExpandedHeightToMaxHeight();
             }
             if (mAccessibilityManager.isEnabled()) {
                 mView.setAccessibilityPaneTitle(determineAccessibilityPaneTitle());
@@ -4794,7 +4841,7 @@
             if (mQsExpanded && mQsFullyExpanded) {
                 mQsExpansionHeight = mQsMaxExpansionHeight;
                 requestScrollerTopPaddingUpdate(false /* animate */);
-                requestPanelHeightUpdate();
+                updateExpandedHeightToMaxHeight();
 
                 // Size has changed, start an animation.
                 if (mQsMaxExpansionHeight != oldMaxHeight) {
diff --git a/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java b/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java
index a0076937..c3f1e57 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/PanelViewController.java
@@ -248,7 +248,7 @@
         keyguardStateController.addCallback(new KeyguardStateController.Callback() {
             @Override
             public void onKeyguardFadingAwayChanged() {
-                requestPanelHeightUpdate();
+                updateExpandedHeightToMaxHeight();
             }
         });
         mAmbientState = ambientState;
@@ -730,7 +730,7 @@
         setExpandedHeightInternal(height);
     }
 
-    protected void requestPanelHeightUpdate() {
+    void updateExpandedHeightToMaxHeight() {
         float currentMaxPanelHeight = getMaxPanelHeight();
 
         if (isFullyCollapsed()) {
@@ -753,6 +753,13 @@
         setExpandedHeight(currentMaxPanelHeight);
     }
 
+    /**
+     * Returns drag down distance after which panel should be fully expanded. Usually it's the
+     * same as max panel height but for large screen devices (especially split shade) we might
+     * want to return different value to shorten drag distance
+     */
+    public abstract int getMaxPanelTransitionDistance();
+
     public void setExpandedHeightInternal(float h) {
         if (isNaN(h)) {
             Log.wtf(TAG, "ExpandedHeight set to NaN");
@@ -763,18 +770,15 @@
                         () -> mLatencyTracker.onActionEnd(LatencyTracker.ACTION_EXPAND_PANEL));
                 mExpandLatencyTracking = false;
             }
-            float maxPanelHeight = getMaxPanelHeight();
+            float maxPanelHeight = getMaxPanelTransitionDistance();
             if (mHeightAnimator == null) {
                 // Split shade has its own overscroll logic
                 if (mTracking && !mInSplitShade) {
                     float overExpansionPixels = Math.max(0, h - maxPanelHeight);
                     setOverExpansionInternal(overExpansionPixels, true /* isFromGesture */);
                 }
-                mExpandedHeight = Math.min(h, maxPanelHeight);
-            } else {
-                mExpandedHeight = h;
             }
-
+            mExpandedHeight = Math.min(h, maxPanelHeight);
             // If we are closing the panel and we are almost there due to a slow decelerating
             // interpolator, abort the animation.
             if (mExpandedHeight < 1f && mExpandedHeight != 0f && mClosing) {
@@ -832,7 +836,7 @@
     protected abstract int getMaxPanelHeight();
 
     public void setExpandedFraction(float frac) {
-        setExpandedHeight(getMaxPanelHeight() * frac);
+        setExpandedHeight(getMaxPanelTransitionDistance() * frac);
     }
 
     public float getExpandedHeight() {
@@ -1029,7 +1033,7 @@
         mHeightAnimator = animator;
         if (animator == null && mPanelUpdateWhenAnimatorEnds) {
             mPanelUpdateWhenAnimatorEnds = false;
-            requestPanelHeightUpdate();
+            updateExpandedHeightToMaxHeight();
         }
     }
 
@@ -1421,7 +1425,7 @@
         @Override
         public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft,
                 int oldTop, int oldRight, int oldBottom) {
-            requestPanelHeightUpdate();
+            updateExpandedHeightToMaxHeight();
             mHasLayoutedSinceDown = true;
             if (mUpdateFlingOnLayout) {
                 abortAnimations();
diff --git a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
index afd57da..618c892 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/transition/ScrimShadeTransitionController.kt
@@ -14,6 +14,7 @@
 import com.android.systemui.statusbar.phone.panelstate.PanelState
 import com.android.systemui.statusbar.phone.panelstate.STATE_OPENING
 import com.android.systemui.statusbar.policy.ConfigurationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
 import com.android.systemui.util.LargeScreenUtils
 import java.io.PrintWriter
 import javax.inject.Inject
@@ -28,6 +29,7 @@
     private val scrimController: ScrimController,
     @Main private val resources: Resources,
     private val statusBarStateController: SysuiStatusBarStateController,
+    private val headsUpManager: HeadsUpManager
 ) {
 
     private var inSplitShade = false
@@ -84,7 +86,11 @@
     }
 
     private fun canUseCustomFraction(panelState: Int?) =
-        inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING
+        inSplitShade && isScreenUnlocked() && panelState == STATE_OPENING &&
+                // in case of HUN we can't always use predefined distances to manage scrim
+                // transition because dragDownPxAmount can start from value bigger than
+                // splitShadeScrimTransitionDistance
+                !headsUpManager.isTrackingHeadsUp
 
     private fun isScreenUnlocked() =
         statusBarStateController.currentOrUpcomingState == StatusBarState.SHADE
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
index 6bfb0da..90d0b69 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/HeadsUpTouchHelper.java
@@ -115,9 +115,7 @@
                     mInitialTouchY = y;
                     int startHeight = (int) (mPickedChild.getActualHeight()
                                                 + mPickedChild.getTranslationY());
-                    float maxPanelHeight = mPanel.getMaxPanelHeight();
-                    mPanel.setPanelScrimMinFraction(maxPanelHeight > 0f
-                            ? (float) startHeight / maxPanelHeight : 0f);
+                    mPanel.setHeadsUpDraggingStartingHeight(startHeight);
                     mPanel.startExpandMotion(x, y, true /* startTracking */, startHeight);
                     // This call needs to be after the expansion start otherwise we will get a
                     // flicker of one frame as it's not expanded yet.
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt b/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
index a6160aa..6b7c42e 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/panelstate/PanelExpansionStateManager.kt
@@ -114,8 +114,8 @@
                     "end state=${state.panelStateToString()} " +
                     "f=$fraction " +
                     "expanded=$expanded " +
-                    "tracking=$tracking" +
-                    "drawDownPxAmount=$dragDownPxAmount " +
+                    "tracking=$tracking " +
+                    "dragDownPxAmount=$dragDownPxAmount " +
                     "${if (fullyOpened) " fullyOpened" else ""} " +
                     if (fullyClosed) " fullyClosed" else ""
         )
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
index f267013..eb6a6b4 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/NotificationPanelViewControllerTest.java
@@ -184,6 +184,7 @@
 @TestableLooper.RunWithLooper
 public class NotificationPanelViewControllerTest extends SysuiTestCase {
 
+    private static final int SPLIT_SHADE_FULL_TRANSITION_DISTANCE = 400;
     private static final int NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE = 50;
 
     @Mock
@@ -413,6 +414,8 @@
                 .thenReturn(NOTIFICATION_SCRIM_TOP_PADDING_IN_SPLIT_SHADE);
         when(mResources.getDimensionPixelSize(R.dimen.notification_panel_margin_horizontal))
                 .thenReturn(10);
+        when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
+                .thenReturn(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
         when(mView.getContext()).thenReturn(getContext());
         when(mView.findViewById(R.id.keyguard_header)).thenReturn(mKeyguardStatusBar);
         when(mView.findViewById(R.id.keyguard_user_switcher_view)).thenReturn(mUserSwitcherView);
@@ -751,8 +754,9 @@
     }
 
     @Test
-    public void testSetPanelScrimMinFraction() {
-        mNotificationPanelViewController.setPanelScrimMinFraction(0.5f);
+    public void testSetPanelScrimMinFractionWhenHeadsUpIsDragged() {
+        mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
+                mNotificationPanelViewController.getMaxPanelHeight() / 2);
         verify(mNotificationShadeDepthController).setPanelPullDownMinFraction(eq(0.5f));
     }
 
@@ -1448,40 +1452,47 @@
     }
 
     @Test
-    public void getMaxPanelHeight_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
-        int splitShadeFullTransitionDistance = 123456;
+    public void getMaxPanelTransitionDistance_expanding_inSplitShade_returnsSplitShadeFullTransitionDistance() {
         enableSplitShade(true);
-        setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance);
         mNotificationPanelViewController.expandWithQs();
 
-        int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight();
+        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
 
-        assertThat(maxPanelHeight).isEqualTo(splitShadeFullTransitionDistance);
+        assertThat(maxDistance).isEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
     }
 
     @Test
-    public void getMaxPanelHeight_expandingSplitShade_keyguard_returnsNonSplitShadeValue() {
+    public void getMaxPanelTransitionDistance_inSplitShade_withHeadsUp_returnsBiggerValue() {
+        enableSplitShade(true);
+        mNotificationPanelViewController.expandWithQs();
+        when(mHeadsUpManager.isTrackingHeadsUp()).thenReturn(true);
+        mNotificationPanelViewController.setHeadsUpDraggingStartingHeight(
+                SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
+
+        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
+
+        assertThat(maxDistance).isGreaterThan(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
+    }
+
+    @Test
+    public void getMaxPanelTransitionDistance_expandingSplitShade_keyguard_returnsNonSplitShadeValue() {
         mStatusBarStateController.setState(KEYGUARD);
-        int splitShadeFullTransitionDistance = 123456;
         enableSplitShade(true);
-        setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance);
         mNotificationPanelViewController.expandWithQs();
 
-        int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight();
+        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
 
-        assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance);
+        assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
     }
 
     @Test
-    public void getMaxPanelHeight_expanding_notSplitShade_returnsNonSplitShadeValue() {
-        int splitShadeFullTransitionDistance = 123456;
+    public void getMaxPanelTransitionDistance_expanding_notSplitShade_returnsNonSplitShadeValue() {
         enableSplitShade(false);
-        setSplitShadeFullTransitionDistance(splitShadeFullTransitionDistance);
         mNotificationPanelViewController.expandWithQs();
 
-        int maxPanelHeight = mNotificationPanelViewController.getMaxPanelHeight();
+        int maxDistance = mNotificationPanelViewController.getMaxPanelTransitionDistance();
 
-        assertThat(maxPanelHeight).isNotEqualTo(splitShadeFullTransitionDistance);
+        assertThat(maxDistance).isNotEqualTo(SPLIT_SHADE_FULL_TRANSITION_DISTANCE);
     }
 
     private static MotionEvent createMotionEvent(int x, int y, int action) {
@@ -1507,12 +1518,6 @@
         }
     }
 
-    private void givenViewDetached() {
-        for (View.OnAttachStateChangeListener listener : mOnAttachStateChangeListeners) {
-            listener.onViewDetachedFromWindow(mView);
-        }
-    }
-
     private ConstraintSet.Layout getConstraintSetLayout(@IdRes int id) {
         ConstraintSet constraintSet = new ConstraintSet();
         constraintSet.clone(mNotificationContainerParent);
@@ -1544,12 +1549,6 @@
         mTouchHandler.onTouch(mView, ev);
     }
 
-    private void setSplitShadeFullTransitionDistance(int splitShadeFullTransitionDistance) {
-        when(mResources.getDimensionPixelSize(R.dimen.split_shade_full_transition_distance))
-                .thenReturn(splitShadeFullTransitionDistance);
-        mNotificationPanelViewController.updateResources();
-    }
-
     private void setDozing(boolean dozing, boolean dozingAlwaysOn) {
         when(mDozeParameters.getAlwaysOn()).thenReturn(dozingAlwaysOn);
         mNotificationPanelViewController.setDozing(
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
index baaa447..6be76a6 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/transition/ScrimShadeTransitionControllerTest.kt
@@ -13,6 +13,7 @@
 import com.android.systemui.statusbar.phone.panelstate.STATE_OPEN
 import com.android.systemui.statusbar.phone.panelstate.STATE_OPENING
 import com.android.systemui.statusbar.policy.FakeConfigurationController
+import com.android.systemui.statusbar.policy.HeadsUpManager
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
@@ -28,6 +29,7 @@
     @Mock private lateinit var scrimController: ScrimController
     @Mock private lateinit var dumpManager: DumpManager
     @Mock private lateinit var statusBarStateController: SysuiStatusBarStateController
+    @Mock private lateinit var headsUpManager: HeadsUpManager
     private val configurationController = FakeConfigurationController()
 
     private lateinit var controller: ScrimShadeTransitionController
@@ -42,7 +44,8 @@
                 dumpManager,
                 scrimController,
                 context.resources,
-                statusBarStateController)
+                statusBarStateController,
+                headsUpManager)
 
         controller.onPanelStateChanged(STATE_OPENING)
     }