From a429fdbbe6162d071026c97ccd30cdf7eec49037 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 1 May 2019 11:23:52 -0700 Subject: [PATCH 1/2] End window animation to home when handler invalidated We did this already for mCurrentShift, which is used for all animations except home animation. Now we do it for the home animation as well to ensure we are properly cleaned up for the next interaction. Test: Swipe up to home and double tap nav region before animation finishes. Before, this would return to the app you swiped up from but was in a broken state where subsequent swipes were ignored. Now we jump to the home screen and remain there. Bug: 130802487 Change-Id: I98a2e71a1791f5580451c94a35af98da193ff12f --- .../WindowTransformSwipeHandler.java | 28 +++++++++++++-- .../quickstep/util/RectFSpringAnim.java | 36 +++++++++++++------ .../launcher3/anim/FlingSpringAnim.java | 14 ++++++-- 3 files changed, 61 insertions(+), 17 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 3797e87995..7076f58d94 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -220,6 +220,8 @@ public class WindowTransformSwipeHandler protected Runnable mGestureEndCallback; protected GestureEndTarget mGestureEndTarget; + // Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise + private RunningWindowAnim mRunningWindowAnim; private boolean mIsShelfPeeking; private DeviceProfile mDp; private int mTransitionDragLength; @@ -805,7 +807,7 @@ public class WindowTransformSwipeHandler @UiThread private InputConsumer createNewInputProxyHandler() { - mCurrentShift.finishAnimation(); + endRunningWindowAnim(); if (mLauncherTransitionController != null) { mLauncherTransitionController.getAnimationPlayer().end(); } @@ -817,6 +819,12 @@ public class WindowTransformSwipeHandler return OverviewInputConsumer.newInstance(mActivityControlHelper, null, true); } + private void endRunningWindowAnim() { + if (mRunningWindowAnim != null) { + mRunningWindowAnim.end(); + } + } + @UiThread private void handleNormalGestureEnd(float endVelocity, boolean isFling, PointF velocity, boolean isCancel) { @@ -984,6 +992,7 @@ public class WindowTransformSwipeHandler } }); windowAnim.start(velocityPxPerMs); + mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); mLauncherTransitionController = null; } else { ValueAnimator windowAnim = mCurrentShift.animateToValue(start, end); @@ -1002,6 +1011,7 @@ public class WindowTransformSwipeHandler } }); windowAnim.start(); + mRunningWindowAnim = RunningWindowAnim.wrap(windowAnim); } // Always play the entire launcher animation when going home, since it is separate from // the animation that has been controlled thus far. @@ -1111,7 +1121,7 @@ public class WindowTransformSwipeHandler false /* animate */, true /* freezeTaskList */); }); } - TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", false); + TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true); doLogGesture(NEW_TASK); reset(); } @@ -1133,7 +1143,7 @@ public class WindowTransformSwipeHandler } private void invalidateHandler() { - mCurrentShift.finishAnimation(); + endRunningWindowAnim(); if (mGestureEndCallback != null) { mGestureEndCallback.run(); @@ -1281,4 +1291,16 @@ public class WindowTransformSwipeHandler return app.isNotInRecents || app.activityType == RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME; } + + private interface RunningWindowAnim { + void end(); + + static RunningWindowAnim wrap(Animator animator) { + return animator::end; + } + + static RunningWindowAnim wrap(RectFSpringAnim rectFSpringAnim) { + return rectFSpringAnim::end; + } + } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java index 2edeb3aec2..7159e7c721 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/RectFSpringAnim.java @@ -23,6 +23,9 @@ import android.graphics.PointF; import android.graphics.RectF; import android.util.FloatProperty; +import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener; +import androidx.dynamicanimation.animation.FloatPropertyCompat; + import com.android.launcher3.Utilities; import com.android.launcher3.anim.AnimationSuccessListener; import com.android.launcher3.anim.FlingSpringAnim; @@ -30,9 +33,6 @@ import com.android.launcher3.anim.FlingSpringAnim; import java.util.ArrayList; import java.util.List; -import androidx.dynamicanimation.animation.DynamicAnimation.OnAnimationEndListener; -import androidx.dynamicanimation.animation.FloatPropertyCompat; - /** * Applies spring forces to animate from a starting rect to a target rect, * while providing update callbacks to the caller. @@ -98,6 +98,10 @@ public class RectFSpringAnim { private float mCurrentCenterX; private float mCurrentCenterY; private float mCurrentScaleProgress; + private FlingSpringAnim mRectXAnim; + private FlingSpringAnim mRectYAnim; + private ValueAnimator mRectScaleAnim; + private boolean mAnimsStarted; private boolean mRectXAnimEnded; private boolean mRectYAnimEnded; private boolean mRectScaleAnimEnded; @@ -127,15 +131,15 @@ public class RectFSpringAnim { mRectYAnimEnded = true; maybeOnEnd(); }); - FlingSpringAnim rectXAnim = new FlingSpringAnim(this, RECT_CENTER_X, mCurrentCenterX, + mRectXAnim = new FlingSpringAnim(this, RECT_CENTER_X, mCurrentCenterX, mTargetRect.centerX(), velocityPxPerMs.x * 1000, onXEndListener); - FlingSpringAnim rectYAnim = new FlingSpringAnim(this, RECT_CENTER_Y, mCurrentCenterY, + mRectYAnim = new FlingSpringAnim(this, RECT_CENTER_Y, mCurrentCenterY, mTargetRect.centerY(), velocityPxPerMs.y * 1000, onYEndListener); - ValueAnimator rectScaleAnim = ObjectAnimator.ofPropertyValuesHolder(this, + mRectScaleAnim = ObjectAnimator.ofPropertyValuesHolder(this, PropertyValuesHolder.ofFloat(RECT_SCALE_PROGRESS, 1)) .setDuration(RECT_SCALE_DURATION); - rectScaleAnim.addListener(new AnimationSuccessListener() { + mRectScaleAnim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { mRectScaleAnimEnded = true; @@ -143,14 +147,23 @@ public class RectFSpringAnim { } }); - rectXAnim.start(); - rectYAnim.start(); - rectScaleAnim.start(); + mRectXAnim.start(); + mRectYAnim.start(); + mRectScaleAnim.start(); + mAnimsStarted = true; for (Animator.AnimatorListener animatorListener : mAnimatorListeners) { animatorListener.onAnimationStart(null); } } + public void end() { + if (mAnimsStarted) { + mRectXAnim.end(); + mRectYAnim.end(); + mRectScaleAnim.end(); + } + } + private void onUpdate() { if (!mOnUpdateListeners.isEmpty()) { float currentWidth = Utilities.mapRange(mCurrentScaleProgress, mStartRect.width(), @@ -166,7 +179,8 @@ public class RectFSpringAnim { } private void maybeOnEnd() { - if (mRectXAnimEnded && mRectYAnimEnded && mRectScaleAnimEnded) { + if (mAnimsStarted && mRectXAnimEnded && mRectYAnimEnded && mRectScaleAnimEnded) { + mAnimsStarted = false; for (Animator.AnimatorListener animatorListener : mAnimatorListeners) { animatorListener.onAnimationEnd(null); } diff --git a/src/com/android/launcher3/anim/FlingSpringAnim.java b/src/com/android/launcher3/anim/FlingSpringAnim.java index 3d21d82a25..45d49e8706 100644 --- a/src/com/android/launcher3/anim/FlingSpringAnim.java +++ b/src/com/android/launcher3/anim/FlingSpringAnim.java @@ -34,6 +34,7 @@ public class FlingSpringAnim { private static final float SPRING_DAMPING = SpringForce.DAMPING_RATIO_LOW_BOUNCY; private final FlingAnimation mFlingAnim; + private SpringAnimation mSpringAnim; public FlingSpringAnim(K object, FloatPropertyCompat property, float startPosition, float targetPosition, float startVelocity, OnAnimationEndListener onEndListener) { @@ -44,17 +45,24 @@ public class FlingSpringAnim { .setMinValue(Math.min(startPosition, targetPosition)) .setMaxValue(Math.max(startPosition, targetPosition)); mFlingAnim.addEndListener(((animation, canceled, value, velocity) -> { - SpringAnimation springAnim = new SpringAnimation(object, property) + mSpringAnim = new SpringAnimation(object, property) .setStartVelocity(velocity) .setSpring(new SpringForce(targetPosition) .setStiffness(SPRING_STIFFNESS) .setDampingRatio(SPRING_DAMPING)); - springAnim.addEndListener(onEndListener); - springAnim.start(); + mSpringAnim.addEndListener(onEndListener); + mSpringAnim.start(); })); } public void start() { mFlingAnim.start(); } + + public void end() { + mFlingAnim.cancel(); + if (mSpringAnim.canSkipToEnd()) { + mSpringAnim.skipToEnd(); + } + } } From 1a468145abf426ce1a5de3f14981025146c138b7 Mon Sep 17 00:00:00 2001 From: Tony Wickham Date: Wed, 1 May 2019 17:40:57 -0700 Subject: [PATCH 2/2] Allow touches on launcher while animating to home Previously we only proxied if the end target was recents (now we do it for home as well) and only proxied to the controllers, not to all views. We still only proxy to controllers for touches in the nav bar, but otherwise we dispatch touches through normal view hierarchy. Tests while animating home: - Swipe down for notifications - Swipe up for all apps - Long press icon or wallpaper for shortcuts - Tap a folder to open it - Tap an icon to launch it (currently no animation plays, looking into it separately) Bug: 131775822 Change-Id: I705b7a657b6d17bc0e24ed4fb44ecfb0f319e942 --- .../android/quickstep/OverviewInputConsumer.java | 16 ++++++++++++---- .../quickstep/WindowTransformSwipeHandler.java | 5 ++++- 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java index b48e3de856..bafc367c80 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/OverviewInputConsumer.java @@ -22,13 +22,15 @@ import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SY import android.view.KeyEvent; import android.view.MotionEvent; +import androidx.annotation.Nullable; + import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.Utilities; import com.android.launcher3.views.BaseDragLayer; import com.android.systemui.shared.system.ActivityManagerWrapper; import com.android.systemui.shared.system.InputMonitorCompat; -import androidx.annotation.Nullable; +import java.util.function.Predicate; /** * Input consumer for handling touch on the recents/Launcher activity. @@ -42,6 +44,7 @@ public class OverviewInputConsumer private final int[] mLocationOnScreen = new int[2]; private final boolean mProxyTouch; + private final Predicate mEventReceiver; private final boolean mStartingInActivityBounds; private boolean mTargetHandledTouch; @@ -53,10 +56,15 @@ public class OverviewInputConsumer mStartingInActivityBounds = startingInActivityBounds; mTarget = activity.getDragLayer(); - if (!startingInActivityBounds) { + if (startingInActivityBounds) { + mEventReceiver = mTarget::dispatchTouchEvent; + mProxyTouch = true; + } else { + // Only proxy touches to controllers if we are starting touch from nav bar. + mEventReceiver = mTarget::proxyTouchEvent; mTarget.getLocationOnScreen(mLocationOnScreen); + mProxyTouch = mTarget.prepareProxyEventStarting(); } - mProxyTouch = mTarget.prepareProxyEventStarting(); } @Override @@ -80,7 +88,7 @@ public class OverviewInputConsumer ev.setEdgeFlags(flags | Utilities.EDGE_NAV_BAR); } ev.offsetLocation(-mLocationOnScreen[0], -mLocationOnScreen[1]); - boolean handled = mTarget.proxyTouchEvent(ev); + boolean handled = mEventReceiver.test(ev); ev.offsetLocation(mLocationOnScreen[0], mLocationOnScreen[1]); ev.setEdgeFlags(flags); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java index 7076f58d94..5783f603a8 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/WindowTransformSwipeHandler.java @@ -906,12 +906,15 @@ public class WindowTransformSwipeHandler } } + if (endTarget.isLauncher) { + mRecentsAnimationWrapper.enableInputProxy(); + } + if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); } else if (endTarget == RECENTS) { mLiveTileOverlay.startIconAnimation(); - mRecentsAnimationWrapper.enableInputProxy(); if (mRecentsView != null) { duration = Math.max(duration, mRecentsView.getScroller().getDuration()); }