10/ Migrate shared state to the gesture state
- Instead of a shared state which is written into, gestures update their own gesture state and that state is passed to the next gesture. - The existing shared state encoded the final end target (which is currently directly correlated with canGestureBeContinued). If we move the end target calculations to the GestureState, the handlers can listen for those changes and we can use the previous gesture state to decide which consumer to choose. In addition, we move over the interrupted- finish-launch-task id. Bug: 141886704 Change-Id: Icb6a3815c16b23692dbcde316114bd3cea06634e Signed-off-by: Winson Chung <winsonc@google.com>
This commit is contained in:
parent
c9bf6d45ac
commit
c80b3224aa
|
@ -20,13 +20,14 @@ import android.os.Looper;
|
|||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
|
||||
/**
|
||||
* State to indicate we are about to launch a recent task. Note that this state is only used when
|
||||
* quick switching from launcher; quick switching from an app uses WindowTransformSwipeHelper.
|
||||
* @see com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget#NEW_TASK
|
||||
* @see GestureState.GestureEndTarget#NEW_TASK
|
||||
*/
|
||||
public class QuickSwitchState extends BackgroundAppState {
|
||||
|
||||
|
|
|
@ -96,6 +96,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
protected float mDragLengthFactor = 1;
|
||||
|
||||
protected final Context mContext;
|
||||
protected final GestureState mGestureState;
|
||||
protected final OverviewComponentObserver mOverviewComponentObserver;
|
||||
protected final BaseActivityInterface<T> mActivityInterface;
|
||||
protected final RecentsModel mRecentsModel;
|
||||
|
@ -139,6 +140,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
OverviewComponentObserver overviewComponentObserver,
|
||||
RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
|
||||
mContext = context;
|
||||
mGestureState = gestureState;
|
||||
mOverviewComponentObserver = overviewComponentObserver;
|
||||
mActivityInterface = gestureState.getActivityInterface();
|
||||
mRecentsModel = recentsModel;
|
||||
|
@ -394,7 +396,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
|||
@UiThread
|
||||
public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
|
||||
|
||||
public abstract void onConsumerAboutToBeSwitched(SwipeSharedState sharedState);
|
||||
public abstract void onConsumerAboutToBeSwitched();
|
||||
|
||||
public void setIsLikelyToStartNewTask(boolean isLikelyToStartNewTask) { }
|
||||
|
||||
|
|
|
@ -1,59 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2019 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.quickstep;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Utility class used to store state information shared across multiple transitions.
|
||||
*/
|
||||
public class SwipeSharedState {
|
||||
|
||||
public boolean canGestureBeContinued;
|
||||
public boolean goingToLauncher;
|
||||
public boolean recentsAnimationFinishInterrupted;
|
||||
public int nextRunningTaskId = -1;
|
||||
private int mLogId;
|
||||
|
||||
/**
|
||||
* Called when a recents animation has finished, but was interrupted before the next task was
|
||||
* launched. The given {@param runningTaskId} should be used as the running task for the
|
||||
* continuing input consumer.
|
||||
*/
|
||||
public void setRecentsAnimationFinishInterrupted(int runningTaskId) {
|
||||
recentsAnimationFinishInterrupted = true;
|
||||
nextRunningTaskId = runningTaskId;
|
||||
}
|
||||
|
||||
public void clearAllState() {
|
||||
canGestureBeContinued = false;
|
||||
recentsAnimationFinishInterrupted = false;
|
||||
nextRunningTaskId = -1;
|
||||
goingToLauncher = false;
|
||||
}
|
||||
|
||||
public void dump(String prefix, PrintWriter pw) {
|
||||
pw.println(prefix + "goingToLauncher=" + goingToLauncher);
|
||||
pw.println(prefix + "canGestureBeContinued=" + canGestureBeContinued);
|
||||
pw.println(prefix + "recentsAnimationFinishInterrupted=" + recentsAnimationFinishInterrupted);
|
||||
pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
|
||||
pw.println(prefix + "logTraceId=" + mLogId);
|
||||
}
|
||||
|
||||
public void setLogTraceId(int logId) {
|
||||
this.mLogId = logId;
|
||||
}
|
||||
}
|
|
@ -235,8 +235,6 @@ public class TouchInteractionService extends Service implements
|
|||
|
||||
private static boolean sConnected = false;
|
||||
private static boolean sIsInitialized = false;
|
||||
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
|
||||
private int mLogId;
|
||||
|
||||
public static boolean isConnected() {
|
||||
return sConnected;
|
||||
|
@ -246,10 +244,6 @@ public class TouchInteractionService extends Service implements
|
|||
return sIsInitialized;
|
||||
}
|
||||
|
||||
public static SwipeSharedState getSwipeSharedState() {
|
||||
return sSwipeSharedState;
|
||||
}
|
||||
|
||||
private final BaseSwipeUpHandler.Factory mWindowTransformFactory =
|
||||
this::createWindowTransformSwipeHandler;
|
||||
private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
|
||||
|
@ -267,6 +261,7 @@ public class TouchInteractionService extends Service implements
|
|||
private InputConsumer mConsumer = InputConsumer.NO_OP;
|
||||
private Choreographer mMainChoreographer;
|
||||
private InputConsumer mResetGestureInputConsumer;
|
||||
private GestureState mGestureState = new GestureState();
|
||||
|
||||
private InputMonitorCompat mInputMonitorCompat;
|
||||
private InputEventReceiver mInputEventReceiver;
|
||||
|
@ -360,7 +355,6 @@ public class TouchInteractionService extends Service implements
|
|||
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
||||
null, () -> {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
sSwipeSharedState.clearAllState();
|
||||
});
|
||||
} else {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
|
@ -440,15 +434,13 @@ public class TouchInteractionService extends Service implements
|
|||
MotionEvent event = (MotionEvent) ev;
|
||||
if (event.getAction() == ACTION_DOWN) {
|
||||
GestureState newGestureState = new GestureState(
|
||||
mOverviewComponentObserver.getActivityInterface());
|
||||
|
||||
mLogId = ActiveGestureLog.INSTANCE.generateAndSetLogId();
|
||||
sSwipeSharedState.setLogTraceId(mLogId);
|
||||
mOverviewComponentObserver.getActivityInterface(),
|
||||
ActiveGestureLog.INSTANCE.generateAndSetLogId());
|
||||
|
||||
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
|
||||
boolean useSharedState = mConsumer.useSharedSwipeState();
|
||||
mConsumer.onConsumerAboutToBeSwitched();
|
||||
mConsumer = newConsumer(newGestureState, useSharedState, event);
|
||||
mConsumer = newConsumer(mGestureState, newGestureState, event);
|
||||
|
||||
ActiveGestureLog.INSTANCE.addLog("setInputConsumer", mConsumer.getType());
|
||||
mUncheckedConsumer = mConsumer;
|
||||
} else if (mDeviceState.isUserUnlocked() && mMode == Mode.NO_BUTTON
|
||||
|
@ -461,6 +453,9 @@ public class TouchInteractionService extends Service implements
|
|||
} else {
|
||||
mUncheckedConsumer = InputConsumer.NO_OP;
|
||||
}
|
||||
|
||||
// Save the current gesture state
|
||||
mGestureState = newGestureState;
|
||||
}
|
||||
|
||||
ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
|
||||
|
@ -468,39 +463,42 @@ public class TouchInteractionService extends Service implements
|
|||
TraceHelper.INSTANCE.endFlagsOverride(traceToken);
|
||||
}
|
||||
|
||||
private InputConsumer newConsumer(GestureState gestureState, boolean useSharedState,
|
||||
MotionEvent event) {
|
||||
private InputConsumer newConsumer(GestureState previousGestureState,
|
||||
GestureState newGestureState, MotionEvent event) {
|
||||
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
|
||||
|
||||
if (!mDeviceState.isUserUnlocked()) {
|
||||
if (canStartSystemGesture) {
|
||||
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
|
||||
// launched while device is locked even after exiting direct boot mode (e.g. camera).
|
||||
return createDeviceLockedInputConsumer(gestureState,
|
||||
return createDeviceLockedInputConsumer(newGestureState,
|
||||
mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
|
||||
} else {
|
||||
return mResetGestureInputConsumer;
|
||||
}
|
||||
}
|
||||
|
||||
// When using sharedState, bypass systemState check as this is a followup gesture and the
|
||||
// first gesture started in a valid system state.
|
||||
InputConsumer base = canStartSystemGesture || useSharedState
|
||||
? newBaseConsumer(gestureState, useSharedState, event) : mResetGestureInputConsumer;
|
||||
// When there is an existing recents animation running, bypass systemState check as this is
|
||||
// a followup gesture and the first gesture started in a valid system state.
|
||||
InputConsumer base = canStartSystemGesture
|
||||
|| previousGestureState.isRecentsAnimationRunning()
|
||||
? newBaseConsumer(previousGestureState, newGestureState, event)
|
||||
: mResetGestureInputConsumer;
|
||||
if (mMode == Mode.NO_BUTTON) {
|
||||
if (mDeviceState.canTriggerAssistantAction(event)) {
|
||||
base = new AssistantInputConsumer(this, gestureState, base, mInputMonitorCompat);
|
||||
base = new AssistantInputConsumer(this, newGestureState, base, mInputMonitorCompat);
|
||||
}
|
||||
|
||||
if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
|
||||
// Put the Compose gesture as higher priority than the Assistant or base gestures
|
||||
base = new QuickCaptureInputConsumer(this, gestureState, base, mInputMonitorCompat);
|
||||
base = new QuickCaptureInputConsumer(this, newGestureState, base,
|
||||
mInputMonitorCompat);
|
||||
}
|
||||
|
||||
if (mDeviceState.isScreenPinningActive()) {
|
||||
// Note: we only allow accessibility to wrap this, and it replaces the previous
|
||||
// base input consumer (which should be NO_OP anyway since topTaskLocked == true).
|
||||
base = new ScreenPinnedInputConsumer(this, gestureState);
|
||||
base = new ScreenPinnedInputConsumer(this, newGestureState);
|
||||
}
|
||||
|
||||
if (mDeviceState.isAccessibilityMenuAvailable()) {
|
||||
|
@ -515,14 +513,10 @@ public class TouchInteractionService extends Service implements
|
|||
return base;
|
||||
}
|
||||
|
||||
private InputConsumer newBaseConsumer(GestureState gestureState, boolean useSharedState,
|
||||
MotionEvent event) {
|
||||
private InputConsumer newBaseConsumer(GestureState previousGestureState,
|
||||
GestureState gestureState, MotionEvent event) {
|
||||
RunningTaskInfo runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(0));
|
||||
if (!useSharedState) {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
||||
sSwipeSharedState.clearAllState();
|
||||
}
|
||||
if (mDeviceState.isKeyguardShowingOccluded()) {
|
||||
// This handles apps showing over the lockscreen (e.g. camera)
|
||||
return createDeviceLockedInputConsumer(gestureState, runningTaskInfo);
|
||||
|
@ -543,26 +537,27 @@ public class TouchInteractionService extends Service implements
|
|||
}
|
||||
}
|
||||
|
||||
if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
|
||||
&& !sSwipeSharedState.recentsAnimationFinishInterrupted) {
|
||||
return mResetGestureInputConsumer;
|
||||
} else if (sSwipeSharedState.recentsAnimationFinishInterrupted) {
|
||||
if (previousGestureState.getFinishingRecentsAnimationTaskId() > 0) {
|
||||
// If the finish animation was interrupted, then continue using the other activity input
|
||||
// consumer but with the next task as the running task
|
||||
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||
info.id = sSwipeSharedState.nextRunningTaskId;
|
||||
return createOtherActivityInputConsumer(gestureState, event, info);
|
||||
} else if (sSwipeSharedState.goingToLauncher
|
||||
info.id = previousGestureState.getFinishingRecentsAnimationTaskId();
|
||||
return createOtherActivityInputConsumer(previousGestureState, gestureState, event,
|
||||
info);
|
||||
} else if (runningTaskInfo == null) {
|
||||
return mResetGestureInputConsumer;
|
||||
} else if (previousGestureState.isRunningAnimationToLauncher()
|
||||
|| gestureState.getActivityInterface().isResumed()
|
||||
|| forceOverviewInputConsumer) {
|
||||
return createOverviewInputConsumer(gestureState, event);
|
||||
return createOverviewInputConsumer(previousGestureState, gestureState, event);
|
||||
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get()
|
||||
&& gestureState.getActivityInterface().isInLiveTileMode()) {
|
||||
return createOverviewInputConsumer(gestureState, event);
|
||||
return createOverviewInputConsumer(previousGestureState, gestureState, event);
|
||||
} else if (mDeviceState.isGestureBlockedActivity(runningTaskInfo)) {
|
||||
return mResetGestureInputConsumer;
|
||||
} else {
|
||||
return createOtherActivityInputConsumer(gestureState, event, runningTaskInfo);
|
||||
return createOtherActivityInputConsumer(previousGestureState, gestureState, event,
|
||||
runningTaskInfo);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -572,14 +567,15 @@ public class TouchInteractionService extends Service implements
|
|||
&& (info.baseIntent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) != 0;
|
||||
}
|
||||
|
||||
private InputConsumer createOtherActivityInputConsumer(GestureState gestureState,
|
||||
private InputConsumer createOtherActivityInputConsumer(GestureState previousGestureState,
|
||||
GestureState gestureState,
|
||||
MotionEvent event, RunningTaskInfo runningTaskInfo) {
|
||||
|
||||
final boolean shouldDefer;
|
||||
final BaseSwipeUpHandler.Factory factory;
|
||||
|
||||
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||
shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
|
||||
shouldDefer = previousGestureState.getFinishingRecentsAnimationTaskId() < 0;
|
||||
factory = mFallbackNoButtonFactory;
|
||||
} else {
|
||||
shouldDefer = gestureState.getActivityInterface().deferStartingActivity(mDeviceState,
|
||||
|
@ -590,26 +586,28 @@ public class TouchInteractionService extends Service implements
|
|||
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
|
||||
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, runningTaskInfo, shouldDefer, this::onConsumerInactive,
|
||||
sSwipeSharedState, mInputMonitorCompat, disableHorizontalSwipe, factory, mLogId);
|
||||
mInputMonitorCompat, disableHorizontalSwipe, factory);
|
||||
}
|
||||
|
||||
private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState,
|
||||
RunningTaskInfo taskInfo) {
|
||||
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
|
||||
return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, sSwipeSharedState, mInputMonitorCompat, taskInfo.taskId, mLogId);
|
||||
gestureState, mInputMonitorCompat, taskInfo.taskId);
|
||||
} else {
|
||||
return mResetGestureInputConsumer;
|
||||
}
|
||||
}
|
||||
|
||||
public InputConsumer createOverviewInputConsumer(GestureState gestureState, MotionEvent event) {
|
||||
public InputConsumer createOverviewInputConsumer(GestureState previousGestureState,
|
||||
GestureState gestureState, MotionEvent event) {
|
||||
BaseDraggingActivity activity = gestureState.getActivityInterface().getCreatedActivity();
|
||||
if (activity == null) {
|
||||
return mResetGestureInputConsumer;
|
||||
}
|
||||
|
||||
if (activity.getRootView().hasWindowFocus() || sSwipeSharedState.goingToLauncher) {
|
||||
if (activity.getRootView().hasWindowFocus()
|
||||
|| previousGestureState.isRunningAnimationToLauncher()) {
|
||||
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
|
||||
false /* startingInActivityBounds */);
|
||||
} else {
|
||||
|
@ -704,10 +702,6 @@ public class TouchInteractionService extends Service implements
|
|||
boolean resumed = mOverviewComponentObserver != null
|
||||
&& mOverviewComponentObserver.getActivityInterface().isResumed();
|
||||
pw.println(" resumed=" + resumed);
|
||||
pw.println(" useSharedState=" + mConsumer.useSharedSwipeState());
|
||||
if (mConsumer.useSharedSwipeState()) {
|
||||
sSwipeSharedState.dump(" ", pw);
|
||||
}
|
||||
pw.println(" mConsumer=" + mConsumer.getName());
|
||||
pw.println("FeatureFlags:");
|
||||
pw.println(" APPLY_CONFIG_AT_RUNTIME=" + APPLY_CONFIG_AT_RUNTIME.get());
|
||||
|
|
|
@ -26,11 +26,12 @@ import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
|||
import static com.android.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
||||
import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.HIDE;
|
||||
import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.GestureState.STATE_END_TARGET_ANIMATION_FINISHED;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
@ -70,6 +71,7 @@ import com.android.launcher3.util.TraceHelper;
|
|||
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
|
||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState;
|
||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
|
@ -138,42 +140,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
private static final int LAUNCHER_UI_STATES =
|
||||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
|
||||
|
||||
public enum GestureEndTarget {
|
||||
HOME(1, STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT, true, false,
|
||||
ContainerType.WORKSPACE, false),
|
||||
|
||||
RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
|
||||
| STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER, true),
|
||||
|
||||
NEW_TASK(0, STATE_START_NEW_TASK | STATE_CAPTURE_SCREENSHOT, false, true,
|
||||
ContainerType.APP, true),
|
||||
|
||||
LAST_TASK(0, STATE_RESUME_LAST_TASK, false, true, ContainerType.APP, false);
|
||||
|
||||
GestureEndTarget(float endShift, int endState, boolean isLauncher, boolean canBeContinued,
|
||||
int containerType, boolean recentsAttachedToAppWindow) {
|
||||
this.endShift = endShift;
|
||||
this.endState = endState;
|
||||
this.isLauncher = isLauncher;
|
||||
this.canBeContinued = canBeContinued;
|
||||
this.containerType = containerType;
|
||||
this.recentsAttachedToAppWindow = recentsAttachedToAppWindow;
|
||||
}
|
||||
|
||||
/** 0 is app, 1 is overview */
|
||||
public final float endShift;
|
||||
/** The state to apply when we reach this final target */
|
||||
public final int endState;
|
||||
/** Whether the target is in the launcher activity */
|
||||
public final boolean isLauncher;
|
||||
/** Whether the user can start a new gesture while this one is finishing */
|
||||
public final boolean canBeContinued;
|
||||
/** Used to log where the user ended up after the gesture ends */
|
||||
public final int containerType;
|
||||
/** Whether RecentsView should be attached to the window as we animate to this target */
|
||||
public final boolean recentsAttachedToAppWindow;
|
||||
}
|
||||
|
||||
public static final long MAX_SWIPE_DURATION = 350;
|
||||
public static final long MIN_SWIPE_DURATION = 80;
|
||||
public static final long MIN_OVERSHOOT_DURATION = 120;
|
||||
|
@ -195,7 +161,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
private final GestureState mGestureState;
|
||||
|
||||
private GestureEndTarget mGestureEndTarget;
|
||||
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
|
||||
private RunningWindowAnim mRunningWindowAnim;
|
||||
private boolean mIsShelfPeeking;
|
||||
|
@ -287,6 +252,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
| STATE_GESTURE_STARTED,
|
||||
this::setupLauncherUiAfterSwipeUpToRecentsAnimation);
|
||||
|
||||
mGestureState.addCallback(STATE_END_TARGET_ANIMATION_FINISHED,
|
||||
this::onEndTargetSet);
|
||||
|
||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
|
||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::invalidateHandlerWithLauncher);
|
||||
|
@ -338,7 +306,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mGestureEndTarget != HOME;
|
||||
return mGestureState.getEndTarget() != HOME;
|
||||
}
|
||||
|
||||
private void onLauncherStart(final T activity) {
|
||||
|
@ -351,7 +319,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
// If we've already ended the gesture and are going home, don't prepare recents UI,
|
||||
// as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
|
||||
if (mGestureEndTarget != HOME) {
|
||||
if (mGestureState.getEndTarget() != HOME) {
|
||||
Runnable initAnimFactory = () -> {
|
||||
mAnimationFactory = mActivityInterface.prepareRecentsUI(mActivity,
|
||||
mWasLauncherAlreadyVisible, true,
|
||||
|
@ -419,7 +387,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
||||
null, () -> {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
TouchInteractionService.getSwipeSharedState().clearAllState();
|
||||
});
|
||||
} else {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
|
@ -460,13 +427,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
.getHighResLoadingState().setVisible(true);
|
||||
}
|
||||
|
||||
private float getTaskCurveScaleForOffsetX(float offsetX, float taskWidth) {
|
||||
float distanceToReachEdge = mDp.widthPx / 2 + taskWidth / 2 +
|
||||
mContext.getResources().getDimensionPixelSize(R.dimen.recents_page_spacing);
|
||||
float interpolation = Math.min(1, offsetX / distanceToReachEdge);
|
||||
return TaskView.getCurveScaleForInterpolation(interpolation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
|
||||
|
@ -491,9 +451,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
? null
|
||||
: mRecentsAnimationTargets.findTask(mRunningTaskId);
|
||||
final boolean recentsAttachedToAppWindow;
|
||||
int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||
if (mGestureEndTarget != null) {
|
||||
recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow;
|
||||
if (mGestureState.getEndTarget() != null) {
|
||||
recentsAttachedToAppWindow = mGestureState.getEndTarget().recentsAttachedToAppWindow;
|
||||
} else if (mContinuingLastGesture
|
||||
&& mRecentsView.getRunningTaskIndex() != mRecentsView.getNextPage()) {
|
||||
recentsAttachedToAppWindow = true;
|
||||
|
@ -540,9 +499,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
|
||||
private void buildAnimationController() {
|
||||
if (mGestureEndTarget == HOME || mHasLauncherTransitionControllerStarted) {
|
||||
// We don't want a new mLauncherTransitionController if mGestureEndTarget == HOME (it
|
||||
// has its own animation) or if we're already animating the current controller.
|
||||
if (mGestureState.getEndTarget() == HOME || mHasLauncherTransitionControllerStarted) {
|
||||
// We don't want a new mLauncherTransitionController if
|
||||
// mGestureState.getEndTarget() == HOME (it has its own animation) or if we're already
|
||||
// animating the current controller.
|
||||
return;
|
||||
}
|
||||
initTransitionEndpoints(mActivity.getDeviceProfile());
|
||||
|
@ -599,7 +559,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
|
||||
private void updateLauncherTransitionProgress() {
|
||||
if (mGestureEndTarget == HOME) {
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
return;
|
||||
}
|
||||
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
|
||||
|
@ -709,7 +669,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
endRunningWindowAnim(mGestureEndTarget == HOME /* cancel */);
|
||||
endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
|
||||
endLauncherTransitionController();
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// Hide the task view, if not already hidden
|
||||
|
@ -731,6 +691,24 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
}
|
||||
|
||||
private void onEndTargetSet() {
|
||||
switch (mGestureState.getEndTarget()) {
|
||||
case HOME:
|
||||
mStateCallback.setState(STATE_SCALED_CONTROLLER_HOME | STATE_CAPTURE_SCREENSHOT);
|
||||
break;
|
||||
case RECENTS:
|
||||
mStateCallback.setState(STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT
|
||||
| STATE_SCREENSHOT_VIEW_SHOWN);
|
||||
break;
|
||||
case NEW_TASK:
|
||||
mStateCallback.setState(STATE_START_NEW_TASK | STATE_CAPTURE_SCREENSHOT);
|
||||
break;
|
||||
case LAST_TASK:
|
||||
mStateCallback.setState(STATE_RESUME_LAST_TASK);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling,
|
||||
boolean isCancel) {
|
||||
final GestureEndTarget endTarget;
|
||||
|
@ -800,7 +778,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
float currentShift = mCurrentShift.value;
|
||||
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
|
||||
isFling, isCancel);
|
||||
float endShift = endTarget.endShift;
|
||||
float endShift = endTarget.isLauncher ? 1 : 0;
|
||||
final float startShift;
|
||||
Interpolator interpolator = DEACCEL;
|
||||
if (!isFling) {
|
||||
|
@ -903,11 +881,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
@UiThread
|
||||
private void animateToProgressInternal(float start, float end, long duration,
|
||||
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
|
||||
mGestureEndTarget = target;
|
||||
// Set the state, but don't notify until the animation completes
|
||||
mGestureState.setEndTarget(target, false /* isAtomic */);
|
||||
|
||||
maybeUpdateRecentsAttachedState();
|
||||
|
||||
if (mGestureEndTarget == HOME) {
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
HomeAnimationFactory homeAnimFactory;
|
||||
if (mActivity != null) {
|
||||
homeAnimFactory = mActivityInterface.prepareHomeUI(mActivity);
|
||||
|
@ -934,7 +913,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
setStateOnUiThread(target.endState);
|
||||
// Finalize the state and notify of the change
|
||||
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
|
||||
}
|
||||
});
|
||||
windowAnim.start(velocityPxPerMs);
|
||||
|
@ -959,10 +939,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
// We are about to launch the current running task, so use LAST_TASK state
|
||||
// instead of NEW_TASK. This could happen, for example, if our scroll is
|
||||
// aborted after we determined the target to be NEW_TASK.
|
||||
setStateOnUiThread(LAST_TASK.endState);
|
||||
} else {
|
||||
setStateOnUiThread(target.endState);
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
}
|
||||
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
|
||||
}
|
||||
});
|
||||
windowAnim.start();
|
||||
|
@ -970,7 +949,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
// Always play the entire launcher animation when going home, since it is separate from
|
||||
// the animation that has been controlled thus far.
|
||||
if (mGestureEndTarget == HOME) {
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
start = 0;
|
||||
}
|
||||
|
||||
|
@ -1029,14 +1008,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
||||
if (mGestureEndTarget != null) {
|
||||
sharedState.canGestureBeContinued = mGestureEndTarget.canBeContinued;
|
||||
sharedState.goingToLauncher = mGestureEndTarget.isLauncher;
|
||||
}
|
||||
|
||||
if (sharedState.canGestureBeContinued) {
|
||||
cancelCurrentAnimation(sharedState);
|
||||
public void onConsumerAboutToBeSwitched() {
|
||||
if (!mGestureState.isRunningAnimationToLauncher()) {
|
||||
cancelCurrentAnimation();
|
||||
} else {
|
||||
reset();
|
||||
}
|
||||
|
@ -1075,7 +1049,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
* Cancels any running animation so that the active target can be overriden by a new swipe
|
||||
* handle (in case of quick switch).
|
||||
*/
|
||||
private void cancelCurrentAnimation(SwipeSharedState sharedState) {
|
||||
private void cancelCurrentAnimation() {
|
||||
mCanceled = true;
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mLauncherTransitionController != null && mLauncherTransitionController
|
||||
|
@ -1093,7 +1067,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
? newRunningTaskView.getTask().key.id
|
||||
: -1;
|
||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||
sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
|
||||
mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1160,7 +1134,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
mTaskSnapshot = mRecentsAnimationController.screenshotTask(mRunningTaskId);
|
||||
}
|
||||
final TaskView taskView;
|
||||
if (mGestureEndTarget == HOME) {
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
// Capture the screenshot before finishing the transition to home to ensure it's
|
||||
// taken in the correct orientation, but no need to update the thumbnail.
|
||||
taskView = null;
|
||||
|
|
|
@ -22,11 +22,6 @@ public abstract class DelegateInputConsumer implements InputConsumer {
|
|||
mState = STATE_INACTIVE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useSharedSwipeState() {
|
||||
return mDelegate.useSharedSwipeState();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInterceptByParent() {
|
||||
return mDelegate.allowInterceptByParent() && mState != STATE_ACTIVE;
|
||||
|
|
|
@ -44,7 +44,6 @@ import com.android.quickstep.LockScreenRecentsActivity;
|
|||
import com.android.quickstep.MultiStateCallback;
|
||||
import com.android.quickstep.RecentsAnimationController;
|
||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.RecentsAnimationTargets;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
|
@ -79,12 +78,10 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
private final GestureState mGestureState;
|
||||
private final float mTouchSlopSquared;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
private final InputMonitorCompat mInputMonitorCompat;
|
||||
|
||||
private final PointF mTouchDown = new PointF();
|
||||
private final AppWindowAnimationHelper mAppWindowAnimationHelper;
|
||||
private int mLogId;
|
||||
private final AppWindowAnimationHelper.TransformParams mTransformParams;
|
||||
private final Point mDisplaySize;
|
||||
private final MultiStateCallback mStateCallback;
|
||||
|
@ -100,16 +97,13 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
|
||||
public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
||||
int runningTaskId, int logId) {
|
||||
InputMonitorCompat inputMonitorCompat, int runningTaskId) {
|
||||
mContext = context;
|
||||
mDeviceState = deviceState;
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mGestureState = gestureState;
|
||||
mTouchSlopSquared = squaredTouchSlop(context);
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
|
||||
mLogId = logId;
|
||||
mTransformParams = new AppWindowAnimationHelper.TransformParams();
|
||||
mInputMonitorCompat = inputMonitorCompat;
|
||||
mRunningTaskId = runningTaskId;
|
||||
|
@ -216,7 +210,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
.addCategory(Intent.CATEGORY_DEFAULT)
|
||||
.setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
|
||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
||||
.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
|
||||
.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mGestureState.getGestureId());
|
||||
mTaskAnimationManager.startRecentsAnimation(mGestureState, intent, this);
|
||||
}
|
||||
|
||||
|
|
|
@ -15,14 +15,14 @@
|
|||
*/
|
||||
package com.android.quickstep.inputconsumers;
|
||||
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
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.NEW_TASK;
|
||||
import static com.android.quickstep.inputconsumers.FallbackNoButtonInputConsumer.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
@ -35,6 +35,7 @@ import android.graphics.PointF;
|
|||
import android.graphics.RectF;
|
||||
import android.os.Bundle;
|
||||
|
||||
import android.util.ArrayMap;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
|
@ -43,13 +44,13 @@ import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
|||
import com.android.quickstep.AnimatedFloat;
|
||||
import com.android.quickstep.BaseSwipeUpHandler;
|
||||
import com.android.quickstep.GestureState;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.MultiStateCallback;
|
||||
import com.android.quickstep.OverviewComponentObserver;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.RecentsAnimationController;
|
||||
import com.android.quickstep.RecentsModel;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.RecentsAnimationTargets;
|
||||
|
@ -83,27 +84,23 @@ public class FallbackNoButtonInputConsumer extends
|
|||
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
||||
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
|
||||
|
||||
public enum GestureEndTarget {
|
||||
HOME(3, 100, 1),
|
||||
RECENTS(1, 300, 0),
|
||||
LAST_TASK(0, 150, 1),
|
||||
NEW_TASK(0, 150, 1);
|
||||
|
||||
public static class EndTargetAnimationParams {
|
||||
private final float mEndProgress;
|
||||
private final long mDurationMultiplier;
|
||||
private final float mLauncherAlpha;
|
||||
|
||||
GestureEndTarget(float endProgress, long durationMultiplier, float launcherAlpha) {
|
||||
EndTargetAnimationParams(float endProgress, long durationMultiplier, float launcherAlpha) {
|
||||
mEndProgress = endProgress;
|
||||
mDurationMultiplier = durationMultiplier;
|
||||
mLauncherAlpha = launcherAlpha;
|
||||
}
|
||||
}
|
||||
private static ArrayMap<GestureEndTarget, EndTargetAnimationParams>
|
||||
mEndTargetAnimationParams = new ArrayMap();
|
||||
|
||||
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
|
||||
|
||||
private boolean mIsMotionPaused = false;
|
||||
private GestureEndTarget mEndTarget;
|
||||
|
||||
private final boolean mInQuickSwitchMode;
|
||||
private final boolean mContinuingLastGesture;
|
||||
|
@ -136,6 +133,12 @@ public class FallbackNoButtonInputConsumer extends
|
|||
mAppWindowAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
||||
}
|
||||
|
||||
// Going home has an extra long progress to ensure that it animates into the screen
|
||||
mEndTargetAnimationParams.put(HOME, new EndTargetAnimationParams(3, 100, 1));
|
||||
mEndTargetAnimationParams.put(RECENTS, new EndTargetAnimationParams(1, 300, 0));
|
||||
mEndTargetAnimationParams.put(LAST_TASK, new EndTargetAnimationParams(0, 150, 1));
|
||||
mEndTargetAnimationParams.put(NEW_TASK, new EndTargetAnimationParams(0, 150, 1));
|
||||
|
||||
initStateCallbacks();
|
||||
}
|
||||
|
||||
|
@ -161,7 +164,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
}
|
||||
|
||||
private void onLauncherAlphaChanged() {
|
||||
if (mRecentsAnimationTargets != null && mEndTarget == null) {
|
||||
if (mRecentsAnimationTargets != null && mGestureState.getEndTarget() == null) {
|
||||
applyTransformUnchecked();
|
||||
}
|
||||
}
|
||||
|
@ -247,7 +250,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
@Override
|
||||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
mEndTarget = LAST_TASK;
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||
}
|
||||
|
||||
|
@ -256,28 +259,29 @@ public class FallbackNoButtonInputConsumer extends
|
|||
mEndVelocityPxPerMs.set(0, velocity.y / 1000);
|
||||
if (mInQuickSwitchMode) {
|
||||
// For now set it to non-null, it will be reset before starting the animation
|
||||
mEndTarget = LAST_TASK;
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else {
|
||||
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;
|
||||
mGestureState.setEndTarget(endVelocity < 0 ? HOME : LAST_TASK);
|
||||
} else if (mIsMotionPaused) {
|
||||
mEndTarget = RECENTS;
|
||||
mGestureState.setEndTarget(RECENTS);
|
||||
} else {
|
||||
mEndTarget = mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW ? HOME : LAST_TASK;
|
||||
mGestureState.setEndTarget(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW
|
||||
? HOME
|
||||
: LAST_TASK);
|
||||
}
|
||||
}
|
||||
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
||||
if (mInQuickSwitchMode && mEndTarget != null) {
|
||||
sharedState.canGestureBeContinued = true;
|
||||
sharedState.goingToLauncher = false;
|
||||
public void onConsumerAboutToBeSwitched() {
|
||||
if (mInQuickSwitchMode && mGestureState.getEndTarget() != null) {
|
||||
mGestureState.setEndTarget(HOME);
|
||||
|
||||
mCanceled = true;
|
||||
mCurrentShift.cancelAnimation();
|
||||
|
@ -293,7 +297,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
? newRunningTaskView.getTask().key.id
|
||||
: -1;
|
||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||
sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
|
||||
mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
|
||||
}
|
||||
mRecentsView.setOnScrollChangeListener(null);
|
||||
}
|
||||
|
@ -319,7 +323,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
}
|
||||
|
||||
private void finishAnimationTargetSetAnimationComplete() {
|
||||
switch (mEndTarget) {
|
||||
switch (mGestureState.getEndTarget()) {
|
||||
case HOME: {
|
||||
if (mSwipeUpOverHome) {
|
||||
mRecentsAnimationController.finish(false, null, false);
|
||||
|
@ -370,17 +374,20 @@ public class FallbackNoButtonInputConsumer extends
|
|||
// Recalculate the end target, some views might have been initialized after
|
||||
// gesture has ended.
|
||||
if (mRecentsView == null || !hasTargets()) {
|
||||
mEndTarget = LAST_TASK;
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else {
|
||||
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||
final int taskToLaunch = mRecentsView.getNextPage();
|
||||
mEndTarget = (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||
? NEW_TASK : LAST_TASK;
|
||||
mGestureState.setEndTarget(
|
||||
(runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||
? NEW_TASK
|
||||
: LAST_TASK);
|
||||
}
|
||||
}
|
||||
|
||||
float endProgress = mEndTarget.mEndProgress;
|
||||
long duration = (long) (mEndTarget.mDurationMultiplier *
|
||||
EndTargetAnimationParams params = mEndTargetAnimationParams.get(mGestureState.getEndTarget());
|
||||
float endProgress = params.mEndProgress;
|
||||
long duration = (long) (params.mDurationMultiplier *
|
||||
Math.abs(endProgress - mCurrentShift.value));
|
||||
if (mRecentsView != null) {
|
||||
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
|
||||
|
@ -395,7 +402,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
}
|
||||
};
|
||||
|
||||
if (mEndTarget == HOME && !mRunningOverHome) {
|
||||
if (mGestureState.getEndTarget() == HOME && !mRunningOverHome) {
|
||||
RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration);
|
||||
anim.addAnimatorListener(endListener);
|
||||
anim.start(mEndVelocityPxPerMs);
|
||||
|
@ -404,7 +411,7 @@ public class FallbackNoButtonInputConsumer extends
|
|||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(mLauncherAlpha.animateToValue(
|
||||
mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
|
||||
mLauncherAlpha.value, params.mLauncherAlpha));
|
||||
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
|
||||
|
||||
anim.setDuration(duration);
|
||||
|
|
|
@ -54,7 +54,6 @@ import com.android.quickstep.GestureState;
|
|||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
|
@ -85,7 +84,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
private RecentsAnimationCallbacks mActiveCallbacks;
|
||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||
private final RunningTaskInfo mRunningTask;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
private final InputMonitorCompat mInputMonitorCompat;
|
||||
private final SysUINavigationMode.Mode mMode;
|
||||
private final BaseActivityInterface mActivityInterface;
|
||||
|
@ -126,16 +124,14 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
|
||||
true /* restoreHomeStackPosition */);
|
||||
};
|
||||
private int mLogId;
|
||||
|
||||
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
RunningTaskInfo runningTaskInfo, boolean isDeferredDownTarget,
|
||||
Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
||||
boolean disableHorizontalSwipe, Factory handlerFactory, int logId) {
|
||||
InputMonitorCompat inputMonitorCompat, boolean disableHorizontalSwipe,
|
||||
Factory handlerFactory) {
|
||||
super(base);
|
||||
mLogId = logId;
|
||||
mDeviceState = deviceState;
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mGestureState = gestureState;
|
||||
|
@ -154,7 +150,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
|
||||
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
|
||||
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
|
||||
mNavBarPosition = new NavBarPosition(base);
|
||||
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
|
||||
|
@ -347,7 +342,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
notifyGestureStarted();
|
||||
} else {
|
||||
Intent intent = mInteractionHandler.getLaunchIntent();
|
||||
intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
|
||||
intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mGestureState.getGestureId());
|
||||
mActiveCallbacks = mTaskAnimationManager.startRecentsAnimation(mGestureState, intent,
|
||||
mInteractionHandler);
|
||||
}
|
||||
|
@ -404,7 +399,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();
|
||||
mInteractionHandler.onConsumerAboutToBeSwitched(mSwipeSharedState);
|
||||
mInteractionHandler.onConsumerAboutToBeSwitched();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -432,11 +427,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean useSharedSwipeState() {
|
||||
return mInteractionHandler != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean allowInterceptByParent() {
|
||||
return !mPassedPilferInputSlop;
|
||||
|
|
|
@ -42,7 +42,6 @@ public class ResetGestureInputConsumer implements InputConsumer {
|
|||
if (ev.getAction() == MotionEvent.ACTION_DOWN
|
||||
&& mTaskAnimationManager.isRecentsAnimationRunning()) {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
||||
TouchInteractionService.getSwipeSharedState().clearAllState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,8 +15,12 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Manages the state for an active system gesture, listens for events from the system and Launcher,
|
||||
|
@ -24,30 +28,202 @@ import com.android.systemui.shared.recents.model.ThumbnailData;
|
|||
*/
|
||||
public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
|
||||
// Needed to interact with the current activity
|
||||
private BaseActivityInterface mActivityInterface;
|
||||
/**
|
||||
* Defines the end targets of a gesture and the associated state.
|
||||
*/
|
||||
public enum GestureEndTarget {
|
||||
HOME(true, ContainerType.WORKSPACE, false),
|
||||
|
||||
public GestureState(BaseActivityInterface activityInterface) {
|
||||
mActivityInterface = activityInterface;
|
||||
RECENTS(true, ContainerType.TASKSWITCHER, true),
|
||||
|
||||
NEW_TASK(false, ContainerType.APP, true),
|
||||
|
||||
LAST_TASK(false, ContainerType.APP, false);
|
||||
|
||||
GestureEndTarget(boolean isLauncher, int containerType,
|
||||
boolean recentsAttachedToAppWindow) {
|
||||
this.isLauncher = isLauncher;
|
||||
this.containerType = containerType;
|
||||
this.recentsAttachedToAppWindow = recentsAttachedToAppWindow;
|
||||
}
|
||||
|
||||
/** Whether the target is in the launcher activity. Implicitly, if the end target is going
|
||||
to Launcher, then we can not interrupt the animation to start another gesture. */
|
||||
public final boolean isLauncher;
|
||||
/** Used to log where the user ended up after the gesture ends */
|
||||
public final int containerType;
|
||||
/** Whether RecentsView should be attached to the window as we animate to this target */
|
||||
public final boolean recentsAttachedToAppWindow;
|
||||
}
|
||||
|
||||
private static final ArrayList<String> STATE_NAMES = new ArrayList<>();
|
||||
private static int FLAG_COUNT = 0;
|
||||
private static int getFlagForIndex(String name) {
|
||||
if (DEBUG_STATES) {
|
||||
STATE_NAMES.add(name);
|
||||
}
|
||||
int index = 1 << FLAG_COUNT;
|
||||
FLAG_COUNT++;
|
||||
return index;
|
||||
}
|
||||
|
||||
// Called when the end target as been set
|
||||
public static final int STATE_END_TARGET_SET =
|
||||
getFlagForIndex("STATE_END_TARGET_SET");
|
||||
|
||||
// Called when the end target animation has finished
|
||||
public static final int STATE_END_TARGET_ANIMATION_FINISHED =
|
||||
getFlagForIndex("STATE_END_TARGET_ANIMATION_FINISHED");
|
||||
|
||||
// Called when the recents animation has been requested to start
|
||||
public static final int STATE_RECENTS_ANIMATION_INITIALIZED =
|
||||
getFlagForIndex("STATE_RECENTS_ANIMATION_INITIALIZED");
|
||||
|
||||
// Called when the recents animation is started and the TaskAnimationManager has been updated
|
||||
// with the controller and targets
|
||||
public static final int STATE_RECENTS_ANIMATION_STARTED =
|
||||
getFlagForIndex("STATE_RECENTS_ANIMATION_STARTED");
|
||||
|
||||
// Called when the recents animation is canceled
|
||||
public static final int STATE_RECENTS_ANIMATION_CANCELED =
|
||||
getFlagForIndex("STATE_RECENTS_ANIMATION_CANCELED");
|
||||
|
||||
// Called when the recents animation finishes
|
||||
public static final int STATE_RECENTS_ANIMATION_FINISHED =
|
||||
getFlagForIndex("STATE_RECENTS_ANIMATION_FINISHED");
|
||||
|
||||
// Always called when the recents animation ends (regardless of cancel or finish)
|
||||
public static final int STATE_RECENTS_ANIMATION_ENDED =
|
||||
getFlagForIndex("STATE_RECENTS_ANIMATION_ENDED");
|
||||
|
||||
|
||||
// Needed to interact with the current activity
|
||||
private final BaseActivityInterface mActivityInterface;
|
||||
private final MultiStateCallback mStateCallback;
|
||||
private final int mGestureId;
|
||||
|
||||
private GestureEndTarget mEndTarget;
|
||||
// TODO: This can be removed once we stop finishing the animation when starting a new task
|
||||
private int mFinishingRecentsAnimationTaskId = -1;
|
||||
|
||||
public GestureState(BaseActivityInterface activityInterface, int gestureId) {
|
||||
mActivityInterface = activityInterface;
|
||||
mGestureId = gestureId;
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES.toArray(new String[0]));
|
||||
}
|
||||
|
||||
public GestureState() {
|
||||
// Do nothing, only used for initializing the gesture state prior to user unlock
|
||||
mActivityInterface = null;
|
||||
mGestureId = -1;
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES.toArray(new String[0]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the given {@param stateFlag}s.
|
||||
*/
|
||||
public void setState(int stateFlag) {
|
||||
mStateCallback.setState(stateFlag);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a callback for when the states matching the given {@param stateMask} is set.
|
||||
*/
|
||||
public void addCallback(int stateMask, Runnable callback) {
|
||||
mStateCallback.addCallback(stateMask, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the interface to the activity handing the UI updates for this gesture.
|
||||
*/
|
||||
public <T extends BaseDraggingActivity> BaseActivityInterface<T> getActivityInterface() {
|
||||
return mActivityInterface;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id for this particular gesture.
|
||||
*/
|
||||
public int getGestureId() {
|
||||
return mGestureId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the end target for this gesture (if known).
|
||||
*/
|
||||
public GestureEndTarget getEndTarget() {
|
||||
return mEndTarget;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the current gesture is still running a recents animation to a state in the
|
||||
* Launcher or Recents activity.
|
||||
*/
|
||||
public boolean isRunningAnimationToLauncher() {
|
||||
return isRecentsAnimationRunning() && mEndTarget != null && mEndTarget.isLauncher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the end target of this gesture and immediately notifies the state changes.
|
||||
*/
|
||||
public void setEndTarget(GestureEndTarget target) {
|
||||
setEndTarget(target, true /* isAtomic */);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the end target of this gesture, but if {@param isAtomic} is {@code false}, then the
|
||||
* caller must explicitly set {@link #STATE_END_TARGET_ANIMATION_FINISHED} themselves.
|
||||
*/
|
||||
public void setEndTarget(GestureEndTarget target, boolean isAtomic) {
|
||||
mEndTarget = target;
|
||||
mStateCallback.setState(STATE_END_TARGET_SET);
|
||||
if (isAtomic) {
|
||||
mStateCallback.setState(STATE_END_TARGET_ANIMATION_FINISHED);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the id for the task that was about to be launched following the finish of the recents
|
||||
* animation. Only defined between when the finish-recents call was made and the launch
|
||||
* activity call is made.
|
||||
*/
|
||||
public int getFinishingRecentsAnimationTaskId() {
|
||||
return mFinishingRecentsAnimationTaskId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id for the task will be launched after the recents animation is finished. Once the
|
||||
* animation has finished then the id will be reset to -1.
|
||||
*/
|
||||
public void setFinishingRecentsAnimationTaskId(int taskId) {
|
||||
mFinishingRecentsAnimationTaskId = taskId;
|
||||
mStateCallback.addCallback(STATE_RECENTS_ANIMATION_FINISHED, () -> {
|
||||
mFinishingRecentsAnimationTaskId = -1;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the recents animation is started but not yet ended
|
||||
*/
|
||||
public boolean isRecentsAnimationRunning() {
|
||||
return mStateCallback.hasStates(STATE_RECENTS_ANIMATION_INITIALIZED) &&
|
||||
!mStateCallback.hasStates(STATE_RECENTS_ANIMATION_ENDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||
RecentsAnimationTargets targets) {
|
||||
// To be implemented
|
||||
mStateCallback.setState(STATE_RECENTS_ANIMATION_STARTED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
// To be implemented
|
||||
mStateCallback.setState(STATE_RECENTS_ANIMATION_CANCELED);
|
||||
mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
// To be implemented
|
||||
mStateCallback.setState(STATE_RECENTS_ANIMATION_FINISHED);
|
||||
mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -52,10 +52,6 @@ public interface InputConsumer {
|
|||
|
||||
int getType();
|
||||
|
||||
default boolean useSharedSwipeState() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the user has crossed the threshold for it to be an explicit action.
|
||||
*/
|
||||
|
@ -65,6 +61,8 @@ public interface InputConsumer {
|
|||
|
||||
/**
|
||||
* Called by the event queue when the consumer is about to be switched to a new consumer.
|
||||
* Consumers should update the state accordingly here before the state is passed to the new
|
||||
* consumer.
|
||||
*/
|
||||
default void onConsumerAboutToBeSwitched() { }
|
||||
|
||||
|
|
|
@ -17,6 +17,7 @@ package com.android.quickstep;
|
|||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
import static com.android.quickstep.GestureState.STATE_RECENTS_ANIMATION_INITIALIZED;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
@ -95,6 +96,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
|||
mCallbacks.addListener(listener);
|
||||
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
||||
.startRecentsActivity(intent, null, mCallbacks, null, null));
|
||||
gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED);
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue