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.Launcher;
|
||||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||||
|
import com.android.quickstep.GestureState;
|
||||||
import com.android.quickstep.views.RecentsView;
|
import com.android.quickstep.views.RecentsView;
|
||||||
import com.android.quickstep.views.TaskView;
|
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
|
* 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.
|
* 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 {
|
public class QuickSwitchState extends BackgroundAppState {
|
||||||
|
|
||||||
|
|
|
@ -96,6 +96,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||||
protected float mDragLengthFactor = 1;
|
protected float mDragLengthFactor = 1;
|
||||||
|
|
||||||
protected final Context mContext;
|
protected final Context mContext;
|
||||||
|
protected final GestureState mGestureState;
|
||||||
protected final OverviewComponentObserver mOverviewComponentObserver;
|
protected final OverviewComponentObserver mOverviewComponentObserver;
|
||||||
protected final BaseActivityInterface<T> mActivityInterface;
|
protected final BaseActivityInterface<T> mActivityInterface;
|
||||||
protected final RecentsModel mRecentsModel;
|
protected final RecentsModel mRecentsModel;
|
||||||
|
@ -139,6 +140,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||||
OverviewComponentObserver overviewComponentObserver,
|
OverviewComponentObserver overviewComponentObserver,
|
||||||
RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
|
RecentsModel recentsModel, InputConsumerController inputConsumer, int runningTaskId) {
|
||||||
mContext = context;
|
mContext = context;
|
||||||
|
mGestureState = gestureState;
|
||||||
mOverviewComponentObserver = overviewComponentObserver;
|
mOverviewComponentObserver = overviewComponentObserver;
|
||||||
mActivityInterface = gestureState.getActivityInterface();
|
mActivityInterface = gestureState.getActivityInterface();
|
||||||
mRecentsModel = recentsModel;
|
mRecentsModel = recentsModel;
|
||||||
|
@ -394,7 +396,7 @@ public abstract class BaseSwipeUpHandler<T extends BaseDraggingActivity, Q exten
|
||||||
@UiThread
|
@UiThread
|
||||||
public abstract void onGestureEnded(float endVelocity, PointF velocity, PointF downPos);
|
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) { }
|
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 sConnected = false;
|
||||||
private static boolean sIsInitialized = false;
|
private static boolean sIsInitialized = false;
|
||||||
private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState();
|
|
||||||
private int mLogId;
|
|
||||||
|
|
||||||
public static boolean isConnected() {
|
public static boolean isConnected() {
|
||||||
return sConnected;
|
return sConnected;
|
||||||
|
@ -246,10 +244,6 @@ public class TouchInteractionService extends Service implements
|
||||||
return sIsInitialized;
|
return sIsInitialized;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SwipeSharedState getSwipeSharedState() {
|
|
||||||
return sSwipeSharedState;
|
|
||||||
}
|
|
||||||
|
|
||||||
private final BaseSwipeUpHandler.Factory mWindowTransformFactory =
|
private final BaseSwipeUpHandler.Factory mWindowTransformFactory =
|
||||||
this::createWindowTransformSwipeHandler;
|
this::createWindowTransformSwipeHandler;
|
||||||
private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
|
private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
|
||||||
|
@ -267,6 +261,7 @@ public class TouchInteractionService extends Service implements
|
||||||
private InputConsumer mConsumer = InputConsumer.NO_OP;
|
private InputConsumer mConsumer = InputConsumer.NO_OP;
|
||||||
private Choreographer mMainChoreographer;
|
private Choreographer mMainChoreographer;
|
||||||
private InputConsumer mResetGestureInputConsumer;
|
private InputConsumer mResetGestureInputConsumer;
|
||||||
|
private GestureState mGestureState = new GestureState();
|
||||||
|
|
||||||
private InputMonitorCompat mInputMonitorCompat;
|
private InputMonitorCompat mInputMonitorCompat;
|
||||||
private InputEventReceiver mInputEventReceiver;
|
private InputEventReceiver mInputEventReceiver;
|
||||||
|
@ -360,7 +355,6 @@ public class TouchInteractionService extends Service implements
|
||||||
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
||||||
null, () -> {
|
null, () -> {
|
||||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||||
sSwipeSharedState.clearAllState();
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||||
|
@ -440,15 +434,13 @@ public class TouchInteractionService extends Service implements
|
||||||
MotionEvent event = (MotionEvent) ev;
|
MotionEvent event = (MotionEvent) ev;
|
||||||
if (event.getAction() == ACTION_DOWN) {
|
if (event.getAction() == ACTION_DOWN) {
|
||||||
GestureState newGestureState = new GestureState(
|
GestureState newGestureState = new GestureState(
|
||||||
mOverviewComponentObserver.getActivityInterface());
|
mOverviewComponentObserver.getActivityInterface(),
|
||||||
|
ActiveGestureLog.INSTANCE.generateAndSetLogId());
|
||||||
mLogId = ActiveGestureLog.INSTANCE.generateAndSetLogId();
|
|
||||||
sSwipeSharedState.setLogTraceId(mLogId);
|
|
||||||
|
|
||||||
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
|
if (mDeviceState.isInSwipeUpTouchRegion(event)) {
|
||||||
boolean useSharedState = mConsumer.useSharedSwipeState();
|
|
||||||
mConsumer.onConsumerAboutToBeSwitched();
|
mConsumer.onConsumerAboutToBeSwitched();
|
||||||
mConsumer = newConsumer(newGestureState, useSharedState, event);
|
mConsumer = newConsumer(mGestureState, newGestureState, event);
|
||||||
|
|
||||||
ActiveGestureLog.INSTANCE.addLog("setInputConsumer", mConsumer.getType());
|
ActiveGestureLog.INSTANCE.addLog("setInputConsumer", mConsumer.getType());
|
||||||
mUncheckedConsumer = mConsumer;
|
mUncheckedConsumer = mConsumer;
|
||||||
} else if (mDeviceState.isUserUnlocked() && mMode == Mode.NO_BUTTON
|
} else if (mDeviceState.isUserUnlocked() && mMode == Mode.NO_BUTTON
|
||||||
|
@ -461,6 +453,9 @@ public class TouchInteractionService extends Service implements
|
||||||
} else {
|
} else {
|
||||||
mUncheckedConsumer = InputConsumer.NO_OP;
|
mUncheckedConsumer = InputConsumer.NO_OP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save the current gesture state
|
||||||
|
mGestureState = newGestureState;
|
||||||
}
|
}
|
||||||
|
|
||||||
ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
|
ActiveGestureLog.INSTANCE.addLog("onMotionEvent", event.getActionMasked());
|
||||||
|
@ -468,39 +463,42 @@ public class TouchInteractionService extends Service implements
|
||||||
TraceHelper.INSTANCE.endFlagsOverride(traceToken);
|
TraceHelper.INSTANCE.endFlagsOverride(traceToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputConsumer newConsumer(GestureState gestureState, boolean useSharedState,
|
private InputConsumer newConsumer(GestureState previousGestureState,
|
||||||
MotionEvent event) {
|
GestureState newGestureState, MotionEvent event) {
|
||||||
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
|
boolean canStartSystemGesture = mDeviceState.canStartSystemGesture();
|
||||||
|
|
||||||
if (!mDeviceState.isUserUnlocked()) {
|
if (!mDeviceState.isUserUnlocked()) {
|
||||||
if (canStartSystemGesture) {
|
if (canStartSystemGesture) {
|
||||||
// This handles apps launched in direct boot mode (e.g. dialer) as well as apps
|
// 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).
|
// 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));
|
mAM.getRunningTask(ACTIVITY_TYPE_ASSISTANT));
|
||||||
} else {
|
} else {
|
||||||
return mResetGestureInputConsumer;
|
return mResetGestureInputConsumer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// When using sharedState, bypass systemState check as this is a followup gesture and the
|
// When there is an existing recents animation running, bypass systemState check as this is
|
||||||
// first gesture started in a valid system state.
|
// a followup gesture and the first gesture started in a valid system state.
|
||||||
InputConsumer base = canStartSystemGesture || useSharedState
|
InputConsumer base = canStartSystemGesture
|
||||||
? newBaseConsumer(gestureState, useSharedState, event) : mResetGestureInputConsumer;
|
|| previousGestureState.isRecentsAnimationRunning()
|
||||||
|
? newBaseConsumer(previousGestureState, newGestureState, event)
|
||||||
|
: mResetGestureInputConsumer;
|
||||||
if (mMode == Mode.NO_BUTTON) {
|
if (mMode == Mode.NO_BUTTON) {
|
||||||
if (mDeviceState.canTriggerAssistantAction(event)) {
|
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()) {
|
if (FeatureFlags.ENABLE_QUICK_CAPTURE_GESTURE.get()) {
|
||||||
// Put the Compose gesture as higher priority than the Assistant or base gestures
|
// 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()) {
|
if (mDeviceState.isScreenPinningActive()) {
|
||||||
// Note: we only allow accessibility to wrap this, and it replaces the previous
|
// 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 input consumer (which should be NO_OP anyway since topTaskLocked == true).
|
||||||
base = new ScreenPinnedInputConsumer(this, gestureState);
|
base = new ScreenPinnedInputConsumer(this, newGestureState);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mDeviceState.isAccessibilityMenuAvailable()) {
|
if (mDeviceState.isAccessibilityMenuAvailable()) {
|
||||||
|
@ -515,14 +513,10 @@ public class TouchInteractionService extends Service implements
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputConsumer newBaseConsumer(GestureState gestureState, boolean useSharedState,
|
private InputConsumer newBaseConsumer(GestureState previousGestureState,
|
||||||
MotionEvent event) {
|
GestureState gestureState, MotionEvent event) {
|
||||||
RunningTaskInfo runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.0",
|
RunningTaskInfo runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||||
() -> mAM.getRunningTask(0));
|
() -> mAM.getRunningTask(0));
|
||||||
if (!useSharedState) {
|
|
||||||
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
|
||||||
sSwipeSharedState.clearAllState();
|
|
||||||
}
|
|
||||||
if (mDeviceState.isKeyguardShowingOccluded()) {
|
if (mDeviceState.isKeyguardShowingOccluded()) {
|
||||||
// This handles apps showing over the lockscreen (e.g. camera)
|
// This handles apps showing over the lockscreen (e.g. camera)
|
||||||
return createDeviceLockedInputConsumer(gestureState, runningTaskInfo);
|
return createDeviceLockedInputConsumer(gestureState, runningTaskInfo);
|
||||||
|
@ -543,26 +537,27 @@ public class TouchInteractionService extends Service implements
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher
|
if (previousGestureState.getFinishingRecentsAnimationTaskId() > 0) {
|
||||||
&& !sSwipeSharedState.recentsAnimationFinishInterrupted) {
|
|
||||||
return mResetGestureInputConsumer;
|
|
||||||
} else if (sSwipeSharedState.recentsAnimationFinishInterrupted) {
|
|
||||||
// If the finish animation was interrupted, then continue using the other activity input
|
// If the finish animation was interrupted, then continue using the other activity input
|
||||||
// consumer but with the next task as the running task
|
// consumer but with the next task as the running task
|
||||||
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
RunningTaskInfo info = new ActivityManager.RunningTaskInfo();
|
||||||
info.id = sSwipeSharedState.nextRunningTaskId;
|
info.id = previousGestureState.getFinishingRecentsAnimationTaskId();
|
||||||
return createOtherActivityInputConsumer(gestureState, event, info);
|
return createOtherActivityInputConsumer(previousGestureState, gestureState, event,
|
||||||
} else if (sSwipeSharedState.goingToLauncher
|
info);
|
||||||
|
} else if (runningTaskInfo == null) {
|
||||||
|
return mResetGestureInputConsumer;
|
||||||
|
} else if (previousGestureState.isRunningAnimationToLauncher()
|
||||||
|| gestureState.getActivityInterface().isResumed()
|
|| gestureState.getActivityInterface().isResumed()
|
||||||
|| forceOverviewInputConsumer) {
|
|| forceOverviewInputConsumer) {
|
||||||
return createOverviewInputConsumer(gestureState, event);
|
return createOverviewInputConsumer(previousGestureState, gestureState, event);
|
||||||
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get()
|
} else if (ENABLE_QUICKSTEP_LIVE_TILE.get()
|
||||||
&& gestureState.getActivityInterface().isInLiveTileMode()) {
|
&& gestureState.getActivityInterface().isInLiveTileMode()) {
|
||||||
return createOverviewInputConsumer(gestureState, event);
|
return createOverviewInputConsumer(previousGestureState, gestureState, event);
|
||||||
} else if (mDeviceState.isGestureBlockedActivity(runningTaskInfo)) {
|
} else if (mDeviceState.isGestureBlockedActivity(runningTaskInfo)) {
|
||||||
return mResetGestureInputConsumer;
|
return mResetGestureInputConsumer;
|
||||||
} else {
|
} 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;
|
&& (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) {
|
MotionEvent event, RunningTaskInfo runningTaskInfo) {
|
||||||
|
|
||||||
final boolean shouldDefer;
|
final boolean shouldDefer;
|
||||||
final BaseSwipeUpHandler.Factory factory;
|
final BaseSwipeUpHandler.Factory factory;
|
||||||
|
|
||||||
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) {
|
||||||
shouldDefer = !sSwipeSharedState.recentsAnimationFinishInterrupted;
|
shouldDefer = previousGestureState.getFinishingRecentsAnimationTaskId() < 0;
|
||||||
factory = mFallbackNoButtonFactory;
|
factory = mFallbackNoButtonFactory;
|
||||||
} else {
|
} else {
|
||||||
shouldDefer = gestureState.getActivityInterface().deferStartingActivity(mDeviceState,
|
shouldDefer = gestureState.getActivityInterface().deferStartingActivity(mDeviceState,
|
||||||
|
@ -590,26 +586,28 @@ public class TouchInteractionService extends Service implements
|
||||||
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
|
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
|
||||||
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||||
gestureState, runningTaskInfo, shouldDefer, this::onConsumerInactive,
|
gestureState, runningTaskInfo, shouldDefer, this::onConsumerInactive,
|
||||||
sSwipeSharedState, mInputMonitorCompat, disableHorizontalSwipe, factory, mLogId);
|
mInputMonitorCompat, disableHorizontalSwipe, factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState,
|
private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState,
|
||||||
RunningTaskInfo taskInfo) {
|
RunningTaskInfo taskInfo) {
|
||||||
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
|
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
|
||||||
return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||||
gestureState, sSwipeSharedState, mInputMonitorCompat, taskInfo.taskId, mLogId);
|
gestureState, mInputMonitorCompat, taskInfo.taskId);
|
||||||
} else {
|
} else {
|
||||||
return mResetGestureInputConsumer;
|
return mResetGestureInputConsumer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputConsumer createOverviewInputConsumer(GestureState gestureState, MotionEvent event) {
|
public InputConsumer createOverviewInputConsumer(GestureState previousGestureState,
|
||||||
|
GestureState gestureState, MotionEvent event) {
|
||||||
BaseDraggingActivity activity = gestureState.getActivityInterface().getCreatedActivity();
|
BaseDraggingActivity activity = gestureState.getActivityInterface().getCreatedActivity();
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
return mResetGestureInputConsumer;
|
return mResetGestureInputConsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (activity.getRootView().hasWindowFocus() || sSwipeSharedState.goingToLauncher) {
|
if (activity.getRootView().hasWindowFocus()
|
||||||
|
|| previousGestureState.isRunningAnimationToLauncher()) {
|
||||||
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
|
return new OverviewInputConsumer(gestureState, activity, mInputMonitorCompat,
|
||||||
false /* startingInActivityBounds */);
|
false /* startingInActivityBounds */);
|
||||||
} else {
|
} else {
|
||||||
|
@ -704,10 +702,6 @@ public class TouchInteractionService extends Service implements
|
||||||
boolean resumed = mOverviewComponentObserver != null
|
boolean resumed = mOverviewComponentObserver != null
|
||||||
&& mOverviewComponentObserver.getActivityInterface().isResumed();
|
&& mOverviewComponentObserver.getActivityInterface().isResumed();
|
||||||
pw.println(" resumed=" + resumed);
|
pw.println(" resumed=" + resumed);
|
||||||
pw.println(" useSharedState=" + mConsumer.useSharedSwipeState());
|
|
||||||
if (mConsumer.useSharedSwipeState()) {
|
|
||||||
sSwipeSharedState.dump(" ", pw);
|
|
||||||
}
|
|
||||||
pw.println(" mConsumer=" + mConsumer.getName());
|
pw.println(" mConsumer=" + mConsumer.getName());
|
||||||
pw.println("FeatureFlags:");
|
pw.println("FeatureFlags:");
|
||||||
pw.println(" APPLY_CONFIG_AT_RUNTIME=" + APPLY_CONFIG_AT_RUNTIME.get());
|
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.launcher3.util.SystemUiController.UI_STATE_OVERVIEW;
|
||||||
import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.HIDE;
|
import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.HIDE;
|
||||||
import static com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState.PEEK;
|
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.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 static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||||
|
|
||||||
import android.animation.Animator;
|
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;
|
||||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState;
|
import com.android.quickstep.BaseActivityInterface.AnimationFactory.ShelfAnimState;
|
||||||
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
import com.android.quickstep.BaseActivityInterface.HomeAnimationFactory;
|
||||||
|
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||||
import com.android.quickstep.util.ActiveGestureLog;
|
import com.android.quickstep.util.ActiveGestureLog;
|
||||||
|
@ -138,42 +140,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
private static final int LAUNCHER_UI_STATES =
|
private static final int LAUNCHER_UI_STATES =
|
||||||
STATE_LAUNCHER_PRESENT | STATE_LAUNCHER_DRAWN | STATE_LAUNCHER_STARTED;
|
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 MAX_SWIPE_DURATION = 350;
|
||||||
public static final long MIN_SWIPE_DURATION = 80;
|
public static final long MIN_SWIPE_DURATION = 80;
|
||||||
public static final long MIN_OVERSHOOT_DURATION = 120;
|
public static final long MIN_OVERSHOOT_DURATION = 120;
|
||||||
|
@ -195,7 +161,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
private final TaskAnimationManager mTaskAnimationManager;
|
private final TaskAnimationManager mTaskAnimationManager;
|
||||||
private final GestureState mGestureState;
|
private final GestureState mGestureState;
|
||||||
|
|
||||||
private GestureEndTarget mGestureEndTarget;
|
|
||||||
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
|
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
|
||||||
private RunningWindowAnim mRunningWindowAnim;
|
private RunningWindowAnim mRunningWindowAnim;
|
||||||
private boolean mIsShelfPeeking;
|
private boolean mIsShelfPeeking;
|
||||||
|
@ -287,6 +252,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
| STATE_GESTURE_STARTED,
|
| STATE_GESTURE_STARTED,
|
||||||
this::setupLauncherUiAfterSwipeUpToRecentsAnimation);
|
this::setupLauncherUiAfterSwipeUpToRecentsAnimation);
|
||||||
|
|
||||||
|
mGestureState.addCallback(STATE_END_TARGET_ANIMATION_FINISHED,
|
||||||
|
this::onEndTargetSet);
|
||||||
|
|
||||||
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
|
mStateCallback.addCallback(STATE_HANDLER_INVALIDATED, this::invalidateHandler);
|
||||||
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
mStateCallback.addCallback(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||||
this::invalidateHandlerWithLauncher);
|
this::invalidateHandlerWithLauncher);
|
||||||
|
@ -338,7 +306,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean moveWindowWithRecentsScroll() {
|
protected boolean moveWindowWithRecentsScroll() {
|
||||||
return mGestureEndTarget != HOME;
|
return mGestureState.getEndTarget() != HOME;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLauncherStart(final T activity) {
|
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,
|
// 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.
|
// as that will set the state as BACKGROUND_APP, overriding the animation to NORMAL.
|
||||||
if (mGestureEndTarget != HOME) {
|
if (mGestureState.getEndTarget() != HOME) {
|
||||||
Runnable initAnimFactory = () -> {
|
Runnable initAnimFactory = () -> {
|
||||||
mAnimationFactory = mActivityInterface.prepareRecentsUI(mActivity,
|
mAnimationFactory = mActivityInterface.prepareRecentsUI(mActivity,
|
||||||
mWasLauncherAlreadyVisible, true,
|
mWasLauncherAlreadyVisible, true,
|
||||||
|
@ -419,7 +387,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
||||||
null, () -> {
|
null, () -> {
|
||||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||||
TouchInteractionService.getSwipeSharedState().clearAllState();
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||||
|
@ -460,13 +427,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
.getHighResLoadingState().setVisible(true);
|
.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
|
@Override
|
||||||
public void onMotionPauseChanged(boolean isPaused) {
|
public void onMotionPauseChanged(boolean isPaused) {
|
||||||
setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
|
setShelfState(isPaused ? PEEK : HIDE, OVERSHOOT_1_2, SHELF_ANIM_DURATION);
|
||||||
|
@ -491,9 +451,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
? null
|
? null
|
||||||
: mRecentsAnimationTargets.findTask(mRunningTaskId);
|
: mRecentsAnimationTargets.findTask(mRunningTaskId);
|
||||||
final boolean recentsAttachedToAppWindow;
|
final boolean recentsAttachedToAppWindow;
|
||||||
int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
if (mGestureState.getEndTarget() != null) {
|
||||||
if (mGestureEndTarget != null) {
|
recentsAttachedToAppWindow = mGestureState.getEndTarget().recentsAttachedToAppWindow;
|
||||||
recentsAttachedToAppWindow = mGestureEndTarget.recentsAttachedToAppWindow;
|
|
||||||
} else if (mContinuingLastGesture
|
} else if (mContinuingLastGesture
|
||||||
&& mRecentsView.getRunningTaskIndex() != mRecentsView.getNextPage()) {
|
&& mRecentsView.getRunningTaskIndex() != mRecentsView.getNextPage()) {
|
||||||
recentsAttachedToAppWindow = true;
|
recentsAttachedToAppWindow = true;
|
||||||
|
@ -540,9 +499,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildAnimationController() {
|
private void buildAnimationController() {
|
||||||
if (mGestureEndTarget == HOME || mHasLauncherTransitionControllerStarted) {
|
if (mGestureState.getEndTarget() == HOME || mHasLauncherTransitionControllerStarted) {
|
||||||
// We don't want a new mLauncherTransitionController if mGestureEndTarget == HOME (it
|
// We don't want a new mLauncherTransitionController if
|
||||||
// has its own animation) or if we're already animating the current controller.
|
// mGestureState.getEndTarget() == HOME (it has its own animation) or if we're already
|
||||||
|
// animating the current controller.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
initTransitionEndpoints(mActivity.getDeviceProfile());
|
initTransitionEndpoints(mActivity.getDeviceProfile());
|
||||||
|
@ -599,7 +559,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateLauncherTransitionProgress() {
|
private void updateLauncherTransitionProgress() {
|
||||||
if (mGestureEndTarget == HOME) {
|
if (mGestureState.getEndTarget() == HOME) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
|
// 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
|
@Override
|
||||||
protected InputConsumer createNewInputProxyHandler() {
|
protected InputConsumer createNewInputProxyHandler() {
|
||||||
endRunningWindowAnim(mGestureEndTarget == HOME /* cancel */);
|
endRunningWindowAnim(mGestureState.getEndTarget() == HOME /* cancel */);
|
||||||
endLauncherTransitionController();
|
endLauncherTransitionController();
|
||||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||||
// Hide the task view, if not already hidden
|
// 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,
|
private GestureEndTarget calculateEndTarget(PointF velocity, float endVelocity, boolean isFling,
|
||||||
boolean isCancel) {
|
boolean isCancel) {
|
||||||
final GestureEndTarget endTarget;
|
final GestureEndTarget endTarget;
|
||||||
|
@ -800,7 +778,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
float currentShift = mCurrentShift.value;
|
float currentShift = mCurrentShift.value;
|
||||||
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
|
final GestureEndTarget endTarget = calculateEndTarget(velocity, endVelocity,
|
||||||
isFling, isCancel);
|
isFling, isCancel);
|
||||||
float endShift = endTarget.endShift;
|
float endShift = endTarget.isLauncher ? 1 : 0;
|
||||||
final float startShift;
|
final float startShift;
|
||||||
Interpolator interpolator = DEACCEL;
|
Interpolator interpolator = DEACCEL;
|
||||||
if (!isFling) {
|
if (!isFling) {
|
||||||
|
@ -903,11 +881,12 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
@UiThread
|
@UiThread
|
||||||
private void animateToProgressInternal(float start, float end, long duration,
|
private void animateToProgressInternal(float start, float end, long duration,
|
||||||
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
|
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();
|
maybeUpdateRecentsAttachedState();
|
||||||
|
|
||||||
if (mGestureEndTarget == HOME) {
|
if (mGestureState.getEndTarget() == HOME) {
|
||||||
HomeAnimationFactory homeAnimFactory;
|
HomeAnimationFactory homeAnimFactory;
|
||||||
if (mActivity != null) {
|
if (mActivity != null) {
|
||||||
homeAnimFactory = mActivityInterface.prepareHomeUI(mActivity);
|
homeAnimFactory = mActivityInterface.prepareHomeUI(mActivity);
|
||||||
|
@ -934,7 +913,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
|
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onAnimationSuccess(Animator animator) {
|
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);
|
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
|
// 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
|
// instead of NEW_TASK. This could happen, for example, if our scroll is
|
||||||
// aborted after we determined the target to be NEW_TASK.
|
// aborted after we determined the target to be NEW_TASK.
|
||||||
setStateOnUiThread(LAST_TASK.endState);
|
mGestureState.setEndTarget(LAST_TASK);
|
||||||
} else {
|
|
||||||
setStateOnUiThread(target.endState);
|
|
||||||
}
|
}
|
||||||
|
mGestureState.setState(STATE_END_TARGET_ANIMATION_FINISHED);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
windowAnim.start();
|
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
|
// Always play the entire launcher animation when going home, since it is separate from
|
||||||
// the animation that has been controlled thus far.
|
// the animation that has been controlled thus far.
|
||||||
if (mGestureEndTarget == HOME) {
|
if (mGestureState.getEndTarget() == HOME) {
|
||||||
start = 0;
|
start = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1029,14 +1008,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
public void onConsumerAboutToBeSwitched() {
|
||||||
if (mGestureEndTarget != null) {
|
if (!mGestureState.isRunningAnimationToLauncher()) {
|
||||||
sharedState.canGestureBeContinued = mGestureEndTarget.canBeContinued;
|
cancelCurrentAnimation();
|
||||||
sharedState.goingToLauncher = mGestureEndTarget.isLauncher;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (sharedState.canGestureBeContinued) {
|
|
||||||
cancelCurrentAnimation(sharedState);
|
|
||||||
} else {
|
} else {
|
||||||
reset();
|
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
|
* Cancels any running animation so that the active target can be overriden by a new swipe
|
||||||
* handle (in case of quick switch).
|
* handle (in case of quick switch).
|
||||||
*/
|
*/
|
||||||
private void cancelCurrentAnimation(SwipeSharedState sharedState) {
|
private void cancelCurrentAnimation() {
|
||||||
mCanceled = true;
|
mCanceled = true;
|
||||||
mCurrentShift.cancelAnimation();
|
mCurrentShift.cancelAnimation();
|
||||||
if (mLauncherTransitionController != null && mLauncherTransitionController
|
if (mLauncherTransitionController != null && mLauncherTransitionController
|
||||||
|
@ -1093,7 +1067,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
? newRunningTaskView.getTask().key.id
|
? newRunningTaskView.getTask().key.id
|
||||||
: -1;
|
: -1;
|
||||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||||
sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
|
mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1160,7 +1134,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
||||||
mTaskSnapshot = mRecentsAnimationController.screenshotTask(mRunningTaskId);
|
mTaskSnapshot = mRecentsAnimationController.screenshotTask(mRunningTaskId);
|
||||||
}
|
}
|
||||||
final TaskView taskView;
|
final TaskView taskView;
|
||||||
if (mGestureEndTarget == HOME) {
|
if (mGestureState.getEndTarget() == HOME) {
|
||||||
// Capture the screenshot before finishing the transition to home to ensure it's
|
// 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.
|
// taken in the correct orientation, but no need to update the thumbnail.
|
||||||
taskView = null;
|
taskView = null;
|
||||||
|
|
|
@ -22,11 +22,6 @@ public abstract class DelegateInputConsumer implements InputConsumer {
|
||||||
mState = STATE_INACTIVE;
|
mState = STATE_INACTIVE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean useSharedSwipeState() {
|
|
||||||
return mDelegate.useSharedSwipeState();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean allowInterceptByParent() {
|
public boolean allowInterceptByParent() {
|
||||||
return mDelegate.allowInterceptByParent() && mState != STATE_ACTIVE;
|
return mDelegate.allowInterceptByParent() && mState != STATE_ACTIVE;
|
||||||
|
|
|
@ -44,7 +44,6 @@ import com.android.quickstep.LockScreenRecentsActivity;
|
||||||
import com.android.quickstep.MultiStateCallback;
|
import com.android.quickstep.MultiStateCallback;
|
||||||
import com.android.quickstep.RecentsAnimationController;
|
import com.android.quickstep.RecentsAnimationController;
|
||||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||||
import com.android.quickstep.SwipeSharedState;
|
|
||||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||||
import com.android.quickstep.RecentsAnimationTargets;
|
import com.android.quickstep.RecentsAnimationTargets;
|
||||||
import com.android.quickstep.TaskAnimationManager;
|
import com.android.quickstep.TaskAnimationManager;
|
||||||
|
@ -79,12 +78,10 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
||||||
private final TaskAnimationManager mTaskAnimationManager;
|
private final TaskAnimationManager mTaskAnimationManager;
|
||||||
private final GestureState mGestureState;
|
private final GestureState mGestureState;
|
||||||
private final float mTouchSlopSquared;
|
private final float mTouchSlopSquared;
|
||||||
private final SwipeSharedState mSwipeSharedState;
|
|
||||||
private final InputMonitorCompat mInputMonitorCompat;
|
private final InputMonitorCompat mInputMonitorCompat;
|
||||||
|
|
||||||
private final PointF mTouchDown = new PointF();
|
private final PointF mTouchDown = new PointF();
|
||||||
private final AppWindowAnimationHelper mAppWindowAnimationHelper;
|
private final AppWindowAnimationHelper mAppWindowAnimationHelper;
|
||||||
private int mLogId;
|
|
||||||
private final AppWindowAnimationHelper.TransformParams mTransformParams;
|
private final AppWindowAnimationHelper.TransformParams mTransformParams;
|
||||||
private final Point mDisplaySize;
|
private final Point mDisplaySize;
|
||||||
private final MultiStateCallback mStateCallback;
|
private final MultiStateCallback mStateCallback;
|
||||||
|
@ -100,16 +97,13 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
||||||
|
|
||||||
public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
|
public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
|
||||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
InputMonitorCompat inputMonitorCompat, int runningTaskId) {
|
||||||
int runningTaskId, int logId) {
|
|
||||||
mContext = context;
|
mContext = context;
|
||||||
mDeviceState = deviceState;
|
mDeviceState = deviceState;
|
||||||
mTaskAnimationManager = taskAnimationManager;
|
mTaskAnimationManager = taskAnimationManager;
|
||||||
mGestureState = gestureState;
|
mGestureState = gestureState;
|
||||||
mTouchSlopSquared = squaredTouchSlop(context);
|
mTouchSlopSquared = squaredTouchSlop(context);
|
||||||
mSwipeSharedState = swipeSharedState;
|
|
||||||
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
|
mAppWindowAnimationHelper = new AppWindowAnimationHelper(context);
|
||||||
mLogId = logId;
|
|
||||||
mTransformParams = new AppWindowAnimationHelper.TransformParams();
|
mTransformParams = new AppWindowAnimationHelper.TransformParams();
|
||||||
mInputMonitorCompat = inputMonitorCompat;
|
mInputMonitorCompat = inputMonitorCompat;
|
||||||
mRunningTaskId = runningTaskId;
|
mRunningTaskId = runningTaskId;
|
||||||
|
@ -216,7 +210,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
||||||
.addCategory(Intent.CATEGORY_DEFAULT)
|
.addCategory(Intent.CATEGORY_DEFAULT)
|
||||||
.setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
|
.setComponent(new ComponentName(mContext, LockScreenRecentsActivity.class))
|
||||||
.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK)
|
.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);
|
mTaskAnimationManager.startRecentsAnimation(mGestureState, intent, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,14 +15,14 @@
|
||||||
*/
|
*/
|
||||||
package com.android.quickstep.inputconsumers;
|
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.MultiStateCallback.DEBUG_STATES;
|
||||||
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
|
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
|
||||||
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
|
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
|
||||||
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
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 static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||||
|
|
||||||
import android.animation.Animator;
|
import android.animation.Animator;
|
||||||
|
@ -35,6 +35,7 @@ import android.graphics.PointF;
|
||||||
import android.graphics.RectF;
|
import android.graphics.RectF;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
|
import android.util.ArrayMap;
|
||||||
import com.android.launcher3.R;
|
import com.android.launcher3.R;
|
||||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
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.AnimatedFloat;
|
||||||
import com.android.quickstep.BaseSwipeUpHandler;
|
import com.android.quickstep.BaseSwipeUpHandler;
|
||||||
import com.android.quickstep.GestureState;
|
import com.android.quickstep.GestureState;
|
||||||
|
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||||
import com.android.quickstep.InputConsumer;
|
import com.android.quickstep.InputConsumer;
|
||||||
import com.android.quickstep.MultiStateCallback;
|
import com.android.quickstep.MultiStateCallback;
|
||||||
import com.android.quickstep.OverviewComponentObserver;
|
import com.android.quickstep.OverviewComponentObserver;
|
||||||
import com.android.quickstep.RecentsActivity;
|
import com.android.quickstep.RecentsActivity;
|
||||||
import com.android.quickstep.RecentsAnimationController;
|
import com.android.quickstep.RecentsAnimationController;
|
||||||
import com.android.quickstep.RecentsModel;
|
import com.android.quickstep.RecentsModel;
|
||||||
import com.android.quickstep.SwipeSharedState;
|
|
||||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||||
import com.android.quickstep.util.RectFSpringAnim;
|
import com.android.quickstep.util.RectFSpringAnim;
|
||||||
import com.android.quickstep.RecentsAnimationTargets;
|
import com.android.quickstep.RecentsAnimationTargets;
|
||||||
|
@ -83,27 +84,23 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
||||||
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
|
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
|
||||||
|
|
||||||
public enum GestureEndTarget {
|
public static class EndTargetAnimationParams {
|
||||||
HOME(3, 100, 1),
|
|
||||||
RECENTS(1, 300, 0),
|
|
||||||
LAST_TASK(0, 150, 1),
|
|
||||||
NEW_TASK(0, 150, 1);
|
|
||||||
|
|
||||||
private final float mEndProgress;
|
private final float mEndProgress;
|
||||||
private final long mDurationMultiplier;
|
private final long mDurationMultiplier;
|
||||||
private final float mLauncherAlpha;
|
private final float mLauncherAlpha;
|
||||||
|
|
||||||
GestureEndTarget(float endProgress, long durationMultiplier, float launcherAlpha) {
|
EndTargetAnimationParams(float endProgress, long durationMultiplier, float launcherAlpha) {
|
||||||
mEndProgress = endProgress;
|
mEndProgress = endProgress;
|
||||||
mDurationMultiplier = durationMultiplier;
|
mDurationMultiplier = durationMultiplier;
|
||||||
mLauncherAlpha = launcherAlpha;
|
mLauncherAlpha = launcherAlpha;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
private static ArrayMap<GestureEndTarget, EndTargetAnimationParams>
|
||||||
|
mEndTargetAnimationParams = new ArrayMap();
|
||||||
|
|
||||||
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
|
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
|
||||||
|
|
||||||
private boolean mIsMotionPaused = false;
|
private boolean mIsMotionPaused = false;
|
||||||
private GestureEndTarget mEndTarget;
|
|
||||||
|
|
||||||
private final boolean mInQuickSwitchMode;
|
private final boolean mInQuickSwitchMode;
|
||||||
private final boolean mContinuingLastGesture;
|
private final boolean mContinuingLastGesture;
|
||||||
|
@ -136,6 +133,12 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
mAppWindowAnimationHelper.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
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();
|
initStateCallbacks();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -161,7 +164,7 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onLauncherAlphaChanged() {
|
private void onLauncherAlphaChanged() {
|
||||||
if (mRecentsAnimationTargets != null && mEndTarget == null) {
|
if (mRecentsAnimationTargets != null && mGestureState.getEndTarget() == null) {
|
||||||
applyTransformUnchecked();
|
applyTransformUnchecked();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -247,7 +250,7 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
@Override
|
@Override
|
||||||
public void onGestureCancelled() {
|
public void onGestureCancelled() {
|
||||||
updateDisplacement(0);
|
updateDisplacement(0);
|
||||||
mEndTarget = LAST_TASK;
|
mGestureState.setEndTarget(LAST_TASK);
|
||||||
setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,28 +259,29 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
mEndVelocityPxPerMs.set(0, velocity.y / 1000);
|
mEndVelocityPxPerMs.set(0, velocity.y / 1000);
|
||||||
if (mInQuickSwitchMode) {
|
if (mInQuickSwitchMode) {
|
||||||
// For now set it to non-null, it will be reset before starting the animation
|
// For now set it to non-null, it will be reset before starting the animation
|
||||||
mEndTarget = LAST_TASK;
|
mGestureState.setEndTarget(LAST_TASK);
|
||||||
} else {
|
} else {
|
||||||
float flingThreshold = mContext.getResources()
|
float flingThreshold = mContext.getResources()
|
||||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||||
|
|
||||||
if (isFling) {
|
if (isFling) {
|
||||||
mEndTarget = endVelocity < 0 ? HOME : LAST_TASK;
|
mGestureState.setEndTarget(endVelocity < 0 ? HOME : LAST_TASK);
|
||||||
} else if (mIsMotionPaused) {
|
} else if (mIsMotionPaused) {
|
||||||
mEndTarget = RECENTS;
|
mGestureState.setEndTarget(RECENTS);
|
||||||
} else {
|
} 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);
|
setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onConsumerAboutToBeSwitched(SwipeSharedState sharedState) {
|
public void onConsumerAboutToBeSwitched() {
|
||||||
if (mInQuickSwitchMode && mEndTarget != null) {
|
if (mInQuickSwitchMode && mGestureState.getEndTarget() != null) {
|
||||||
sharedState.canGestureBeContinued = true;
|
mGestureState.setEndTarget(HOME);
|
||||||
sharedState.goingToLauncher = false;
|
|
||||||
|
|
||||||
mCanceled = true;
|
mCanceled = true;
|
||||||
mCurrentShift.cancelAnimation();
|
mCurrentShift.cancelAnimation();
|
||||||
|
@ -293,7 +297,7 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
? newRunningTaskView.getTask().key.id
|
? newRunningTaskView.getTask().key.id
|
||||||
: -1;
|
: -1;
|
||||||
mRecentsView.setCurrentTask(newRunningTaskId);
|
mRecentsView.setCurrentTask(newRunningTaskId);
|
||||||
sharedState.setRecentsAnimationFinishInterrupted(newRunningTaskId);
|
mGestureState.setFinishingRecentsAnimationTaskId(newRunningTaskId);
|
||||||
}
|
}
|
||||||
mRecentsView.setOnScrollChangeListener(null);
|
mRecentsView.setOnScrollChangeListener(null);
|
||||||
}
|
}
|
||||||
|
@ -319,7 +323,7 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
}
|
}
|
||||||
|
|
||||||
private void finishAnimationTargetSetAnimationComplete() {
|
private void finishAnimationTargetSetAnimationComplete() {
|
||||||
switch (mEndTarget) {
|
switch (mGestureState.getEndTarget()) {
|
||||||
case HOME: {
|
case HOME: {
|
||||||
if (mSwipeUpOverHome) {
|
if (mSwipeUpOverHome) {
|
||||||
mRecentsAnimationController.finish(false, null, false);
|
mRecentsAnimationController.finish(false, null, false);
|
||||||
|
@ -370,17 +374,20 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
// Recalculate the end target, some views might have been initialized after
|
// Recalculate the end target, some views might have been initialized after
|
||||||
// gesture has ended.
|
// gesture has ended.
|
||||||
if (mRecentsView == null || !hasTargets()) {
|
if (mRecentsView == null || !hasTargets()) {
|
||||||
mEndTarget = LAST_TASK;
|
mGestureState.setEndTarget(LAST_TASK);
|
||||||
} else {
|
} else {
|
||||||
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
final int runningTaskIndex = mRecentsView.getRunningTaskIndex();
|
||||||
final int taskToLaunch = mRecentsView.getNextPage();
|
final int taskToLaunch = mRecentsView.getNextPage();
|
||||||
mEndTarget = (runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
mGestureState.setEndTarget(
|
||||||
? NEW_TASK : LAST_TASK;
|
(runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||||
|
? NEW_TASK
|
||||||
|
: LAST_TASK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float endProgress = mEndTarget.mEndProgress;
|
EndTargetAnimationParams params = mEndTargetAnimationParams.get(mGestureState.getEndTarget());
|
||||||
long duration = (long) (mEndTarget.mDurationMultiplier *
|
float endProgress = params.mEndProgress;
|
||||||
|
long duration = (long) (params.mDurationMultiplier *
|
||||||
Math.abs(endProgress - mCurrentShift.value));
|
Math.abs(endProgress - mCurrentShift.value));
|
||||||
if (mRecentsView != null) {
|
if (mRecentsView != null) {
|
||||||
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
|
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);
|
RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration);
|
||||||
anim.addAnimatorListener(endListener);
|
anim.addAnimatorListener(endListener);
|
||||||
anim.start(mEndVelocityPxPerMs);
|
anim.start(mEndVelocityPxPerMs);
|
||||||
|
@ -404,7 +411,7 @@ public class FallbackNoButtonInputConsumer extends
|
||||||
|
|
||||||
AnimatorSet anim = new AnimatorSet();
|
AnimatorSet anim = new AnimatorSet();
|
||||||
anim.play(mLauncherAlpha.animateToValue(
|
anim.play(mLauncherAlpha.animateToValue(
|
||||||
mLauncherAlpha.value, mEndTarget.mLauncherAlpha));
|
mLauncherAlpha.value, params.mLauncherAlpha));
|
||||||
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
|
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
|
||||||
|
|
||||||
anim.setDuration(duration);
|
anim.setDuration(duration);
|
||||||
|
|
|
@ -54,7 +54,6 @@ import com.android.quickstep.GestureState;
|
||||||
import com.android.quickstep.InputConsumer;
|
import com.android.quickstep.InputConsumer;
|
||||||
import com.android.quickstep.RecentsAnimationCallbacks;
|
import com.android.quickstep.RecentsAnimationCallbacks;
|
||||||
import com.android.quickstep.RecentsAnimationDeviceState;
|
import com.android.quickstep.RecentsAnimationDeviceState;
|
||||||
import com.android.quickstep.SwipeSharedState;
|
|
||||||
import com.android.quickstep.SysUINavigationMode;
|
import com.android.quickstep.SysUINavigationMode;
|
||||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||||
import com.android.quickstep.TaskAnimationManager;
|
import com.android.quickstep.TaskAnimationManager;
|
||||||
|
@ -85,7 +84,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||||
private RecentsAnimationCallbacks mActiveCallbacks;
|
private RecentsAnimationCallbacks mActiveCallbacks;
|
||||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||||
private final RunningTaskInfo mRunningTask;
|
private final RunningTaskInfo mRunningTask;
|
||||||
private final SwipeSharedState mSwipeSharedState;
|
|
||||||
private final InputMonitorCompat mInputMonitorCompat;
|
private final InputMonitorCompat mInputMonitorCompat;
|
||||||
private final SysUINavigationMode.Mode mMode;
|
private final SysUINavigationMode.Mode mMode;
|
||||||
private final BaseActivityInterface mActivityInterface;
|
private final BaseActivityInterface mActivityInterface;
|
||||||
|
@ -126,16 +124,14 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||||
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
|
ActivityManagerWrapper.getInstance().cancelRecentsAnimation(
|
||||||
true /* restoreHomeStackPosition */);
|
true /* restoreHomeStackPosition */);
|
||||||
};
|
};
|
||||||
private int mLogId;
|
|
||||||
|
|
||||||
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
|
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
|
||||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||||
RunningTaskInfo runningTaskInfo, boolean isDeferredDownTarget,
|
RunningTaskInfo runningTaskInfo, boolean isDeferredDownTarget,
|
||||||
Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
InputMonitorCompat inputMonitorCompat, boolean disableHorizontalSwipe,
|
||||||
boolean disableHorizontalSwipe, Factory handlerFactory, int logId) {
|
Factory handlerFactory) {
|
||||||
super(base);
|
super(base);
|
||||||
mLogId = logId;
|
|
||||||
mDeviceState = deviceState;
|
mDeviceState = deviceState;
|
||||||
mTaskAnimationManager = taskAnimationManager;
|
mTaskAnimationManager = taskAnimationManager;
|
||||||
mGestureState = gestureState;
|
mGestureState = gestureState;
|
||||||
|
@ -154,7 +150,6 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||||
|
|
||||||
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
|
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
|
||||||
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
|
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
|
||||||
mSwipeSharedState = swipeSharedState;
|
|
||||||
|
|
||||||
mNavBarPosition = new NavBarPosition(base);
|
mNavBarPosition = new NavBarPosition(base);
|
||||||
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
|
mTouchSlop = ViewConfiguration.get(this).getScaledTouchSlop();
|
||||||
|
@ -347,7 +342,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||||
notifyGestureStarted();
|
notifyGestureStarted();
|
||||||
} else {
|
} else {
|
||||||
Intent intent = mInteractionHandler.getLaunchIntent();
|
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,
|
mActiveCallbacks = mTaskAnimationManager.startRecentsAnimation(mGestureState, intent,
|
||||||
mInteractionHandler);
|
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
|
// The consumer is being switched while we are active. Set up the shared state to be
|
||||||
// used by the next animation
|
// used by the next animation
|
||||||
removeListener();
|
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
|
@Override
|
||||||
public boolean allowInterceptByParent() {
|
public boolean allowInterceptByParent() {
|
||||||
return !mPassedPilferInputSlop;
|
return !mPassedPilferInputSlop;
|
||||||
|
|
|
@ -42,7 +42,6 @@ public class ResetGestureInputConsumer implements InputConsumer {
|
||||||
if (ev.getAction() == MotionEvent.ACTION_DOWN
|
if (ev.getAction() == MotionEvent.ACTION_DOWN
|
||||||
&& mTaskAnimationManager.isRecentsAnimationRunning()) {
|
&& mTaskAnimationManager.isRecentsAnimationRunning()) {
|
||||||
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
||||||
TouchInteractionService.getSwipeSharedState().clearAllState();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,12 @@
|
||||||
*/
|
*/
|
||||||
package com.android.quickstep;
|
package com.android.quickstep;
|
||||||
|
|
||||||
|
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||||
|
|
||||||
import com.android.launcher3.BaseDraggingActivity;
|
import com.android.launcher3.BaseDraggingActivity;
|
||||||
|
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
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,
|
* 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 {
|
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) {
|
RECENTS(true, ContainerType.TASKSWITCHER, true),
|
||||||
mActivityInterface = activityInterface;
|
|
||||||
|
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() {
|
public <T extends BaseDraggingActivity> BaseActivityInterface<T> getActivityInterface() {
|
||||||
return mActivityInterface;
|
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
|
@Override
|
||||||
public void onRecentsAnimationStart(RecentsAnimationController controller,
|
public void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||||
RecentsAnimationTargets targets) {
|
RecentsAnimationTargets targets) {
|
||||||
// To be implemented
|
mStateCallback.setState(STATE_RECENTS_ANIMATION_STARTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||||
// To be implemented
|
mStateCallback.setState(STATE_RECENTS_ANIMATION_CANCELED);
|
||||||
|
mStateCallback.setState(STATE_RECENTS_ANIMATION_ENDED);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
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();
|
int getType();
|
||||||
|
|
||||||
default boolean useSharedSwipeState() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the user has crossed the threshold for it to be an explicit action.
|
* 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.
|
* 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() { }
|
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.MAIN_EXECUTOR;
|
||||||
import static com.android.launcher3.util.Executors.UI_HELPER_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.content.Intent;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
@ -95,6 +96,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
|
||||||
mCallbacks.addListener(listener);
|
mCallbacks.addListener(listener);
|
||||||
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
||||||
.startRecentsActivity(intent, null, mCallbacks, null, null));
|
.startRecentsActivity(intent, null, mCallbacks, null, null));
|
||||||
|
gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED);
|
||||||
return mCallbacks;
|
return mCallbacks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue