Merge "Move logic that overrides MotionPauseDetector to callers" into ub-launcher3-qt-dev

This commit is contained in:
Tony Wickham 2019-04-25 00:34:47 +00:00 committed by Android (Google) Code Review
commit d0d39f1769
5 changed files with 45 additions and 54 deletions

View File

@ -28,6 +28,7 @@ import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet; import android.animation.AnimatorSet;
import android.view.HapticFeedbackConstants; import android.view.HapticFeedbackConstants;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.ViewConfiguration;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState; import com.android.launcher3.LauncherState;
@ -44,12 +45,14 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
private static final long PEEK_ANIM_DURATION = 100; private static final long PEEK_ANIM_DURATION = 100;
private final MotionPauseDetector mMotionPauseDetector; private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
private AnimatorSet mPeekAnim; private AnimatorSet mPeekAnim;
public FlingAndHoldTouchController(Launcher l) { public FlingAndHoldTouchController(Launcher l) {
super(l, false /* allowDragToOverview */); super(l, false /* allowDragToOverview */);
mMotionPauseDetector = new MotionPauseDetector(l); mMotionPauseDetector = new MotionPauseDetector(l);
mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
} }
@Override @Override
@ -98,7 +101,8 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
@Override @Override
public boolean onDrag(float displacement, MotionEvent event) { public boolean onDrag(float displacement, MotionEvent event) {
mMotionPauseDetector.addPosition(displacement, 0, event.getEventTime()); mMotionPauseDetector.setDisallowPause(-displacement < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(displacement, event.getEventTime());
return super.onDrag(displacement, event); return super.onDrag(displacement, event);
} }

View File

@ -21,14 +21,14 @@ import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT; import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPLEFT;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT; import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction.UPRIGHT;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE;
import static com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch.SWIPE_NOOP;
import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR; import static com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType.NAVBAR;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.graphics.PointF; import android.graphics.PointF;
@ -40,10 +40,10 @@ import android.view.HapticFeedbackConstants;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.R;
import com.android.launcher3.anim.Interpolators; import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.logging.UserEventDispatcher; import com.android.launcher3.logging.UserEventDispatcher;
import com.android.systemui.shared.recents.ISystemUiProxy; import com.android.systemui.shared.recents.ISystemUiProxy;
import com.android.launcher3.R;
import com.android.systemui.shared.system.InputMonitorCompat; import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.NavigationBarCompat; import com.android.systemui.shared.system.NavigationBarCompat;

View File

@ -21,9 +21,9 @@ import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID; import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.ENTER;
import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.launcher3.util.RaceConditionTracker.EXIT;
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON; import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG; import static com.android.quickstep.TouchInteractionService.TOUCH_INTERACTION_LOG;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
@ -45,6 +45,9 @@ import android.view.VelocityTracker;
import android.view.ViewConfiguration; import android.view.ViewConfiguration;
import android.view.WindowManager; import android.view.WindowManager;
import androidx.annotation.UiThread;
import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions; import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker; import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper; import com.android.launcher3.util.TraceHelper;
@ -62,8 +65,6 @@ import com.android.systemui.shared.system.WindowManagerWrapper;
import java.util.function.Consumer; import java.util.function.Consumer;
import androidx.annotation.UiThread;
/** /**
* Input consumer for handling events originating from an activity other than Launcher * Input consumer for handling events originating from an activity other than Launcher
*/ */
@ -90,6 +91,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback; private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
private final MotionPauseDetector mMotionPauseDetector; private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
private VelocityTracker mVelocityTracker; private VelocityTracker mVelocityTracker;
private WindowTransformSwipeHandler mInteractionHandler; private WindowTransformSwipeHandler mInteractionHandler;
@ -107,8 +109,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
// Slop used to determine when we say that the gesture has started. // Slop used to determine when we say that the gesture has started.
private boolean mPassedTouchSlop; private boolean mPassedTouchSlop;
// TODO: Start displacement should have both x and y // Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
private float mStartDisplacement; private float mStartDisplacement;
private float mStartDisplacementX;
private Handler mMainThreadHandler; private Handler mMainThreadHandler;
private Runnable mCancelRecentsAnimationRunnable = () -> { private Runnable mCancelRecentsAnimationRunnable = () -> {
@ -131,6 +134,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mMode = SysUINavigationMode.getMode(base); mMode = SysUINavigationMode.getMode(base);
mMotionPauseDetector = new MotionPauseDetector(base); mMotionPauseDetector = new MotionPauseDetector(base);
mMotionPauseMinDisplacement = base.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
mOnCompleteCallback = onCompleteCallback; mOnCompleteCallback = onCompleteCallback;
mVelocityTracker = VelocityTracker.obtain(); mVelocityTracker = VelocityTracker.obtain();
mInputMonitorCompat = inputMonitorCompat; mInputMonitorCompat = inputMonitorCompat;
@ -219,6 +224,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
} }
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex)); mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float displacement = getDisplacement(ev); float displacement = getDisplacement(ev);
float displacementX = mLastPos.x - mDownPos.x;
if (!mPassedDragSlop) { if (!mPassedDragSlop) {
if (!mIsDeferredDownTarget) { if (!mIsDeferredDownTarget) {
@ -227,13 +233,13 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
if (Math.abs(displacement) > mDragSlop) { if (Math.abs(displacement) > mDragSlop) {
mPassedDragSlop = true; mPassedDragSlop = true;
mStartDisplacement = displacement; mStartDisplacement = displacement;
mStartDisplacementX = displacementX;
} }
} }
} }
if (!mPassedTouchSlop) { if (!mPassedTouchSlop) {
if (Math.hypot(mLastPos.x - mDownPos.x, mLastPos.y - mDownPos.y) >= if (Math.hypot(displacementX, mLastPos.y - mDownPos.y) >= mTouchSlop) {
mTouchSlop) {
mPassedTouchSlop = true; mPassedTouchSlop = true;
if (mIsDeferredDownTarget) { if (mIsDeferredDownTarget) {
@ -244,6 +250,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
if (!mPassedDragSlop) { if (!mPassedDragSlop) {
mPassedDragSlop = true; mPassedDragSlop = true;
mStartDisplacement = displacement; mStartDisplacement = displacement;
mStartDisplacementX = displacementX;
} }
notifyGestureStarted(); notifyGestureStarted();
} }
@ -254,12 +261,12 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement); mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
if (mMode == Mode.NO_BUTTON) { if (mMode == Mode.NO_BUTTON) {
boolean isLandscape = isNavBarOnLeft() || isNavBarOnRight(); float horizontalDist = Math.abs(displacementX - mStartDisplacementX);
float orthogonalDisplacement = !isLandscape float upDist = -(displacement - mStartDisplacement);
? ev.getX() - mDownPos.x boolean isLikelyToStartNewTask = horizontalDist > upDist;
: ev.getY() - mDownPos.y; mMotionPauseDetector.setDisallowPause(upDist < mMotionPauseMinDisplacement
mMotionPauseDetector.addPosition(displacement, orthogonalDisplacement, || isLikelyToStartNewTask);
ev.getEventTime()); mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
} }
} }
break; break;

View File

@ -38,7 +38,7 @@
<dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen> <dimen name="motion_pause_detector_speed_very_slow">0.0285dp</dimen>
<dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen> <dimen name="motion_pause_detector_speed_somewhat_fast">0.285dp</dimen>
<dimen name="motion_pause_detector_speed_fast">0.5dp</dimen> <dimen name="motion_pause_detector_speed_fast">0.5dp</dimen>
<dimen name="motion_pause_detector_min_displacement">48dp</dimen> <dimen name="motion_pause_detector_min_displacement_from_app">36dp</dimen>
<!-- Launcher app transition --> <!-- Launcher app transition -->
<dimen name="content_trans_y">50dp</dimen> <dimen name="content_trans_y">50dp</dimen>

View File

@ -38,28 +38,26 @@ public class MotionPauseDetector {
private final float mSpeedVerySlow; private final float mSpeedVerySlow;
private final float mSpeedSomewhatFast; private final float mSpeedSomewhatFast;
private final float mSpeedFast; private final float mSpeedFast;
private final float mMinDisplacementForPause;
private final Alarm mForcePauseTimeout; private final Alarm mForcePauseTimeout;
private Long mPreviousTime = null; private Long mPreviousTime = null;
private Float mPreviousPosition = null; private Float mPreviousPosition = null;
private Float mPreviousVelocity = null; private Float mPreviousVelocity = null;
private TotalDisplacement mTotalDisplacement = new TotalDisplacement();
private Float mFirstPosition = null; private Float mFirstPosition = null;
private Float mFirstOrthogonalPosition = null;
private OnMotionPauseListener mOnMotionPauseListener; private OnMotionPauseListener mOnMotionPauseListener;
private boolean mIsPaused; private boolean mIsPaused;
// Bias more for the first pause to make it feel extra responsive. // Bias more for the first pause to make it feel extra responsive.
private boolean mHasEverBeenPaused; private boolean mHasEverBeenPaused;
/** @see #setDisallowPause(boolean) */
private boolean mDisallowPause;
public MotionPauseDetector(Context context) { public MotionPauseDetector(Context context) {
Resources res = context.getResources(); Resources res = context.getResources();
mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow); mSpeedVerySlow = res.getDimension(R.dimen.motion_pause_detector_speed_very_slow);
mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast); mSpeedSomewhatFast = res.getDimension(R.dimen.motion_pause_detector_speed_somewhat_fast);
mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast); mSpeedFast = res.getDimension(R.dimen.motion_pause_detector_speed_fast);
mMinDisplacementForPause = res.getDimension(R.dimen.motion_pause_detector_min_displacement);
mForcePauseTimeout = new Alarm(); mForcePauseTimeout = new Alarm();
mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */)); mForcePauseTimeout.setOnAlarmListener(alarm -> updatePaused(true /* isPaused */));
} }
@ -72,29 +70,31 @@ public class MotionPauseDetector {
mOnMotionPauseListener = listener; mOnMotionPauseListener = listener;
} }
/**
* @param disallowPause If true, we will not detect any pauses until this is set to false again.
*/
public void setDisallowPause(boolean disallowPause) {
mDisallowPause = disallowPause;
updatePaused(false);
}
/** /**
* Computes velocity and acceleration to determine whether the motion is paused. * Computes velocity and acceleration to determine whether the motion is paused.
* @param position The x or y component of the motion being tracked. * @param position The x or y component of the motion being tracked.
* @param orthogonalPosition The x or y component (opposite of {@param position}) of the motion.
* *
* TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}. * TODO: Use historical positions as well, e.g. {@link MotionEvent#getHistoricalY(int, int)}.
*/ */
public void addPosition(float position, float orthogonalPosition, long time) { public void addPosition(float position, long time) {
if (mFirstPosition == null) { if (mFirstPosition == null) {
mFirstPosition = position; mFirstPosition = position;
} }
if (mFirstOrthogonalPosition == null) {
mFirstOrthogonalPosition = orthogonalPosition;
}
mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT); mForcePauseTimeout.setAlarm(FORCE_PAUSE_TIMEOUT);
if (mPreviousTime != null && mPreviousPosition != null) { if (mPreviousTime != null && mPreviousPosition != null) {
long changeInTime = Math.max(1, time - mPreviousTime); long changeInTime = Math.max(1, time - mPreviousTime);
float changeInPosition = position - mPreviousPosition; float changeInPosition = position - mPreviousPosition;
float velocity = changeInPosition / changeInTime; float velocity = changeInPosition / changeInTime;
if (mPreviousVelocity != null) { if (mPreviousVelocity != null) {
mTotalDisplacement.set(Math.abs(position - mFirstPosition), checkMotionPaused(velocity, mPreviousVelocity);
Math.abs(orthogonalPosition - mFirstOrthogonalPosition));
checkMotionPaused(velocity, mPreviousVelocity, mTotalDisplacement);
} }
mPreviousVelocity = velocity; mPreviousVelocity = velocity;
} }
@ -102,8 +102,7 @@ public class MotionPauseDetector {
mPreviousPosition = position; mPreviousPosition = position;
} }
private void checkMotionPaused(float velocity, float prevVelocity, private void checkMotionPaused(float velocity, float prevVelocity) {
TotalDisplacement totalDisplacement) {
float speed = Math.abs(velocity); float speed = Math.abs(velocity);
float previousSpeed = Math.abs(prevVelocity); float previousSpeed = Math.abs(prevVelocity);
boolean isPaused; boolean isPaused;
@ -125,16 +124,13 @@ public class MotionPauseDetector {
} }
} }
} }
boolean passedMinDisplacement = totalDisplacement.primary >= mMinDisplacementForPause;
boolean isDisplacementOrthogonal = totalDisplacement.orthogonal > totalDisplacement.primary;
if (!passedMinDisplacement || isDisplacementOrthogonal) {
mForcePauseTimeout.cancelAlarm();
isPaused = false;
}
updatePaused(isPaused); updatePaused(isPaused);
} }
private void updatePaused(boolean isPaused) { private void updatePaused(boolean isPaused) {
if (mDisallowPause) {
isPaused = false;
}
if (mIsPaused != isPaused) { if (mIsPaused != isPaused) {
mIsPaused = isPaused; mIsPaused = isPaused;
if (mIsPaused) { if (mIsPaused) {
@ -151,8 +147,6 @@ public class MotionPauseDetector {
mPreviousPosition = null; mPreviousPosition = null;
mPreviousVelocity = null; mPreviousVelocity = null;
mFirstPosition = null; mFirstPosition = null;
mFirstOrthogonalPosition = null;
mTotalDisplacement.set(0, 0);
setOnMotionPauseListener(null); setOnMotionPauseListener(null);
mIsPaused = mHasEverBeenPaused = false; mIsPaused = mHasEverBeenPaused = false;
mForcePauseTimeout.cancelAlarm(); mForcePauseTimeout.cancelAlarm();
@ -165,18 +159,4 @@ public class MotionPauseDetector {
public interface OnMotionPauseListener { public interface OnMotionPauseListener {
void onMotionPauseChanged(boolean isPaused); void onMotionPauseChanged(boolean isPaused);
} }
/**
* Contains the displacement from the first tracked position,
* along both the primary and orthogonal axes.
*/
private class TotalDisplacement {
public float primary;
public float orthogonal;
public void set(float primaryDisplacement, float orthogonalDisplacement) {
this.primary = primaryDisplacement;
this.orthogonal = orthogonalDisplacement;
}
}
} }