9/ Clean up swipe shared state
- Add TaskAnimationManager which keeps track of the animation state whose lifecycle can be longer than the gesture. Move some of the logic related to cleaning up old animations into this class (called when the state is shared across gestures). - Instead of calling into the shared state directly via UIFactory, add callback to cleanup the animation and shared state from Launcher Bug: 141886704 Change-Id: Ib6140b37162f7460a20fa1046cfd4f4068e4a1c6 Signed-off-by: Winson Chung <winsonc@google.com>
This commit is contained in:
parent
9196cb11a2
commit
c9bf6d45ac
|
@ -88,6 +88,4 @@ public abstract class RecentsUiFactory {
|
|||
public static RotationMode getRotationMode(DeviceProfile dp) {
|
||||
return RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
public static void clearSwipeSharedState(Launcher launcher, boolean finishAnimation) { }
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ package com.android.launcher3.uioverrides;
|
|||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_QUICKSTEP_LIVE_TILE;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
|
||||
import android.content.Context;
|
||||
|
@ -45,7 +44,6 @@ import com.android.launcher3.util.UiThreadHelper;
|
|||
import com.android.launcher3.util.UiThreadHelper.AsyncCommand;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
|
@ -188,17 +186,6 @@ public abstract class RecentsUiFactory {
|
|||
return new RecentsViewStateController(launcher);
|
||||
}
|
||||
|
||||
/** Clears the swipe shared state for the current swipe gesture. */
|
||||
public static void clearSwipeSharedState(Launcher launcher, boolean finishAnimation) {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
launcher.<RecentsView>getOverviewPanel().switchToScreenshot(
|
||||
() -> TouchInteractionService.getSwipeSharedState().clearAllState(
|
||||
finishAnimation));
|
||||
} else {
|
||||
TouchInteractionService.getSwipeSharedState().clearAllState(finishAnimation);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recents logic that triggers when launcher state changes or launcher activity stops/resumes.
|
||||
*
|
||||
|
|
|
@ -493,22 +493,21 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
}
|
||||
|
||||
@Override
|
||||
public void switchToScreenshot(ThumbnailData thumbnailData, Runnable runnable) {
|
||||
public void switchRunningTaskViewToScreenshot(ThumbnailData thumbnailData,
|
||||
Runnable onFinishRunnable) {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
RecentsView recentsView = launcher.getOverviewPanel();
|
||||
if (recentsView == null) {
|
||||
if (runnable != null) {
|
||||
runnable.run();
|
||||
if (onFinishRunnable != null) {
|
||||
onFinishRunnable.run();
|
||||
}
|
||||
return;
|
||||
}
|
||||
TaskView taskView = recentsView.getRunningTaskView();
|
||||
if (taskView != null) {
|
||||
taskView.setShowScreenshot(true);
|
||||
taskView.getThumbnail().setThumbnail(taskView.getTask(), thumbnailData);
|
||||
ViewUtils.postDraw(taskView, runnable);
|
||||
} else if (runnable != null) {
|
||||
runnable.run();
|
||||
}
|
||||
recentsView.switchToScreenshot(thumbnailData, onFinishRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnDeferredActivityLaunchCallback(Runnable r) {
|
||||
getCreatedActivity().setOnDeferredActivityLaunchCallback(r);
|
||||
}
|
||||
}
|
|
@ -15,32 +15,12 @@
|
|||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.launcher3.util.Preconditions;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
|
||||
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* Utility class used to store state information shared across multiple transitions.
|
||||
*/
|
||||
public class SwipeSharedState implements RecentsAnimationListener {
|
||||
|
||||
private OverviewComponentObserver mOverviewComponentObserver;
|
||||
|
||||
private RecentsAnimationCallbacks mRecentsAnimationListener;
|
||||
private RecentsAnimationController mLastRecentsAnimationController;
|
||||
private RecentsAnimationTargets mLastAnimationTarget;
|
||||
|
||||
private boolean mLastAnimationCancelled = false;
|
||||
private boolean mLastAnimationRunning = false;
|
||||
public class SwipeSharedState {
|
||||
|
||||
public boolean canGestureBeContinued;
|
||||
public boolean goingToLauncher;
|
||||
|
@ -48,106 +28,6 @@ public class SwipeSharedState implements RecentsAnimationListener {
|
|||
public int nextRunningTaskId = -1;
|
||||
private int mLogId;
|
||||
|
||||
public void setOverviewComponentObserver(OverviewComponentObserver observer) {
|
||||
mOverviewComponentObserver = observer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||
RecentsAnimationTargets targets) {
|
||||
mLastRecentsAnimationController = controller;
|
||||
mLastAnimationTarget = targets;
|
||||
|
||||
mLastAnimationCancelled = false;
|
||||
mLastAnimationRunning = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
if (thumbnailData != null) {
|
||||
mOverviewComponentObserver.getActivityInterface().switchToScreenshot(thumbnailData,
|
||||
() -> {
|
||||
mLastRecentsAnimationController.cleanupScreenshot();
|
||||
clearAnimationState();
|
||||
});
|
||||
} else {
|
||||
clearAnimationState();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
if (mLastRecentsAnimationController == controller) {
|
||||
mLastAnimationRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAnimationTarget() {
|
||||
if (mLastAnimationTarget != null) {
|
||||
mLastAnimationTarget.release();
|
||||
mLastAnimationTarget = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void clearAnimationState() {
|
||||
clearAnimationTarget();
|
||||
|
||||
mLastAnimationCancelled = true;
|
||||
mLastAnimationRunning = false;
|
||||
}
|
||||
|
||||
private void clearListenerState(boolean finishAnimation) {
|
||||
if (mRecentsAnimationListener != null) {
|
||||
mRecentsAnimationListener.removeListener(this);
|
||||
mRecentsAnimationListener.notifyAnimationCanceled();
|
||||
if (mLastAnimationRunning && mLastRecentsAnimationController != null) {
|
||||
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(),
|
||||
finishAnimation
|
||||
? mLastRecentsAnimationController::finishAnimationToHome
|
||||
: mLastRecentsAnimationController::finishAnimationToApp);
|
||||
mLastRecentsAnimationController = null;
|
||||
mLastAnimationTarget = null;
|
||||
}
|
||||
}
|
||||
mRecentsAnimationListener = null;
|
||||
clearAnimationTarget();
|
||||
mLastAnimationCancelled = false;
|
||||
mLastAnimationRunning = false;
|
||||
}
|
||||
|
||||
public RecentsAnimationCallbacks newRecentsAnimationCallbacks() {
|
||||
Preconditions.assertUIThread();
|
||||
|
||||
if (mLastAnimationRunning) {
|
||||
String msg = "New animation started before completing old animation";
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD) {
|
||||
throw new IllegalArgumentException(msg);
|
||||
} else {
|
||||
Log.e("SwipeSharedState", msg, new Exception());
|
||||
}
|
||||
}
|
||||
|
||||
clearListenerState(false /* finishAnimation */);
|
||||
boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false
|
||||
: mOverviewComponentObserver.getActivityInterface().shouldMinimizeSplitScreen();
|
||||
mRecentsAnimationListener = new RecentsAnimationCallbacks(shouldMinimiseSplitScreen);
|
||||
mRecentsAnimationListener.addListener(this);
|
||||
return mRecentsAnimationListener;
|
||||
}
|
||||
|
||||
public RecentsAnimationCallbacks getActiveListener() {
|
||||
return mRecentsAnimationListener;
|
||||
}
|
||||
|
||||
public void applyActiveRecentsAnimationState(RecentsAnimationListener listener) {
|
||||
if (mLastRecentsAnimationController != null) {
|
||||
listener.onRecentsAnimationStart(mLastRecentsAnimationController,
|
||||
mLastAnimationTarget);
|
||||
} else if (mLastAnimationCancelled) {
|
||||
listener.onRecentsAnimationCanceled(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
|
@ -156,11 +36,9 @@ public class SwipeSharedState implements RecentsAnimationListener {
|
|||
public void setRecentsAnimationFinishInterrupted(int runningTaskId) {
|
||||
recentsAnimationFinishInterrupted = true;
|
||||
nextRunningTaskId = runningTaskId;
|
||||
mLastAnimationTarget = mLastAnimationTarget.cloneWithoutTargets();
|
||||
}
|
||||
|
||||
public void clearAllState(boolean finishAnimation) {
|
||||
clearListenerState(finishAnimation);
|
||||
public void clearAllState() {
|
||||
canGestureBeContinued = false;
|
||||
recentsAnimationFinishInterrupted = false;
|
||||
nextRunningTaskId = -1;
|
||||
|
@ -172,8 +50,6 @@ public class SwipeSharedState implements RecentsAnimationListener {
|
|||
pw.println(prefix + "canGestureBeContinued=" + canGestureBeContinued);
|
||||
pw.println(prefix + "recentsAnimationFinishInterrupted=" + recentsAnimationFinishInterrupted);
|
||||
pw.println(prefix + "nextRunningTaskId=" + nextRunningTaskId);
|
||||
pw.println(prefix + "lastAnimationCancelled=" + mLastAnimationCancelled);
|
||||
pw.println(prefix + "lastAnimationRunning=" + mLastAnimationRunning);
|
||||
pw.println(prefix + "logTraceId=" + mLogId);
|
||||
}
|
||||
|
||||
|
|
|
@ -250,10 +250,7 @@ public class TouchInteractionService extends Service implements
|
|||
return sSwipeSharedState;
|
||||
}
|
||||
|
||||
private final InputConsumer mResetGestureInputConsumer =
|
||||
new ResetGestureInputConsumer(sSwipeSharedState);
|
||||
|
||||
private final BaseSwipeUpHandler.Factory mWindowTreansformFactory =
|
||||
private final BaseSwipeUpHandler.Factory mWindowTransformFactory =
|
||||
this::createWindowTransformSwipeHandler;
|
||||
private final BaseSwipeUpHandler.Factory mFallbackNoButtonFactory =
|
||||
this::createFallbackNoButtonSwipeHandler;
|
||||
|
@ -264,10 +261,12 @@ public class TouchInteractionService extends Service implements
|
|||
private OverviewComponentObserver mOverviewComponentObserver;
|
||||
private InputConsumerController mInputConsumer;
|
||||
private RecentsAnimationDeviceState mDeviceState;
|
||||
private TaskAnimationManager mTaskAnimationManager;
|
||||
|
||||
private InputConsumer mUncheckedConsumer = InputConsumer.NO_OP;
|
||||
private InputConsumer mConsumer = InputConsumer.NO_OP;
|
||||
private Choreographer mMainChoreographer;
|
||||
private InputConsumer mResetGestureInputConsumer;
|
||||
|
||||
private InputMonitorCompat mInputMonitorCompat;
|
||||
private InputEventReceiver mInputEventReceiver;
|
||||
|
@ -338,13 +337,13 @@ public class TouchInteractionService extends Service implements
|
|||
|
||||
@UiThread
|
||||
public void onUserUnlocked() {
|
||||
mTaskAnimationManager = new TaskAnimationManager();
|
||||
mRecentsModel = RecentsModel.INSTANCE.get(this);
|
||||
mOverviewComponentObserver = new OverviewComponentObserver(this, mDeviceState);
|
||||
mOverviewCommandHelper = new OverviewCommandHelper(this, mDeviceState,
|
||||
mOverviewComponentObserver);
|
||||
mResetGestureInputConsumer = new ResetGestureInputConsumer(mTaskAnimationManager);
|
||||
mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer();
|
||||
|
||||
sSwipeSharedState.setOverviewComponentObserver(mOverviewComponentObserver);
|
||||
mInputConsumer.registerInputConsumer();
|
||||
onSystemUiFlagsChanged();
|
||||
onAssistantVisibilityChanged();
|
||||
|
@ -356,6 +355,18 @@ public class TouchInteractionService extends Service implements
|
|||
resetHomeBounceSeenOnQuickstepEnabledFirstTime();
|
||||
}
|
||||
|
||||
private void onDeferredActivityLaunch() {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
||||
null, () -> {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
sSwipeSharedState.clearAllState();
|
||||
});
|
||||
} else {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
}
|
||||
}
|
||||
|
||||
private void resetHomeBounceSeenOnQuickstepEnabledFirstTime() {
|
||||
if (!mDeviceState.isUserUnlocked() || !mMode.hasGestures) {
|
||||
// Skip if not yet unlocked (can't read user shared prefs) or if the current navigation
|
||||
|
@ -509,7 +520,8 @@ public class TouchInteractionService extends Service implements
|
|||
RunningTaskInfo runningTaskInfo = TraceHelper.whitelistIpcs("getRunningTask.0",
|
||||
() -> mAM.getRunningTask(0));
|
||||
if (!useSharedState) {
|
||||
sSwipeSharedState.clearAllState(false /* finishAnimation */);
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
||||
sSwipeSharedState.clearAllState();
|
||||
}
|
||||
if (mDeviceState.isKeyguardShowingOccluded()) {
|
||||
// This handles apps showing over the lockscreen (e.g. camera)
|
||||
|
@ -572,20 +584,20 @@ public class TouchInteractionService extends Service implements
|
|||
} else {
|
||||
shouldDefer = gestureState.getActivityInterface().deferStartingActivity(mDeviceState,
|
||||
event);
|
||||
factory = mWindowTreansformFactory;
|
||||
factory = mWindowTransformFactory;
|
||||
}
|
||||
|
||||
final boolean disableHorizontalSwipe = mDeviceState.isInExclusionRegion(event);
|
||||
return new OtherActivityInputConsumer(this, mDeviceState, gestureState, runningTaskInfo,
|
||||
shouldDefer, this::onConsumerInactive, sSwipeSharedState, mInputMonitorCompat,
|
||||
disableHorizontalSwipe, factory, mLogId);
|
||||
return new OtherActivityInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, runningTaskInfo, shouldDefer, this::onConsumerInactive,
|
||||
sSwipeSharedState, mInputMonitorCompat, disableHorizontalSwipe, factory, mLogId);
|
||||
}
|
||||
|
||||
private InputConsumer createDeviceLockedInputConsumer(GestureState gestureState,
|
||||
RunningTaskInfo taskInfo) {
|
||||
if (mMode == Mode.NO_BUTTON && taskInfo != null) {
|
||||
return new DeviceLockedInputConsumer(this, mDeviceState, gestureState,
|
||||
sSwipeSharedState, mInputMonitorCompat, taskInfo.taskId, mLogId);
|
||||
return new DeviceLockedInputConsumer(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, sSwipeSharedState, mInputMonitorCompat, taskInfo.taskId, mLogId);
|
||||
} else {
|
||||
return mResetGestureInputConsumer;
|
||||
}
|
||||
|
@ -647,9 +659,8 @@ public class TouchInteractionService extends Service implements
|
|||
return;
|
||||
}
|
||||
|
||||
// Pass null animation handler to indicate this start is preload.
|
||||
startRecentsActivityAsync(mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState(),
|
||||
null);
|
||||
mTaskAnimationManager.preloadRecentsAnimation(
|
||||
mOverviewComponentObserver.getOverviewIntentIgnoreSysUiState());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -725,9 +736,9 @@ public class TouchInteractionService extends Service implements
|
|||
private BaseSwipeUpHandler createWindowTransformSwipeHandler(GestureState gestureState,
|
||||
RunningTaskInfo runningTask, long touchTimeMs, boolean continuingLastGesture,
|
||||
boolean isLikelyToStartNewTask) {
|
||||
return new WindowTransformSwipeHandler(this, mDeviceState, gestureState, runningTask,
|
||||
touchTimeMs, mOverviewComponentObserver, continuingLastGesture, mInputConsumer,
|
||||
mRecentsModel);
|
||||
return new WindowTransformSwipeHandler(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, runningTask, touchTimeMs, mOverviewComponentObserver,
|
||||
continuingLastGesture, mInputConsumer, mRecentsModel);
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createFallbackNoButtonSwipeHandler(GestureState gestureState,
|
||||
|
|
|
@ -192,6 +192,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
private static final int LOG_NO_OP_PAGE_INDEX = -1;
|
||||
|
||||
private final RecentsAnimationDeviceState mDeviceState;
|
||||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
private final GestureState mGestureState;
|
||||
|
||||
private GestureEndTarget mGestureEndTarget;
|
||||
|
@ -225,13 +226,17 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
private final long mTouchTimeMs;
|
||||
private long mLauncherFrameDrawnTime;
|
||||
|
||||
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
|
||||
|
||||
public WindowTransformSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, RunningTaskInfo runningTaskInfo, long touchTimeMs,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
RunningTaskInfo runningTaskInfo, long touchTimeMs,
|
||||
OverviewComponentObserver overviewComponentObserver, boolean continuingLastGesture,
|
||||
InputConsumerController inputConsumer, RecentsModel recentsModel) {
|
||||
super(context, gestureState, overviewComponentObserver, recentsModel, inputConsumer,
|
||||
runningTaskInfo.id);
|
||||
mDeviceState = deviceState;
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mGestureState = gestureState;
|
||||
mTouchTimeMs = touchTimeMs;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
|
@ -401,9 +406,26 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
// that time by a previous window transition.
|
||||
setupRecentsViewUi();
|
||||
|
||||
// For the duration of the gesture, in cases where an activity is launched while the
|
||||
// activity is not yet resumed, finish the animation to ensure we get resumed
|
||||
mGestureState.getActivityInterface().setOnDeferredActivityLaunchCallback(
|
||||
mOnDeferredActivityLaunch);
|
||||
|
||||
notifyGestureStartedAsync();
|
||||
}
|
||||
|
||||
private void onDeferredActivityLaunch() {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
mOverviewComponentObserver.getActivityInterface().switchRunningTaskViewToScreenshot(
|
||||
null, () -> {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
TouchInteractionService.getSwipeSharedState().clearAllState();
|
||||
});
|
||||
} else {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(true /* toHome */);
|
||||
}
|
||||
}
|
||||
|
||||
private void setupRecentsViewUi() {
|
||||
if (mContinuingLastGesture) {
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
|
@ -1091,6 +1113,8 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity>
|
|||
|
||||
mRecentsView.onGestureAnimationEnd();
|
||||
|
||||
// Reset the callback for deferred activity launches
|
||||
mActivityInterface.setOnDeferredActivityLaunchCallback(null);
|
||||
mActivity.getRootView().setOnApplyWindowInsetsListener(null);
|
||||
removeLiveTileOverlay();
|
||||
}
|
||||
|
|
|
@ -22,7 +22,6 @@ import static android.view.MotionEvent.ACTION_UP;
|
|||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.Utilities.squaredTouchSlop;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
|
||||
import static com.android.quickstep.WindowTransformSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
|
||||
|
||||
|
@ -48,6 +47,7 @@ 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;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.InputMonitorCompat;
|
||||
|
@ -76,6 +76,7 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
|
||||
private final Context mContext;
|
||||
private final RecentsAnimationDeviceState mDeviceState;
|
||||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
private final GestureState mGestureState;
|
||||
private final float mTouchSlopSquared;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
|
@ -98,10 +99,12 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
private RecentsAnimationTargets mRecentsAnimationTargets;
|
||||
|
||||
public DeviceLockedInputConsumer(Context context, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, SwipeSharedState swipeSharedState,
|
||||
InputMonitorCompat inputMonitorCompat, int runningTaskId, int logId) {
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
||||
int runningTaskId, int logId) {
|
||||
mContext = context;
|
||||
mDeviceState = deviceState;
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mGestureState = gestureState;
|
||||
mTouchSlopSquared = squaredTouchSlop(context);
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
|
@ -207,16 +210,14 @@ public class DeviceLockedInputConsumer implements InputConsumer,
|
|||
|
||||
private void startRecentsTransition() {
|
||||
mThresholdCrossed = true;
|
||||
RecentsAnimationCallbacks callbacks = mSwipeSharedState.newRecentsAnimationCallbacks();
|
||||
callbacks.addListener(this);
|
||||
mInputMonitorCompat.pilferPointers();
|
||||
|
||||
Intent intent = new Intent(Intent.ACTION_MAIN)
|
||||
.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);
|
||||
|
||||
mInputMonitorCompat.pilferPointers();
|
||||
startRecentsActivityAsync(intent, callbacks);
|
||||
mTaskAnimationManager.startRecentsAnimation(mGestureState, intent, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,7 +26,6 @@ import static android.view.MotionEvent.INVALID_POINTER_ID;
|
|||
import static com.android.launcher3.Utilities.EDGE_NAV_BAR;
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.util.TraceHelper.FLAG_CHECK_FOR_RACE_CONDITIONS;
|
||||
import static com.android.quickstep.TouchInteractionService.startRecentsActivityAsync;
|
||||
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
|
||||
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
|
||||
|
||||
|
@ -58,6 +57,7 @@ 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;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.CachedEventDispatcher;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
|
@ -80,7 +80,9 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
public static final float QUICKSTEP_TOUCH_SLOP_RATIO = 3;
|
||||
|
||||
private final RecentsAnimationDeviceState mDeviceState;
|
||||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
private final GestureState mGestureState;
|
||||
private RecentsAnimationCallbacks mActiveCallbacks;
|
||||
private final CachedEventDispatcher mRecentsViewDispatcher = new CachedEventDispatcher();
|
||||
private final RunningTaskInfo mRunningTask;
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
|
@ -95,6 +97,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
private final Consumer<OtherActivityInputConsumer> mOnCompleteCallback;
|
||||
private final MotionPauseDetector mMotionPauseDetector;
|
||||
private final float mMotionPauseMinDisplacement;
|
||||
|
||||
private VelocityTracker mVelocityTracker;
|
||||
|
||||
private BaseSwipeUpHandler mInteractionHandler;
|
||||
|
@ -126,13 +129,15 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
private int mLogId;
|
||||
|
||||
public OtherActivityInputConsumer(Context base, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, RunningTaskInfo runningTaskInfo,
|
||||
boolean isDeferredDownTarget, Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
RunningTaskInfo runningTaskInfo, boolean isDeferredDownTarget,
|
||||
Consumer<OtherActivityInputConsumer> onCompleteCallback,
|
||||
SwipeSharedState swipeSharedState, InputMonitorCompat inputMonitorCompat,
|
||||
boolean disableHorizontalSwipe, Factory handlerFactory, int logId) {
|
||||
super(base);
|
||||
mLogId = logId;
|
||||
mDeviceState = deviceState;
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
mGestureState = gestureState;
|
||||
mMainThreadHandler = new Handler(Looper.getMainLooper());
|
||||
mRunningTask = runningTaskInfo;
|
||||
|
@ -147,7 +152,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
mVelocityTracker = VelocityTracker.obtain();
|
||||
mInputMonitorCompat = inputMonitorCompat;
|
||||
|
||||
boolean continuingPreviousGesture = swipeSharedState.getActiveListener() != null;
|
||||
boolean continuingPreviousGesture = mTaskAnimationManager.isRecentsAnimationRunning();
|
||||
mIsDeferredDownTarget = !continuingPreviousGesture && isDeferredDownTarget;
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
|
||||
|
@ -329,25 +334,22 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
long touchTimeMs, boolean isLikelyToStartNewTask) {
|
||||
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimation");
|
||||
|
||||
RecentsAnimationCallbacks listenerSet = mSwipeSharedState.getActiveListener();
|
||||
final BaseSwipeUpHandler handler = mHandlerFactory.newHandler(mGestureState, mRunningTask,
|
||||
touchTimeMs, listenerSet != null, isLikelyToStartNewTask);
|
||||
mInteractionHandler = mHandlerFactory.newHandler(mGestureState, mRunningTask, touchTimeMs,
|
||||
mTaskAnimationManager.isRecentsAnimationRunning(), isLikelyToStartNewTask);
|
||||
mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
|
||||
mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler::onMotionPauseChanged);
|
||||
mInteractionHandler.initWhenReady();
|
||||
|
||||
mInteractionHandler = handler;
|
||||
handler.setGestureEndCallback(this::onInteractionGestureFinished);
|
||||
mMotionPauseDetector.setOnMotionPauseListener(handler::onMotionPauseChanged);
|
||||
handler.initWhenReady();
|
||||
|
||||
if (listenerSet != null) {
|
||||
listenerSet.addListener(handler);
|
||||
mSwipeSharedState.applyActiveRecentsAnimationState(handler);
|
||||
if (mTaskAnimationManager.isRecentsAnimationRunning()) {
|
||||
mActiveCallbacks = mTaskAnimationManager.continueRecentsAnimation(mGestureState);
|
||||
mActiveCallbacks.addListener(mInteractionHandler);
|
||||
mTaskAnimationManager.notifyRecentsAnimationState(mInteractionHandler);
|
||||
notifyGestureStarted();
|
||||
} else {
|
||||
RecentsAnimationCallbacks callbacks = mSwipeSharedState.newRecentsAnimationCallbacks();
|
||||
callbacks.addListener(handler);
|
||||
Intent intent = handler.getLaunchIntent();
|
||||
Intent intent = mInteractionHandler.getLaunchIntent();
|
||||
intent.putExtra(INTENT_EXTRA_LOG_TRACE_ID, mLogId);
|
||||
startRecentsActivityAsync(intent, callbacks);
|
||||
mActiveCallbacks = mTaskAnimationManager.startRecentsAnimation(mGestureState, intent,
|
||||
mInteractionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -415,9 +417,8 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
|||
}
|
||||
|
||||
private void removeListener() {
|
||||
RecentsAnimationCallbacks listenerSet = mSwipeSharedState.getActiveListener();
|
||||
if (listenerSet != null) {
|
||||
listenerSet.removeListener(mInteractionHandler);
|
||||
if (mActiveCallbacks != null) {
|
||||
mActiveCallbacks.removeListener(mInteractionHandler);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,17 +18,18 @@ package com.android.quickstep.inputconsumers;
|
|||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.quickstep.InputConsumer;
|
||||
import com.android.quickstep.SwipeSharedState;
|
||||
import com.android.quickstep.TaskAnimationManager;
|
||||
import com.android.quickstep.TouchInteractionService;
|
||||
|
||||
/**
|
||||
* A NO_OP input consumer which also resets any pending gesture
|
||||
*/
|
||||
public class ResetGestureInputConsumer implements InputConsumer {
|
||||
|
||||
private final SwipeSharedState mSwipeSharedState;
|
||||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
|
||||
public ResetGestureInputConsumer(SwipeSharedState swipeSharedState) {
|
||||
mSwipeSharedState = swipeSharedState;
|
||||
public ResetGestureInputConsumer(TaskAnimationManager taskAnimationManager) {
|
||||
mTaskAnimationManager = taskAnimationManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -39,8 +40,9 @@ public class ResetGestureInputConsumer implements InputConsumer {
|
|||
@Override
|
||||
public void onMotionEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN
|
||||
&& mSwipeSharedState.getActiveListener() != null) {
|
||||
mSwipeSharedState.clearAllState(false /* finishAnimation */);
|
||||
&& mTaskAnimationManager.isRecentsAnimationRunning()) {
|
||||
mTaskAnimationManager.finishRunningRecentsAnimation(false /* toHome */);
|
||||
TouchInteractionService.getSwipeSharedState().clearAllState();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -102,8 +102,9 @@ public class LauncherRecentsView extends RecentsView<Launcher> implements StateL
|
|||
@Override
|
||||
public void startHome() {
|
||||
if (ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
switchToScreenshot(() -> finishRecentsAnimation(true /* toRecents */,
|
||||
() -> mActivity.getStateManager().goToState(NORMAL)));
|
||||
switchToScreenshot(null,
|
||||
() -> finishRecentsAnimation(true /* toRecents */,
|
||||
() -> mActivity.getStateManager().goToState(NORMAL)));
|
||||
} else {
|
||||
mActivity.getStateManager().goToState(NORMAL);
|
||||
}
|
||||
|
|
|
@ -1851,20 +1851,20 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
|||
return Math.max(insets.getSystemGestureInsets().right, insets.getSystemWindowInsetRight());
|
||||
}
|
||||
|
||||
|
||||
/** If it's in the live tile mode, switch the running task into screenshot mode. */
|
||||
public void switchToScreenshot(Runnable onFinishRunnable) {
|
||||
public void switchToScreenshot(ThumbnailData thumbnailData, Runnable onFinishRunnable) {
|
||||
TaskView taskView = getRunningTaskView();
|
||||
if (taskView == null) {
|
||||
if (onFinishRunnable != null) {
|
||||
onFinishRunnable.run();
|
||||
if (taskView != null) {
|
||||
taskView.setShowScreenshot(true);
|
||||
if (thumbnailData != null) {
|
||||
taskView.getThumbnail().setThumbnail(taskView.getTask(), thumbnailData);
|
||||
} else {
|
||||
taskView.getThumbnail().refresh();
|
||||
}
|
||||
return;
|
||||
ViewUtils.postDraw(taskView, onFinishRunnable);
|
||||
} else {
|
||||
onFinishRunnable.run();
|
||||
}
|
||||
|
||||
taskView.setShowScreenshot(true);
|
||||
taskView.getThumbnail().refresh();
|
||||
ViewUtils.postDraw(taskView, onFinishRunnable);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -60,6 +60,11 @@ public interface BaseActivityInterface<T extends BaseDraggingActivity> {
|
|||
|
||||
ActivityInitListener createActivityInitListener(BiPredicate<T, Boolean> onInitListener);
|
||||
|
||||
/**
|
||||
* Sets a callback to be run when an activity launch happens while launcher is not yet resumed.
|
||||
*/
|
||||
default void setOnDeferredActivityLaunchCallback(Runnable r) {}
|
||||
|
||||
@Nullable
|
||||
T getCreatedActivity();
|
||||
|
||||
|
@ -96,7 +101,8 @@ public interface BaseActivityInterface<T extends BaseDraggingActivity> {
|
|||
|
||||
default void closeOverlay() { }
|
||||
|
||||
default void switchToScreenshot(ThumbnailData thumbnailData, Runnable runnable) {}
|
||||
default void switchRunningTaskViewToScreenshot(ThumbnailData thumbnailData,
|
||||
Runnable runnable) {}
|
||||
|
||||
interface AnimationFactory {
|
||||
|
||||
|
|
|
@ -16,12 +16,13 @@
|
|||
package com.android.quickstep;
|
||||
|
||||
import com.android.launcher3.BaseDraggingActivity;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
|
||||
/**
|
||||
* Manages the state for an active system gesture, listens for events from the system and Launcher,
|
||||
* and fires events when the states change.
|
||||
*/
|
||||
public class GestureState {
|
||||
public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
|
||||
// Needed to interact with the current activity
|
||||
private BaseActivityInterface mActivityInterface;
|
||||
|
@ -33,4 +34,20 @@ public class GestureState {
|
|||
public <T extends BaseDraggingActivity> BaseActivityInterface<T> getActivityInterface() {
|
||||
return mActivityInterface;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||
RecentsAnimationTargets targets) {
|
||||
// To be implemented
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
// To be implemented
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
// To be implemented
|
||||
}
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public class RecentsAnimationCallbacks implements
|
|||
*/
|
||||
public interface RecentsAnimationListener {
|
||||
default void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||
RecentsAnimationTargets targetSet) {}
|
||||
RecentsAnimationTargets targets) {}
|
||||
|
||||
/**
|
||||
* Callback from the system when the recents animation is canceled. {@param thumbnailData}
|
||||
|
@ -135,6 +135,9 @@ public class RecentsAnimationCallbacks implements
|
|||
*/
|
||||
default void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {}
|
||||
|
||||
/**
|
||||
* Callback made whenever the recents animation is finished.
|
||||
*/
|
||||
default void onRecentsAnimationFinished(RecentsAnimationController controller) {}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -41,13 +41,4 @@ public class RecentsAnimationTargets extends RemoteAnimationTargets {
|
|||
public boolean hasTargets() {
|
||||
return unfilteredApps.length != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clones the target set without any actual targets. Used only when continuing a gesture after
|
||||
* the actual recents animation has finished.
|
||||
*/
|
||||
public RecentsAnimationTargets cloneWithoutTargets() {
|
||||
return new RecentsAnimationTargets(new RemoteAnimationTargetCompat[0],
|
||||
new RemoteAnimationTargetCompat[0], homeContentInsets, minimizedHomeBounds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,173 @@
|
|||
/*
|
||||
* 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 static com.android.launcher3.util.Executors.MAIN_EXECUTOR;
|
||||
import static com.android.launcher3.util.Executors.UI_HELPER_EXECUTOR;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.config.FeatureFlags;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
|
||||
public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAnimationListener {
|
||||
|
||||
private RecentsAnimationController mController;
|
||||
private RecentsAnimationCallbacks mCallbacks;
|
||||
private RecentsAnimationTargets mTargets;
|
||||
// Temporary until we can hook into gesture state events
|
||||
private GestureState mLastGestureState;
|
||||
private ThumbnailData mCanceledThumbnail;
|
||||
|
||||
/**
|
||||
* Preloads the recents animation.
|
||||
*/
|
||||
public void preloadRecentsAnimation(Intent intent) {
|
||||
// Pass null animation handler to indicate this start is for preloading
|
||||
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
||||
.startRecentsActivity(intent, null, null, null, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new recents animation for the activity with the given {@param intent}.
|
||||
*/
|
||||
@UiThread
|
||||
public RecentsAnimationCallbacks startRecentsAnimation(GestureState gestureState,
|
||||
Intent intent, RecentsAnimationCallbacks.RecentsAnimationListener listener) {
|
||||
// Notify if recents animation is still running
|
||||
if (mController != null) {
|
||||
String msg = "New recents animation started before old animation completed";
|
||||
if (FeatureFlags.IS_DOGFOOD_BUILD) {
|
||||
throw new IllegalArgumentException(msg);
|
||||
} else {
|
||||
Log.e("TaskAnimationManager", msg, new Exception());
|
||||
}
|
||||
}
|
||||
// But force-finish it anyways
|
||||
finishRunningRecentsAnimation(false /* toHome */);
|
||||
|
||||
final BaseActivityInterface activityInterface = gestureState.getActivityInterface();
|
||||
mLastGestureState = gestureState;
|
||||
mCallbacks = new RecentsAnimationCallbacks(activityInterface.shouldMinimizeSplitScreen());
|
||||
mCallbacks.addListener(new RecentsAnimationCallbacks.RecentsAnimationListener() {
|
||||
@Override
|
||||
public void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||
RecentsAnimationTargets targets) {
|
||||
mController = controller;
|
||||
mTargets = targets;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
if (thumbnailData != null) {
|
||||
// If a screenshot is provided, switch to the screenshot before cleaning up
|
||||
activityInterface.switchRunningTaskViewToScreenshot(thumbnailData,
|
||||
() -> cleanUpRecentsAnimation());
|
||||
} else {
|
||||
cleanUpRecentsAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationFinished(RecentsAnimationController controller) {
|
||||
cleanUpRecentsAnimation();
|
||||
}
|
||||
});
|
||||
mCallbacks.addListener(gestureState);
|
||||
mCallbacks.addListener(listener);
|
||||
UI_HELPER_EXECUTOR.execute(() -> ActivityManagerWrapper.getInstance()
|
||||
.startRecentsActivity(intent, null, mCallbacks, null, null));
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Continues the existing running recents animation for a new gesture.
|
||||
*/
|
||||
public RecentsAnimationCallbacks continueRecentsAnimation(GestureState gestureState) {
|
||||
mCallbacks.removeListener(mLastGestureState);
|
||||
mLastGestureState = gestureState;
|
||||
mCallbacks.addListener(gestureState);
|
||||
return mCallbacks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finishes the running recents animation.
|
||||
*/
|
||||
public void finishRunningRecentsAnimation(boolean toHome) {
|
||||
if (mController != null) {
|
||||
mCallbacks.notifyAnimationCanceled();
|
||||
Utilities.postAsyncCallback(MAIN_EXECUTOR.getHandler(), toHome
|
||||
? mController::finishAnimationToHome
|
||||
: mController::finishAnimationToApp);
|
||||
cleanUpRecentsAnimation();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to notify a listener of the current recents animation state (used if the listener was
|
||||
* not yet added to the callbacks at the point that the listener callbacks would have been
|
||||
* made).
|
||||
*/
|
||||
public void notifyRecentsAnimationState(
|
||||
RecentsAnimationCallbacks.RecentsAnimationListener listener) {
|
||||
if (isRecentsAnimationRunning()) {
|
||||
listener.onRecentsAnimationStart(mController, mTargets);
|
||||
}
|
||||
// TODO: Do we actually need to report canceled/finished?
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether there is a recents animation running.
|
||||
*/
|
||||
public boolean isRecentsAnimationRunning() {
|
||||
return mController != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the recents animation entirely.
|
||||
*/
|
||||
private void cleanUpRecentsAnimation() {
|
||||
// Clean up the screenshot if necessary
|
||||
if (mController != null && mCanceledThumbnail != null) {
|
||||
mController.cleanupScreenshot();
|
||||
}
|
||||
|
||||
// Release all the target leashes
|
||||
if (mTargets != null) {
|
||||
mTargets.release();
|
||||
}
|
||||
|
||||
// Remove gesture state from callbacks
|
||||
if (mCallbacks != null && mLastGestureState != null) {
|
||||
mCallbacks.removeListener(mLastGestureState);
|
||||
}
|
||||
|
||||
mController = null;
|
||||
mCallbacks = null;
|
||||
mTargets = null;
|
||||
mCanceledThumbnail = null;
|
||||
mLastGestureState = null;
|
||||
}
|
||||
|
||||
public void dump() {
|
||||
// TODO
|
||||
}
|
||||
}
|
|
@ -267,6 +267,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
private ArrayList<OnResumeCallback> mOnResumeCallbacks = new ArrayList<>();
|
||||
|
||||
// Used to notify when an activity launch has been deferred because launcher is not yet resumed
|
||||
// TODO: See if we can remove this later
|
||||
private Runnable mOnDeferredActivityLaunchCallback;
|
||||
|
||||
private ViewOnDrawExecutor mPendingExecutor;
|
||||
|
||||
private LauncherModel mModel;
|
||||
|
@ -1886,7 +1890,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
// recents animation into launcher. Defer launching the activity until Launcher is
|
||||
// next resumed.
|
||||
addOnResumeCallback(() -> startActivitySafely(v, intent, item, sourceContainer));
|
||||
UiFactory.clearSwipeSharedState(this, true /* finishAnimation */);
|
||||
if (mOnDeferredActivityLaunchCallback != null) {
|
||||
mOnDeferredActivityLaunchCallback.run();
|
||||
mOnDeferredActivityLaunchCallback = null;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1947,6 +1954,14 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
mOnResumeCallbacks.add(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Persistant callback which notifies when an activity launch is deferred because the activity
|
||||
* was not yet resumed.
|
||||
*/
|
||||
public void setOnDeferredActivityLaunchCallback(Runnable callback) {
|
||||
mOnDeferredActivityLaunchCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of the method from LauncherModel.Callbacks.
|
||||
*/
|
||||
|
|
|
@ -96,9 +96,6 @@ public class UiFactory {
|
|||
|
||||
public static void resetPendingActivityResults(Launcher launcher, int requestCode) { }
|
||||
|
||||
/** No-op. */
|
||||
public static void clearSwipeSharedState(Launcher launcher, boolean finishAnimation) { }
|
||||
|
||||
public static Person[] getPersons(ShortcutInfo si) {
|
||||
return Utilities.EMPTY_PERSON_ARRAY;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue