Standardize quickstep velocities

- Compute velocities as px/ms from VelocityTracker, instead of
  computing px/s and dividing by 1000 in various places
- Use quickstep_fling_threshold_speed in TriggerSwipeUpTouchTracker
  instead of ViewConfiguration#getScaledMinimumFlingVelocity
- Check MotionPauseDetector to determine whether a fling is
  sufficient to escape after pause, in additon to above threshold

Bug: 159089437
Change-Id: Ib0fae7804e1f008f3b6ab37d6c463352c224b0e4
This commit is contained in:
Tony Wickham
2020-08-31 21:00:59 -07:00
parent 3a89e42237
commit 01e4070836
8 changed files with 56 additions and 33 deletions
+1 -4
View File
@@ -35,16 +35,13 @@
loading full resolution screenshots. -->
<dimen name="recents_fast_fling_velocity">600dp</dimen>
<!-- These velocities are in dp / s -->
<dimen name="quickstep_fling_threshold_velocity">500dp</dimen>
<dimen name="quickstep_fling_min_velocity">250dp</dimen>
<!-- These speeds are in dp / ms -->
<dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
<dimen name="motion_pause_detector_speed_slow">0.15dp</dimen>
<dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
<dimen name="motion_pause_detector_speed_fast">1.4dp</dimen>
<dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen>
<dimen name="quickstep_fling_threshold_speed">0.5dp</dimen>
<!-- Launcher app transition -->
<dimen name="content_trans_y">50dp</dimen>
@@ -75,6 +75,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
private final float mMotionPauseMinDisplacement;
private boolean mDidTouchStartInNavBar;
private boolean mStartedOverview;
private boolean mReachedOverview;
// The last recorded displacement before we reached overview.
private PointF mStartDisplacement = new PointF();
@@ -138,6 +139,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
mFromState.getOverviewScrimAlpha(mLauncher),
mToState.getOverviewScrimAlpha(mLauncher));
}
mStartedOverview = false;
mReachedOverview = false;
mOverviewResistYAnim = null;
}
@@ -152,7 +154,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
@Override
public void onDragEnd(float velocity) {
if (mMotionPauseDetector.isPaused() && handlingOverviewAnim()) {
if (mStartedOverview) {
goToOverviewOrHomeOnDragEnd(velocity);
} else {
super.onDragEnd(velocity);
@@ -199,6 +201,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
maybeSwipeInteractionToOverviewComplete();
});
});
mStartedOverview = true;
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
}
@@ -219,7 +222,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
if (TestProtocol.sDebugTracing) {
Log.d(TestProtocol.PAUSE_NOT_DETECTED, "NoButtonNavbarToOverviewTouchController");
}
if (mMotionPauseDetector.isPaused()) {
if (mStartedOverview) {
if (!mReachedOverview) {
mStartDisplacement.set(xDisplacement, yDisplacement);
mStartY = event.getY();
@@ -234,8 +237,6 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
* OVERVIEW_MOVEMENT_FACTOR);
}
}
// Stay in Overview.
return true;
}
float upDisplacement = -yDisplacement;
@@ -243,13 +244,12 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
|| upDisplacement < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(event);
return super.onDrag(yDisplacement, xDisplacement, event);
// Stay in Overview.
return mStartedOverview || super.onDrag(yDisplacement, xDisplacement, event);
}
private void goToOverviewOrHomeOnDragEnd(float velocity) {
float velocityDp = dpiFromPx(velocity);
boolean isFling = Math.abs(velocityDp) > 1;
boolean goToHomeInsteadOfOverview = isFling;
boolean goToHomeInsteadOfOverview = !mMotionPauseDetector.isPaused();
if (goToHomeInsteadOfOverview) {
new OverviewToHomeAnim(mLauncher, ()-> onSwipeInteractionCompleted(NORMAL, Touch.FLING))
.animateWithVelocity(velocity);
@@ -751,8 +751,9 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
@UiThread
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
boolean isFling = mGestureStarted && Math.abs(endVelocity) > flingThreshold;
.getDimension(R.dimen.quickstep_fling_threshold_speed);
boolean isFling = mGestureStarted && !mIsMotionPaused
&& Math.abs(endVelocity) > flingThreshold;
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
mLogAction = isFling ? Touch.FLING : Touch.SWIPE;
@@ -867,7 +868,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !willGoToNewTaskOnSwipeUp) {
endTarget = HOME;
} else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp && !mIsMotionPaused) {
} else if (mDeviceState.isFullyGesturalNavMode() && isSwipeUp) {
// If swiping at a diagonal, base end target on the faster velocity.
endTarget = NEW_TASK;
} else if (isSwipeUp) {
@@ -887,7 +888,6 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
@UiThread
private void handleNormalGestureEnd(float endVelocity, boolean isFling, PointF velocity,
boolean isCancel) {
PointF velocityPxPerMs = new PointF(velocity.x / 1000, velocity.y / 1000);
long duration = MAX_SWIPE_DURATION;
float currentShift = mCurrentShift.value;
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
@@ -902,14 +902,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
startShift = currentShift;
interpolator = endTarget == RECENTS ? OVERSHOOT_1_2 : DEACCEL;
} else {
startShift = Utilities.boundToRange(currentShift - velocityPxPerMs.y
startShift = Utilities.boundToRange(currentShift - velocity.y
* getSingleFrameMs(mContext) / mTransitionDragLength, 0, mDragLengthFactor);
float minFlingVelocity = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_min_velocity);
if (Math.abs(endVelocity) > minFlingVelocity && mTransitionDragLength > 0) {
if (mTransitionDragLength > 0) {
if (endTarget == RECENTS && !mDeviceState.isFullyGesturalNavMode()) {
Interpolators.OvershootParams overshoot = new Interpolators.OvershootParams(
startShift, endShift, endShift, endVelocity / 1000,
startShift, endShift, endShift, endVelocity,
mTransitionDragLength, mContext);
endShift = overshoot.end;
interpolator = overshoot.interpolator;
@@ -921,7 +919,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
// we want the page's snap velocity to approximately match the velocity at
// which the user flings, so we scale the duration by a value near to the
// derivative of the scroll interpolator at zero, ie. 2.
long baseDuration = Math.round(Math.abs(distanceToTravel / velocityPxPerMs.y));
long baseDuration = Math.round(Math.abs(distanceToTravel / velocity.y));
duration = Math.min(MAX_SWIPE_DURATION, 2 * baseDuration);
if (endTarget == RECENTS) {
@@ -961,7 +959,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<?>, Q extends
mGestureState.setState(STATE_RECENTS_SCROLLING_FINISHED);
}
animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs);
animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocity);
}
private void doLogGesture(GestureEndTarget endTarget, @Nullable TaskView targetTask) {
@@ -21,6 +21,7 @@ import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.Utilities.squaredTouchSlop;
import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import static com.android.quickstep.AbsSwipeUpHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
@@ -35,7 +36,6 @@ import android.graphics.Point;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators;
@@ -180,12 +180,11 @@ public class DeviceLockedInputConsumer implements InputConsumer,
*/
private void finishTouchTracking(MotionEvent ev) {
if (mThresholdCrossed && ev.getAction() == ACTION_UP) {
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
float velocityY = mVelocityTracker.getYVelocity();
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
.getDimension(R.dimen.quickstep_fling_threshold_speed);
boolean dismissTask;
if (Math.abs(velocityY) > flingThreshold) {
@@ -28,6 +28,7 @@ import static com.android.launcher3.PagedView.DEBUG_FAILED_QUICKSWITCH;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import static com.android.quickstep.GestureState.STATE_OVERSCROLL_WINDOW_CREATED;
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@@ -393,8 +394,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
if (ev.getActionMasked() == ACTION_CANCEL) {
mInteractionHandler.onGestureCancelled();
} else {
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(this).getScaledMaximumFlingVelocity());
mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
float velocity = mNavBarPosition.isRightEdge()
@@ -144,7 +144,6 @@ public class NavBarGestureHandler implements OnTouchListener,
if (mGestureCallback == null || mAssistantGestureActive) {
return;
}
finalVelocity.set(finalVelocity.x / 1000, finalVelocity.y / 1000);
if (mTouchCameFromNavBar) {
mGestureCallback.onNavBarGestureAttempted(wasFling
? HOME_GESTURE_COMPLETED : OVERVIEW_GESTURE_COMPLETED, finalVelocity);
@@ -21,13 +21,14 @@ import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.Utilities.squaredHypot;
import static com.android.launcher3.util.VelocityUtils.PX_PER_MS;
import android.content.Context;
import android.graphics.PointF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import com.android.launcher3.R;
import com.android.launcher3.Utilities;
/**
@@ -50,7 +51,8 @@ public class TriggerSwipeUpTouchTracker {
NavBarPosition navBarPosition, Runnable onInterceptTouch,
OnSwipeUpListener onSwipeUp) {
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
mMinFlingVelocity = ViewConfiguration.get(context).getScaledMinimumFlingVelocity();
mMinFlingVelocity = context.getResources().getDimension(
R.dimen.quickstep_fling_threshold_speed);
mNavBarPosition = navBarPosition;
mDisableHorizontalSwipe = disableHorizontalSwipe;
mOnInterceptTouch = onInterceptTouch;
@@ -130,7 +132,7 @@ public class TriggerSwipeUpTouchTracker {
}
private void onGestureEnd(MotionEvent ev) {
mVelocityTracker.computeCurrentVelocity(1000);
mVelocityTracker.computeCurrentVelocity(PX_PER_MS);
float velocityX = mVelocityTracker.getXVelocity();
float velocityY = mVelocityTracker.getYVelocity();
float velocity = mNavBarPosition.isRightEdge()
@@ -0,0 +1,28 @@
/*
* Copyright (C) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.launcher3.util;
/**
* Contains some constants and functions to standardize velocity usage.
*/
public class VelocityUtils {
/**
* Unit to pass to {@link android.view.VelocityTracker#computeCurrentVelocity(int)}.
*/
public static final int PX_PER_MS = 1;
}