Merge "Improve unlock motion." into lmp-preview-dev
diff --git a/packages/SystemUI/res/values/dimens.xml b/packages/SystemUI/res/values/dimens.xml
index b8f9ad3..836cf82 100644
--- a/packages/SystemUI/res/values/dimens.xml
+++ b/packages/SystemUI/res/values/dimens.xml
@@ -335,4 +335,7 @@
 
     <!-- end margin for multi user switch in expanded quick settings -->
     <dimen name="multi_user_switch_expanded_margin">8dp</dimen>
+
+    <!-- the distance the panel moves up when starting the up motion on Keyguard -->
+    <dimen name="keyguard_panel_move_up_distance">100dp</dimen>
 </resources>
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
index 6a83a5e..db85b14 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardClockPositionAlgorithm.java
@@ -88,13 +88,15 @@
 
     public void run(Result result) {
         int y = getClockY() - mKeyguardStatusHeight/2;
-        float clockAdjustment = getClockYExpansionAdjustment();
+        float topAdjustment = getTopExpansionAdjustment();
         float topPaddingAdjMultiplier = getTopPaddingAdjMultiplier();
-        result.stackScrollerPaddingAdjustment = (int) (clockAdjustment*topPaddingAdjMultiplier);
+        result.stackScrollerPaddingAdjustment = (int) (topAdjustment*topPaddingAdjMultiplier);
         int clockNotificationsPadding = getClockNotificationsPadding()
                 + result.stackScrollerPaddingAdjustment;
         int padding = y + clockNotificationsPadding;
-        y += clockAdjustment;
+        if (mNotificationCount == 0) {
+            y += topAdjustment;
+        }
         result.clockY = y;
         result.stackScrollerPadding = mKeyguardStatusHeight + padding;
         result.clockAlpha = getClockAlpha(result.stackScrollerPadding
@@ -117,8 +119,8 @@
         return (int) (getClockYFraction() * mHeight);
     }
 
-    private float getClockYExpansionAdjustment() {
-        float rubberbandFactor = getClockYExpansionRubberbandFactor();
+    private float getTopExpansionAdjustment() {
+        float rubberbandFactor = getTopExpansionRubberbandFactor();
         float value = (rubberbandFactor * (mMaxPanelHeight - mExpandedHeight));
         float t = value / mMaxPanelHeight;
         float slowedDownValue = -sSlowDownInterpolator.getInterpolation(t) * SLOW_DOWN_FACTOR
@@ -130,7 +132,7 @@
         }
     }
 
-    private float getClockYExpansionRubberbandFactor() {
+    private float getTopExpansionRubberbandFactor() {
         float t = getNotificationAmountT();
         t = Math.min(t, 1.0f);
         t = (float) Math.pow(t, 0.3f);
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
index eb8bce0..5c686fc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/NotificationPanelView.java
@@ -696,6 +696,11 @@
     }
 
     @Override
+    protected boolean hasNotifications() {
+        return mNotificationStackScroller.getNotGoneChildCount() > 0;
+    }
+
+    @Override
     protected int getMaxPanelHeight() {
         // TODO: Figure out transition for collapsing when QS is open, adjust height here.
         int emptyBottomMargin = mNotificationStackScroller.getEmptyBottomMargin();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
index 1f3098d..08305dc 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PanelView.java
@@ -30,6 +30,8 @@
 import android.view.ViewTreeObserver;
 import android.view.animation.AnimationUtils;
 import android.view.animation.Interpolator;
+import android.view.animation.LinearInterpolator;
+import android.view.animation.PathInterpolator;
 import android.widget.FrameLayout;
 
 import com.android.systemui.R;
@@ -43,6 +45,8 @@
     public static final boolean DEBUG = PanelBar.DEBUG;
     public static final String TAG = PanelView.class.getSimpleName();
 
+    private static final long KEYGUARD_MOVE_UP_LENGTH = 300;
+
     private final void logf(String fmt, Object... args) {
         Log.v(TAG, (mViewName != null ? (mViewName + ": ") : "") + String.format(fmt, args));
     }
@@ -62,6 +66,9 @@
     protected int mTouchSlop;
     protected boolean mHintAnimationRunning;
     private boolean mOverExpandedBeforeFling;
+    private boolean mKeyguardMovingUp;
+    private int mKeyguardMoveUpDistance;
+    private float mKeyguardFingerHeight;
 
     private ValueAnimator mHeightAnimator;
     private ObjectAnimator mPeekAnimator;
@@ -82,6 +89,8 @@
 
     private Interpolator mLinearOutSlowInInterpolator;
     private Interpolator mBounceInterpolator;
+    private Interpolator mKeyguardMoveUpInterpolator;
+    private final Interpolator mLinearInterpolator = new LinearInterpolator();
 
     protected void onExpandingFinished() {
         mBar.onExpandingFinished();
@@ -109,6 +118,7 @@
         mLinearOutSlowInInterpolator =
                 AnimationUtils.loadInterpolator(context, android.R.interpolator.fast_out_slow_in);
         mBounceInterpolator = new BounceInterpolator();
+        mKeyguardMoveUpInterpolator = new PathInterpolator(0.6f, 0f, 0.4f, 1f);
     }
 
     protected void loadDimens() {
@@ -120,6 +130,8 @@
         mTouchSlop = configuration.getScaledTouchSlop();
         mHintDistance = res.getDimension(R.dimen.hint_move_distance);
         mEdgeTapAreaWidth = res.getDimensionPixelSize(R.dimen.edge_tap_area_width);
+        mKeyguardMoveUpDistance =
+                res.getDimensionPixelSize(R.dimen.keyguard_panel_move_up_distance);
     }
 
     private void trackMovement(MotionEvent event) {
@@ -217,8 +229,13 @@
                     mJustPeeked = false;
                 }
                 if (!mJustPeeked && (!waitForTouchSlop || mTracking)) {
-                    setExpandedHeightInternal(newHeight);
-                    mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+                    if (mStatusBar.getBarState() == StatusBarState.KEYGUARD &&
+                            !hasNotifications()) {
+                        setExpandedHeightKeyguard(newHeight);
+                    } else {
+                        setExpandedHeightInternal(newHeight);
+                        mBar.panelExpansionChanged(PanelView.this, mExpandedFraction);
+                    }
                 }
 
                 trackMovement(event);
@@ -247,10 +264,56 @@
         return !waitForTouchSlop || mTracking;
     }
 
+    protected abstract boolean hasNotifications();
+
+    private void setExpandedHeightKeyguard(float newHeight) {
+        mKeyguardFingerHeight = newHeight;
+        if (newHeight < getMaxPanelHeight() && !mKeyguardMovingUp) {
+            mKeyguardMovingUp = true;
+            ValueAnimator anim = createHeightAnimator(
+                    getMaxPanelHeight() - mKeyguardMoveUpDistance);
+            anim.setDuration(KEYGUARD_MOVE_UP_LENGTH);
+            anim.setInterpolator(mKeyguardMoveUpInterpolator);
+            anim.addListener(new AnimatorListenerAdapter() {
+                @Override
+                public void onAnimationEnd(Animator animation) {
+                    mHeightAnimator = null;
+                }
+            });
+            mHeightAnimator = anim;
+            anim.start();
+            postOnAnimationDelayed(new Runnable() {
+                @Override
+                public void run() {
+                    if (mKeyguardFingerHeight < mExpandedHeight && mHeightAnimator != null
+                            && mKeyguardMovingUp) {
+                        mHeightAnimator.cancel();
+                        float target = getMaxPanelHeight() - 1.75f * mKeyguardMoveUpDistance;
+                        float diff = mExpandedHeight - target;
+                        ValueAnimator anim = createHeightAnimator(target);
+                        float velocity = 2.5f * mKeyguardMoveUpDistance /
+                                (KEYGUARD_MOVE_UP_LENGTH / 1000f);
+                        anim.setInterpolator(mLinearInterpolator);
+                        anim.setDuration(Math.max(0, (long) (diff / velocity * 1000f)));
+                        anim.addListener(new AnimatorListenerAdapter() {
+                            @Override
+                            public void onAnimationEnd(Animator animation) {
+                                mHeightAnimator = null;
+                            }
+                        });
+                        mHeightAnimator = anim;
+                        anim.start();
+                    }
+                }
+            }, KEYGUARD_MOVE_UP_LENGTH / 2);
+        }
+    }
+
     protected abstract boolean hasConflictingGestures();
 
     protected void onTrackingStopped(boolean expand) {
         mTracking = false;
+        mKeyguardMovingUp = false;
         mBar.onTrackingStopped(PanelView.this, expand);
     }
 
@@ -381,6 +444,9 @@
 
     protected void fling(float vel, boolean expand) {
         cancelPeek();
+        if (mHeightAnimator != null) {
+            mHeightAnimator.cancel();
+        }
         float target = expand ? getMaxPanelHeight() : 0.0f;
         if (target == mExpandedHeight || getOverExpansionAmount() > 0f && expand) {
             onExpandingFinished();