Unifying FallbackNoButton input consumer with OtherActivityInputConsumer

using a different handler

This will allow us to use common logic for handling horizontal swipe

Bug: 137197916
Change-Id: I6f9cba6e8728dd0669482906c4bf34270af2bc82
This commit is contained in:
Sunny Goyal
2019-07-10 13:16:43 -07:00
parent 6b0eb38461
commit c127dff181
7 changed files with 193 additions and 325 deletions
@@ -22,22 +22,32 @@ import static com.android.launcher3.anim.Interpolators.DEACCEL;
import static com.android.quickstep.TouchInteractionService.BACKGROUND_EXECUTOR;
import android.annotation.TargetApi;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.graphics.PointF;
import android.os.Build;
import android.os.VibrationEffect;
import android.os.Vibrator;
import android.provider.Settings;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
import com.android.launcher3.Utilities;
import com.android.launcher3.graphics.RotationMode;
import com.android.quickstep.util.ClipAnimationHelper;
import com.android.quickstep.util.ClipAnimationHelper.TransformParams;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import com.android.quickstep.views.RecentsView;
import java.util.function.Consumer;
import androidx.annotation.UiThread;
/**
* Base class for swipe up handler with some utility methods
*/
@TargetApi(Build.VERSION_CODES.Q)
public abstract class BaseSwipeUpHandler {
public abstract class BaseSwipeUpHandler implements SwipeAnimationListener {
// Start resisting when swiping past this factor of mTransitionDragLength.
private static final float DRAG_LENGTH_FACTOR_START_PULLBACK = 1.4f;
@@ -57,6 +67,16 @@ public abstract class BaseSwipeUpHandler {
private final Vibrator mVibrator;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
// visible.
protected final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
protected RecentsView mRecentsView;
protected Runnable mGestureEndCallback;
protected BaseSwipeUpHandler(Context context) {
mContext = context;
mClipAnimationHelper = new ClipAnimationHelper(context);
@@ -80,14 +100,20 @@ public abstract class BaseSwipeUpHandler {
BACKGROUND_EXECUTOR.execute(() -> mVibrator.vibrate(effect));
}
protected float getShiftForDisplacement(float displacement) {
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
return mRecentsView != null ? mRecentsView.getEventDispatcher(rotationMode) : null;
}
@UiThread
public void updateDisplacement(float displacement) {
// We are moving in the negative x/y direction
displacement = -displacement;
float shift;
if (displacement > mTransitionDragLength * mDragLengthFactor && mTransitionDragLength > 0) {
return mDragLengthFactor;
shift = mDragLengthFactor;
} else {
float translation = Math.max(displacement, 0);
float shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
shift = mTransitionDragLength == 0 ? 0 : translation / mTransitionDragLength;
if (shift > DRAG_LENGTH_FACTOR_START_PULLBACK) {
float pullbackProgress = Utilities.getProgress(shift,
DRAG_LENGTH_FACTOR_START_PULLBACK, mDragLengthFactor);
@@ -95,7 +121,44 @@ public abstract class BaseSwipeUpHandler {
shift = DRAG_LENGTH_FACTOR_START_PULLBACK + pullbackProgress
* (DRAG_LENGTH_FACTOR_MAX_PULLBACK - DRAG_LENGTH_FACTOR_START_PULLBACK);
}
return shift;
}
mCurrentShift.updateValue(shift);
}
public void setGestureEndCallback(Runnable gestureEndCallback) {
mGestureEndCallback = gestureEndCallback;
}
/**
* Called when the value of {@link #mCurrentShift} changes
*/
public abstract void updateFinalShift();
/**
* Called when motion pause is detected
*/
public abstract void onMotionPauseChanged(boolean isPaused);
@UiThread
public void onGestureStarted() { }
@UiThread
public abstract void onGestureCancelled();
@UiThread
public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) { }
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
public void initWhenReady() { }
public interface Factory {
BaseSwipeUpHandler newHandler(RunningTaskInfo runningTask,
long touchTimeMs, boolean continuingLastGesture);
}
}
@@ -199,6 +199,12 @@ public final class RecentsActivity extends BaseRecentsActivity {
mFallbackRecentsView.resetTaskVisuals();
}
@Override
protected void onStop() {
super.onStop();
mFallbackRecentsView.reset();
}
public void onTaskLaunched() {
mFallbackRecentsView.resetTaskVisuals();
}
@@ -239,6 +239,11 @@ public class TouchInteractionService extends Service implements
private final InputConsumer mResetGestureInputConsumer =
new ResetGestureInputConsumer(sSwipeSharedState);
private final BaseSwipeUpHandler.Factory mWindowTreansformFactory =
this::createWindowTransformSwipeHandler;
private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
this::createFallbackNoButtonSwipeHandler;
private ActivityManagerWrapper mAM;
private RecentsModel mRecentsModel;
private ISystemUiProxy mISystemUiProxy;
@@ -623,10 +628,6 @@ public class TouchInteractionService extends Service implements
} else if (mGestureBlockingActivity != null && runningTaskInfo != null
&& mGestureBlockingActivity.equals(runningTaskInfo.topActivity)) {
return mResetGestureInputConsumer;
} else if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
return new FallbackNoButtonInputConsumer(this, activityControl,
mInputMonitorCompat, sSwipeSharedState, mSwipeTouchRegion,
mOverviewComponentObserver, disableHorizontalSwipe(event), runningTaskInfo);
} else {
return createOtherActivityInputConsumer(event, runningTaskInfo);
}
@@ -639,17 +640,28 @@ public class TouchInteractionService extends Service implements
&& exclusionRegion.contains((int) event.getX(), (int) event.getY());
}
private OtherActivityInputConsumer createOtherActivityInputConsumer(MotionEvent event,
private InputConsumer createOtherActivityInputConsumer(MotionEvent event,
RunningTaskInfo runningTaskInfo) {
final ActivityControlHelper activityControl =
mOverviewComponentObserver.getActivityControlHelper();
boolean shouldDefer = activityControl.deferStartingActivity(mActiveNavBarRegion, event);
return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel,
mOverviewComponentObserver.getOverviewIntent(), activityControl,
shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive,
final boolean shouldDefer;
final BaseSwipeUpHandler.Factory factory;
final Intent homeIntent;
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
shouldDefer = true;
factory = mFallbackNoButtonFactory;
homeIntent = mOverviewComponentObserver.getHomeIntent();
} else {
shouldDefer = mOverviewComponentObserver.getActivityControlHelper()
.deferStartingActivity(mActiveNavBarRegion, event);
factory = mWindowTreansformFactory;
homeIntent = mOverviewComponentObserver.getOverviewIntent();
}
return new OtherActivityInputConsumer(this, runningTaskInfo, homeIntent,
shouldDefer, mOverviewCallbacks, this::onConsumerInactive,
sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion,
disableHorizontalSwipe(event));
disableHorizontalSwipe(event), factory);
}
private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) {
@@ -788,6 +800,19 @@ public class TouchInteractionService extends Service implements
}
}
private BaseSwipeUpHandler createWindowTransformSwipeHandler(RunningTaskInfo runningTask,
long touchTimeMs, boolean continuingLastGesture) {
return new WindowTransformSwipeHandler(
runningTask, this, touchTimeMs,
mOverviewComponentObserver.getActivityControlHelper(),
continuingLastGesture, mInputConsumer, mRecentsModel);
}
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(RunningTaskInfo runningTask,
long touchTimeMs, boolean continuingLastGesture) {
return new FallbackNoButtonInputConsumer(this, mOverviewComponentObserver, runningTask);
}
public static void startRecentsActivityAsync(Intent intent, RecentsAnimationListener listener) {
BACKGROUND_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
.startRecentsActivity(intent, null, listener, null, null));
@@ -58,7 +58,6 @@ import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnApplyWindowInsetsListener;
import android.view.ViewTreeObserver.OnDrawListener;
@@ -66,10 +65,6 @@ import android.view.WindowInsets;
import android.view.WindowManager;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.UiThread;
import com.android.launcher3.AbstractFloatingView;
import com.android.launcher3.BaseDraggingActivity;
import com.android.launcher3.DeviceProfile;
@@ -79,7 +74,6 @@ import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.Interpolators;
import com.android.launcher3.graphics.RotationMode;
import com.android.launcher3.logging.UserEventDispatcher;
import com.android.launcher3.testing.TestProtocol;
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
@@ -99,9 +93,7 @@ import com.android.quickstep.util.ClipAnimationHelper.TargetAlphaProvider;
import com.android.quickstep.util.RectFSpringAnim;
import com.android.quickstep.util.RemoteAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import com.android.quickstep.views.LiveTileOverlay;
import com.android.quickstep.views.RecentsView;
import com.android.quickstep.views.TaskView;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.InputConsumerController;
@@ -110,11 +102,12 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat;
import com.android.systemui.shared.system.WindowCallbacksCompat;
import java.util.function.Consumer;
import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
@TargetApi(Build.VERSION_CODES.O)
public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends BaseSwipeUpHandler
implements SwipeAnimationListener, OnApplyWindowInsetsListener {
implements OnApplyWindowInsetsListener {
private static final String TAG = WindowTransformSwipeHandler.class.getSimpleName();
private static final Rect TEMP_RECT = new Rect();
@@ -222,18 +215,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
*/
private static final int LOG_NO_OP_PAGE_INDEX = -1;
private Runnable mGestureEndCallback;
private GestureEndTarget mGestureEndTarget;
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
private RunningWindowAnim mRunningWindowAnim;
private boolean mIsShelfPeeking;
private DeviceProfile mDp;
// Shift in the range of [0, 1].
// 0 => preview snapShot is completely visible, and hotseat is completely translated down
// 1 => preview snapShot is completely aligned with the recents view and hotseat is completely
// visible.
private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift);
private boolean mContinuingLastGesture;
// To avoid UI jump when gesture is started, we offset the animation by the threshold.
private float mShiftAtGestureStart = 0;
@@ -242,6 +229,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
private final ActivityControlHelper<T> mActivityControlHelper;
private final ActivityInitListener mActivityInitListener;
private final RecentsModel mRecentsModel;
private final SysUINavigationMode.Mode mMode;
@@ -254,7 +242,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
private boolean mHasLauncherTransitionControllerStarted;
private T mActivity;
private RecentsView mRecentsView;
private AnimationFactory mAnimationFactory = (t) -> { };
private LiveTileOverlay mLiveTileOverlay = new LiveTileOverlay();
@@ -276,11 +263,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
public WindowTransformSwipeHandler(RunningTaskInfo runningTaskInfo, Context context,
long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture,
InputConsumerController inputConsumer) {
InputConsumerController inputConsumer, RecentsModel recentsModel) {
super(context);
mRunningTaskId = runningTaskInfo.id;
mTouchTimeMs = touchTimeMs;
mActivityControlHelper = controller;
mRecentsModel = recentsModel;
mActivityInitListener = mActivityControlHelper
.createActivityInitListener(this::onActivityInit);
mContinuingLastGesture = continuingLastGesture;
@@ -375,7 +363,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
}
}
@Override
public void initWhenReady() {
// Preload the plan
mRecentsModel.getTasks(null);
mActivityInitListener.register();
}
@@ -546,15 +538,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
return TaskView.getCurveScaleForInterpolation(interpolation);
}
public Consumer<MotionEvent> getRecentsViewDispatcher(RotationMode rotationMode) {
return mRecentsView != null ? mRecentsView.getEventDispatcher(rotationMode) : null;
}
@UiThread
public void updateDisplacement(float displacement) {
mCurrentShift.updateValue(getShiftForDisplacement(displacement));
}
@Override
public void onMotionPauseChanged(boolean isPaused) {
setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
}
@@ -605,6 +589,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
mAnimationFactory.setRecentsAttachedToAppWindow(recentsAttachedToAppWindow, animate);
}
@Override
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) {
if (mIsLikelyToStartNewTask != isLikelyToStartNewTask) {
mIsLikelyToStartNewTask = isLikelyToStartNewTask;
@@ -651,7 +636,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
}
@UiThread
private void updateFinalShift() {
@Override
public void updateFinalShift() {
float shift = mCurrentShift.value;
SwipeAnimationTargetSet controller = mRecentsAnimationWrapper.getController();
@@ -766,7 +752,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
TOUCH_INTERACTION_LOG.addLog("cancelRecentsAnimation");
}
@UiThread
@Override
public void onGestureStarted() {
notifyGestureStartedAsync();
mShiftAtGestureStart = mCurrentShift.value;
@@ -790,7 +776,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
/**
* Called as a result on ACTION_CANCEL to return the UI to the start state.
*/
@UiThread
@Override
public void onGestureCancelled() {
updateDisplacement(0);
setStateOnUiThread(STATE_GESTURE_COMPLETED);
@@ -803,7 +789,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
* @param velocity The x and y components of the velocity when the gesture ends.
* @param downPos The x and y value of where the gesture started.
*/
@UiThread
@Override
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
@@ -1174,11 +1160,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
return anim;
}
/**
* @return The GestureEndTarget if the gesture has ended, else null.
*/
public @Nullable GestureEndTarget getGestureEndTarget() {
return mGestureEndTarget;
@Override
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
if (mGestureEndTarget != null) {
sharedState.canGestureBeContinued = mGestureEndTarget.canBeContinued;
sharedState.goingToLauncher = mGestureEndTarget.isLauncher;
}
if (sharedState.canGestureBeContinued) {
cancelCurrentAnimation(sharedState);
} else {
reset();
}
}
@UiThread
@@ -1227,7 +1220,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
TOUCH_INTERACTION_LOG.addLog("finishRecentsAnimation", true);
}
public void reset() {
private void reset() {
setStateOnUiThread(STATE_HANDLER_INVALIDATED);
}
@@ -1235,7 +1228,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
* Cancels any running animation so that the active target can be overriden by a new swipe
* handle (in case of quick switch).
*/
public void cancelCurrentAnimation(SwipeSharedState sharedState) {
private void cancelCurrentAnimation(SwipeSharedState sharedState) {
mCanceled = true;
mCurrentShift.cancelAnimation();
if (mLauncherTransitionController != null && mLauncherTransitionController
@@ -1398,10 +1391,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> extends
reset();
}
public void setGestureEndCallback(Runnable gestureEndCallback) {
mGestureEndCallback = gestureEndCallback;
}
private void setTargetAlphaProvider(TargetAlphaProvider provider) {
mClipAnimationHelper.setTaskAlphaCallback(provider);
updateFinalShift();
@@ -15,23 +15,12 @@
*/
package com.android.quickstep.inputconsumers;
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
import static android.view.MotionEvent.ACTION_POINTER_UP;
import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.HOME;
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.LAST_TASK;
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS;
import static com.android.quickstep.inputconsumers.OtherActivityInputConsumer.QUICKSTEP_TOUCH_SLOP_RATIO;
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -42,11 +31,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.PointF;
import android.graphics.Rect;
import android.graphics.RectF;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.ViewConfiguration;
import android.view.WindowManager;
import com.android.launcher3.DeviceProfile;
@@ -56,20 +41,12 @@ import com.android.quickstep.ActivityControlHelper;
import com.android.quickstep.AnimatedFloat;
import com.android.quickstep.BaseSwipeUpHandler;
import com.android.quickstep.OverviewComponentObserver;
import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.ObjectWrapper;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.quickstep.util.SwipeAnimationTargetSet;
import com.android.quickstep.util.SwipeAnimationTargetSet.SwipeAnimationListener;
import com.android.systemui.shared.recents.model.ThumbnailData;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputMonitorCompat;
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
implements InputConsumer, SwipeAnimationListener {
public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler {
public enum GestureEndTarget {
HOME(3, 100, 1),
@@ -79,6 +56,7 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
private final float mEndProgress;
private final long mDurationMultiplier;
private final float mLauncherAlpha;
GestureEndTarget(float endProgress, long durationMultiplier, float launcherAlpha) {
mEndProgress = endProgress;
mDurationMultiplier = durationMultiplier;
@@ -87,68 +65,26 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
}
private final ActivityControlHelper mActivityControlHelper;
private final InputMonitorCompat mInputMonitor;
private final NavBarPosition mNavBarPosition;
private final SwipeSharedState mSwipeSharedState;
private final OverviewComponentObserver mOverviewComponentObserver;
private final int mRunningTaskId;
private final DeviceProfile mDP;
private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
private final Rect mTargetRect = new Rect();
private final RectF mSwipeTouchRegion;
private final boolean mDisableHorizontalSwipe;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
private final AnimatedFloat mProgress = new AnimatedFloat(this::onProgressChanged);
private int mActivePointerId = -1;
// Slop used to determine when we say that the gesture has started.
private boolean mPassedPilferInputSlop;
private VelocityTracker mVelocityTracker;
// Distance after which we start dragging the window.
private final float mTouchSlop;
// Might be displacement in X or Y, depending on the direction we are swiping from the nav bar.
private float mStartDisplacement;
private SwipeAnimationTargetSet mSwipeAnimationTargetSet;
private boolean mIsMotionPaused = false;
private GestureEndTarget mEndTarget;
public FallbackNoButtonInputConsumer(Context context,
ActivityControlHelper activityControlHelper, InputMonitorCompat inputMonitor,
SwipeSharedState swipeSharedState, RectF swipeTouchRegion,
OverviewComponentObserver overviewComponentObserver,
boolean disableHorizontalSwipe, RunningTaskInfo runningTaskInfo) {
RunningTaskInfo runningTaskInfo) {
super(context);
mActivityControlHelper = activityControlHelper;
mInputMonitor = inputMonitor;
mOverviewComponentObserver = overviewComponentObserver;
mActivityControlHelper = overviewComponentObserver.getActivityControlHelper();
mRunningTaskId = runningTaskInfo.id;
mMotionPauseDetector = new MotionPauseDetector(context);
mMotionPauseMinDisplacement = context.getResources().getDimension(
R.dimen.motion_pause_detector_min_displacement_from_app);
mMotionPauseDetector.setOnMotionPauseListener(this::onMotionPauseChanged);
mSwipeSharedState = swipeSharedState;
mSwipeTouchRegion = swipeTouchRegion;
mDisableHorizontalSwipe = disableHorizontalSwipe;
mNavBarPosition = new NavBarPosition(context);
mVelocityTracker = VelocityTracker.obtain();
mTouchSlop = QUICKSTEP_TOUCH_SLOP_RATIO
* ViewConfiguration.get(context).getScaledTouchSlop();
mDP = InvariantDeviceProfile.INSTANCE.get(context).getDeviceProfile(context).copy(context);
mLauncherAlpha.value = 1;
@@ -156,18 +92,14 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
initTransitionTarget();
}
@Override
public int getType() {
return TYPE_FALLBACK_NO_BUTTON;
}
private void onLauncherAlphaChanged() {
if (mSwipeAnimationTargetSet != null && mEndTarget == null) {
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
}
}
private void onMotionPauseChanged(boolean isPaused) {
@Override
public void onMotionPauseChanged(boolean isPaused) {
mIsMotionPaused = isPaused;
mLauncherAlpha.animateToValue(mLauncherAlpha.value, isPaused ? 0 : 1)
.setDuration(150).start();
@@ -175,150 +107,36 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
}
@Override
public void onMotionEvent(MotionEvent ev) {
if (mVelocityTracker == null) {
return;
}
mVelocityTracker.addMovement(ev);
if (ev.getActionMasked() == ACTION_POINTER_UP) {
mVelocityTracker.clear();
mMotionPauseDetector.clear();
}
switch (ev.getActionMasked()) {
case ACTION_DOWN: {
mActivePointerId = ev.getPointerId(0);
mDownPos.set(ev.getX(), ev.getY());
mLastPos.set(mDownPos);
break;
}
case ACTION_POINTER_DOWN: {
if (!mPassedPilferInputSlop) {
// Cancel interaction in case of multi-touch interaction
int ptrIdx = ev.getActionIndex();
if (!mSwipeTouchRegion.contains(ev.getX(ptrIdx), ev.getY(ptrIdx))) {
forceCancelGesture(ev);
}
}
break;
}
case ACTION_POINTER_UP: {
int ptrIdx = ev.getActionIndex();
int ptrId = ev.getPointerId(ptrIdx);
if (ptrId == mActivePointerId) {
final int newPointerIdx = ptrIdx == 0 ? 1 : 0;
mDownPos.set(
ev.getX(newPointerIdx) - (mLastPos.x - mDownPos.x),
ev.getY(newPointerIdx) - (mLastPos.y - mDownPos.y));
mLastPos.set(ev.getX(newPointerIdx), ev.getY(newPointerIdx));
mActivePointerId = ev.getPointerId(newPointerIdx);
}
break;
}
case ACTION_MOVE: {
int pointerIndex = ev.findPointerIndex(mActivePointerId);
if (pointerIndex == INVALID_POINTER_ID) {
break;
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
float displacement = getDisplacement(ev);
if (!mPassedPilferInputSlop) {
if (mDisableHorizontalSwipe && Math.abs(mLastPos.x - mDownPos.x)
> Math.abs(mLastPos.y - mDownPos.y)) {
// Horizontal gesture is not allowed in this region
forceCancelGesture(ev);
break;
}
if (Math.abs(displacement) >= mTouchSlop) {
mPassedPilferInputSlop = true;
// Deferred gesture, start the animation and gesture tracking once
// we pass the actual touch slop
startTouchTrackingForWindowAnimation(displacement);
}
} else {
updateDisplacement(displacement - mStartDisplacement);
mMotionPauseDetector.setDisallowPause(
-displacement < mMotionPauseMinDisplacement);
mMotionPauseDetector.addPosition(displacement, ev.getEventTime());
}
break;
}
case ACTION_CANCEL:
case ACTION_UP: {
finishTouchTracking(ev);
break;
}
}
}
private void startTouchTrackingForWindowAnimation(float displacement) {
mStartDisplacement = Math.min(displacement, -mTouchSlop);
RecentsAnimationListenerSet listenerSet =
mSwipeSharedState.newRecentsAnimationListenerSet();
listenerSet.addListener(this);
Intent homeIntent = mOverviewComponentObserver.getHomeIntent();
startRecentsActivityAsync(homeIntent, listenerSet);
ActivityManagerWrapper.getInstance().closeSystemWindows(
CLOSE_SYSTEM_WINDOWS_REASON_RECENTS);
mInputMonitor.pilferPointers();
}
private void updateDisplacement(float displacement) {
mProgress.updateValue(getShiftForDisplacement(displacement));
}
private void onProgressChanged() {
mTransformParams.setProgress(mProgress.value);
public void updateFinalShift() {
mTransformParams.setProgress(mCurrentShift.value);
if (mSwipeAnimationTargetSet != null) {
mClipAnimationHelper.applyTransform(mSwipeAnimationTargetSet, mTransformParams);
}
}
private void forceCancelGesture(MotionEvent ev) {
int action = ev.getAction();
ev.setAction(ACTION_CANCEL);
finishTouchTracking(ev);
ev.setAction(action);
@Override
public void onGestureCancelled() {
updateDisplacement(0);
mEndTarget = LAST_TASK;
finishAnimationTargetSetAnimationComplete();
}
/**
* Called when the gesture has ended. Does not correlate to the completion of the interaction as
* the animation can still be running.
*/
private void finishTouchTracking(MotionEvent ev) {
if (ev.getAction() == ACTION_CANCEL) {
mEndTarget = LAST_TASK;
@Override
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
boolean isFling = Math.abs(endVelocity) > flingThreshold;
if (isFling) {
mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
} else if (mIsMotionPaused) {
mEndTarget = RECENTS;
} else {
mVelocityTracker.computeCurrentVelocity(1000,
ViewConfiguration.get(mContext).getScaledMaximumFlingVelocity());
float velocityX = mVelocityTracker.getXVelocity(mActivePointerId);
float velocityY = mVelocityTracker.getYVelocity(mActivePointerId);
float velocity = mNavBarPosition.isRightEdge() ? velocityX
: mNavBarPosition.isLeftEdge() ? -velocityX
: velocityY;
float flingThreshold = mContext.getResources()
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
boolean isFling = Math.abs(velocity) > flingThreshold;
if (isFling) {
mEndTarget = velocity < 0 ? HOME : LAST_TASK;
} else if (mIsMotionPaused) {
mEndTarget = RECENTS;
} else {
mEndTarget = mProgress.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
}
mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
}
if (mSwipeAnimationTargetSet != null) {
finishAnimationTargetSet();
}
mMotionPauseDetector.clear();
}
private void finishAnimationTargetSetAnimationComplete() {
@@ -346,19 +164,22 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
break;
}
}
if (mGestureEndCallback != null) {
mGestureEndCallback.run();
}
}
private void finishAnimationTargetSet() {
float endProgress = mEndTarget.mEndProgress;
if (mProgress.value != endProgress) {
if (mCurrentShift.value != endProgress) {
AnimatorSet anim = new AnimatorSet();
anim.play(mLauncherAlpha.animateToValue(
mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
anim.play(mProgress.animateToValue(mProgress.value, endProgress));
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
anim.setDuration((long) (mEndTarget.mDurationMultiplier *
Math.abs(endProgress - mProgress.value)));
Math.abs(endProgress - mCurrentShift.value)));
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
@@ -403,19 +224,4 @@ public class FallbackNoButtonInputConsumer extends BaseSwipeUpHandler
@Override
public void onRecentsAnimationCanceled() { }
private float getDisplacement(MotionEvent ev) {
if (mNavBarPosition.isRightEdge()) {
return ev.getX() - mDownPos.x;
} else if (mNavBarPosition.isLeftEdge()) {
return mDownPos.x - ev.getX();
} else {
return ev.getY() - mDownPos.y;
}
}
@Override
public boolean allowInterceptByParent() {
return !mPassedPilferInputSlop;
}
}
@@ -33,7 +33,6 @@ public interface InputConsumer {
int TYPE_SCREEN_PINNED = 1 << 6;
int TYPE_OVERVIEW_WITHOUT_FOCUS = 1 << 7;
int TYPE_RESET_GESTURE = 1 << 8;
int TYPE_FALLBACK_NO_BUTTON = 1 << 9;
String[] NAMES = new String[] {
"TYPE_NO_OP", // 0
@@ -45,7 +44,6 @@ public interface InputConsumer {
"TYPE_SCREEN_PINNED", // 6
"TYPE_OVERVIEW_WITHOUT_FOCUS", // 7
"TYPE_RESET_GESTURE", // 8
"TYPE_FALLBACK_NO_BUTTON", // 9
};
InputConsumer NO_OP = () -> TYPE_NO_OP;
@@ -49,20 +49,16 @@ import com.android.launcher3.R;
import com.android.launcher3.util.Preconditions;
import com.android.launcher3.util.RaceConditionTracker;
import com.android.launcher3.util.TraceHelper;
import com.android.quickstep.ActivityControlHelper;
import com.android.quickstep.BaseSwipeUpHandler;
import com.android.quickstep.OverviewCallbacks;
import com.android.quickstep.RecentsModel;
import com.android.quickstep.SwipeSharedState;
import com.android.quickstep.SysUINavigationMode;
import com.android.quickstep.SysUINavigationMode.Mode;
import com.android.quickstep.WindowTransformSwipeHandler;
import com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget;
import com.android.quickstep.util.CachedEventDispatcher;
import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.NavBarPosition;
import com.android.quickstep.util.RecentsAnimationListenerSet;
import com.android.systemui.shared.system.ActivityManagerWrapper;
import com.android.systemui.shared.system.InputConsumerController;
import com.android.systemui.shared.system.InputMonitorCompat;
import java.util.function.Consumer;
@@ -83,16 +79,15 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
private final RunningTaskInfo mRunningTask;
private final RecentsModel mRecentsModel;
private final Intent mHomeIntent;
private final ActivityControlHelper mActivityControlHelper;
private final OverviewCallbacks mOverviewCallbacks;
private final InputConsumerController mInputConsumer;
private final SwipeSharedState mSwipeSharedState;
private final InputMonitorCompat mInputMonitorCompat;
private final SysUINavigationMode.Mode mMode;
private final RectF mSwipeTouchRegion;
private final BaseSwipeUpHandler.Factory mHandlerFactory;
private final NavBarPosition mNavBarPosition;
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
@@ -100,7 +95,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final float mMotionPauseMinDisplacement;
private VelocityTracker mVelocityTracker;
private WindowTransformSwipeHandler mInteractionHandler;
private BaseSwipeUpHandler mInteractionHandler;
private final boolean mIsDeferredDownTarget;
private final PointF mDownPos = new PointF();
@@ -114,7 +109,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private final boolean mDisableHorizontalSwipe;
// Slop used to check when we start moving window.
private boolean mPaddedWindowMoveSlop;
private boolean mPassedWindowMoveSlop;
// Slop used to determine when we say that the gesture has started.
private boolean mPassedPilferInputSlop;
@@ -122,26 +117,24 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
private float mStartDisplacement;
private Handler mMainThreadHandler;
private Runnable mCancelRecentsAnimationRunnable = () -> {
private Runnable mCancelRecentsAnimationRunnable = () ->
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
true /* restoreHomeStackPosition */);
};
public OtherActivityInputConsumer(Context base, RunningTaskInfo runningTaskInfo,
RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl,
boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
InputConsumerController inputConsumer,
Intent homeIntent, boolean isDeferredDownTarget, OverviewCallbacks overviewCallbacks,
Consumer<OtherActivityInputConsumer> onCompleteCallback,
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
RectF swipeTouchRegion, boolean disableHorizontalSwipe) {
RectF swipeTouchRegion, boolean disableHorizontalSwipe,
BaseSwipeUpHandler.Factory handlerFactory) {
super(base);
mMainThreadHandler = new Handler(Looper.getMainLooper());
mRunningTask = runningTaskInfo;
mRecentsModel = recentsModel;
mHomeIntent = homeIntent;
mMode = SysUINavigationMode.getMode(base);
mSwipeTouchRegion = swipeTouchRegion;
mHandlerFactory = handlerFactory;
mMotionPauseDetector = new MotionPauseDetector(base);
mMotionPauseMinDisplacement = base.getResources().getDimension(
@@ -150,11 +143,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
mVelocityTracker = VelocityTracker.obtain();
mInputMonitorCompat = inputMonitorCompat;
mActivityControlHelper = activityControl;
boolean continuingPreviousGesture = swipeSharedState.getActiveListener() != null;
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
mOverviewCallbacks = overviewCallbacks;
mInputConsumer = inputConsumer;
mSwipeSharedState = swipeSharedState;
mNavBarPosition = new NavBarPosition(base);
@@ -163,7 +154,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
float slop = QUICKSTEP_TOUCH_SLOP_RATIO * mTouchSlop;
mSquaredTouchSlop = slop * slop;
mPassedPilferInputSlop = mPaddedWindowMoveSlop = continuingPreviousGesture;
mPassedPilferInputSlop = mPassedWindowMoveSlop = continuingPreviousGesture;
mDisableHorizontalSwipe = !mPassedPilferInputSlop && disableHorizontalSwipe;
}
@@ -186,7 +177,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
// Proxy events to recents view
if (mPaddedWindowMoveSlop && mInteractionHandler != null
if (mPassedWindowMoveSlop && mInteractionHandler != null
&& !mRecentsViewDispatcher.hasConsumer()) {
mRecentsViewDispatcher.setConsumer(mInteractionHandler.getRecentsViewDispatcher(
mNavBarPosition.getRotationMode()));
@@ -251,12 +242,12 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
float displacement = getDisplacement(ev);
float displacementX = mLastPos.x - mDownPos.x;
if (!mPaddedWindowMoveSlop) {
if (!mPassedWindowMoveSlop) {
if (!mIsDeferredDownTarget) {
// Normal gesture, ensure we pass the drag slop before we start tracking
// the gesture
if (Math.abs(displacement) > mTouchSlop) {
mPaddedWindowMoveSlop = true;
mPassedWindowMoveSlop = true;
mStartDisplacement = Math.min(displacement, -mTouchSlop);
}
}
@@ -279,8 +270,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
// we pass the actual touch slop
startTouchTrackingForWindowAnimation(ev.getEventTime());
}
if (!mPaddedWindowMoveSlop) {
mPaddedWindowMoveSlop = true;
if (!mPassedWindowMoveSlop) {
mPassedWindowMoveSlop = true;
mStartDisplacement = Math.min(displacement, -mTouchSlop);
}
@@ -289,7 +280,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
}
if (mInteractionHandler != null) {
if (mPaddedWindowMoveSlop) {
if (mPassedWindowMoveSlop) {
// Move
mInteractionHandler.updateDisplacement(displacement - mStartDisplacement);
}
@@ -333,12 +324,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
TOUCH_INTERACTION_LOG.addLog("startRecentsAnimation");
RecentsAnimationListenerSet listenerSet = mSwipeSharedState.getActiveListener();
final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler(
mRunningTask, this, touchTimeMs, mActivityControlHelper,
listenerSet != null, mInputConsumer);
final BaseSwipeUpHandler handler = mHandlerFactory.newHandler(mRunningTask, touchTimeMs,
listenerSet != null);
// Preload the plan
mRecentsModel.getTasks(null);
mInteractionHandler = handler;
handler.setGestureEndCallback(this::onInteractionGestureFinished);
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
@@ -364,7 +352,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
RaceConditionTracker.onEvent(UP_EVT, ENTER);
TraceHelper.endSection("TouchInt");
if (mPaddedWindowMoveSlop && mInteractionHandler != null) {
if (mPassedWindowMoveSlop && mInteractionHandler != null) {
if (ev.getActionMasked() == ACTION_CANCEL) {
mInteractionHandler.onGestureCancelled();
} else {
@@ -407,14 +395,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
// The consumer is being switched while we are active. Set up the shared state to be
// used by the next animation
removeListener();
GestureEndTarget endTarget = mInteractionHandler.getGestureEndTarget();
mSwipeSharedState.canGestureBeContinued = endTarget != null && endTarget.canBeContinued;
mSwipeSharedState.goingToLauncher = endTarget != null && endTarget.isLauncher;
if (mSwipeSharedState.canGestureBeContinued) {
mInteractionHandler.cancelCurrentAnimation(mSwipeSharedState);
} else {
mInteractionHandler.reset();
}
mInteractionHandler.onConsumerAboutToBeSwitched(mSwipeSharedState);
}
}