diff --git a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java index 45822432f5..cbc77d2720 100644 --- a/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +++ b/go/quickstep/src/com/android/launcher3/uioverrides/RecentsUiFactory.java @@ -89,4 +89,6 @@ public abstract class RecentsUiFactory { public static RotationMode getRotationMode(DeviceProfile dp) { return RotationMode.NORMAL; } + + public static void clearSwipeSharedState(boolean finishAnimation) {} } diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java index 8d5ac50942..6ecf1c11bd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java +++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/uioverrides/RecentsUiFactory.java @@ -46,6 +46,7 @@ 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.views.RecentsView; import com.android.systemui.shared.system.WindowManagerWrapper; @@ -183,6 +184,13 @@ public abstract class RecentsUiFactory { return new RecentsViewStateController(launcher); } + /** + * Clears the swipe shared state for the current swipe gesture. + */ + public static void clearSwipeSharedState(boolean finishAnimation) { + TouchInteractionService.getSwipeSharedState().clearAllState(finishAnimation); + } + /** * Recents logic that triggers when launcher state changes or launcher activity stops/resumes. * diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java index 6689ce3d78..c55f656dfd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/SwipeSharedState.java @@ -72,13 +72,15 @@ public class SwipeSharedState implements SwipeAnimationListener { mLastAnimationRunning = false; } - private void clearListenerState() { + private void clearListenerState(boolean finishAnimation) { if (mRecentsAnimationListener != null) { mRecentsAnimationListener.removeListener(this); mRecentsAnimationListener.cancelListener(); if (mLastAnimationRunning && mLastAnimationTarget != null) { Utilities.postAsyncCallback(MAIN_THREAD_EXECUTOR.getHandler(), - mLastAnimationTarget::cancelAnimation); + finishAnimation + ? mLastAnimationTarget::finishAnimation + : mLastAnimationTarget::cancelAnimation); mLastAnimationTarget = null; } } @@ -106,7 +108,7 @@ public class SwipeSharedState implements SwipeAnimationListener { } } - clearListenerState(); + clearListenerState(false /* finishAnimation */); boolean shouldMinimiseSplitScreen = mOverviewComponentObserver == null ? false : mOverviewComponentObserver.getActivityControlHelper().shouldMinimizeSplitScreen(); mRecentsAnimationListener = new RecentsAnimationListenerSet( @@ -138,8 +140,8 @@ public class SwipeSharedState implements SwipeAnimationListener { mLastAnimationTarget = mLastAnimationTarget.cloneWithoutTargets(); } - public void clearAllState() { - clearListenerState(); + public void clearAllState(boolean finishAnimation) { + clearListenerState(finishAnimation); canGestureBeContinued = false; recentsAnimationFinishInterrupted = false; nextRunningTaskId = -1; diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java index 8f08f0de9b..53da0f92dd 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/TouchInteractionService.java @@ -225,14 +225,18 @@ public class TouchInteractionService extends Service implements }; private static boolean sConnected = false; + private static final SwipeSharedState sSwipeSharedState = new SwipeSharedState(); public static boolean isConnected() { return sConnected; } - private final SwipeSharedState mSwipeSharedState = new SwipeSharedState(); + public static SwipeSharedState getSwipeSharedState() { + return sSwipeSharedState; + } + private final InputConsumer mResetGestureInputConsumer = - new ResetGestureInputConsumer(mSwipeSharedState); + new ResetGestureInputConsumer(sSwipeSharedState); private ActivityManagerWrapper mAM; private RecentsModel mRecentsModel; @@ -436,7 +440,7 @@ public class TouchInteractionService extends Service implements mInputConsumer = InputConsumerController.getRecentsAnimationInputConsumer(); mIsUserUnlocked = true; - mSwipeSharedState.setOverviewComponentObserver(mOverviewComponentObserver); + sSwipeSharedState.setOverviewComponentObserver(mOverviewComponentObserver); mInputConsumer.registerInputConsumer(); onSystemUiProxySet(); onSystemUiFlagsChanged(); @@ -589,7 +593,7 @@ public class TouchInteractionService extends Service implements private InputConsumer newBaseConsumer(boolean useSharedState, MotionEvent event) { final RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0); if (!useSharedState) { - mSwipeSharedState.clearAllState(); + sSwipeSharedState.clearAllState(false /* finishAnimation */); } if ((mSystemUiStateFlags & SYSUI_STATE_STATUS_BAR_KEYGUARD_SHOWING_OCCLUDED) != 0) { // This handles apps showing over the lockscreen (e.g. camera) @@ -599,16 +603,16 @@ public class TouchInteractionService extends Service implements final ActivityControlHelper activityControl = mOverviewComponentObserver.getActivityControlHelper(); - if (runningTaskInfo == null && !mSwipeSharedState.goingToLauncher - && !mSwipeSharedState.recentsAnimationFinishInterrupted) { + if (runningTaskInfo == null && !sSwipeSharedState.goingToLauncher + && !sSwipeSharedState.recentsAnimationFinishInterrupted) { return mResetGestureInputConsumer; - } else if (mSwipeSharedState.recentsAnimationFinishInterrupted) { + } else if (sSwipeSharedState.recentsAnimationFinishInterrupted) { // If the finish animation was interrupted, then continue using the other activity input // consumer but with the next task as the running task RunningTaskInfo info = new ActivityManager.RunningTaskInfo(); - info.id = mSwipeSharedState.nextRunningTaskId; + info.id = sSwipeSharedState.nextRunningTaskId; return createOtherActivityInputConsumer(event, info); - } else if (mSwipeSharedState.goingToLauncher || activityControl.isResumed()) { + } else if (sSwipeSharedState.goingToLauncher || activityControl.isResumed()) { return createOverviewInputConsumer(event); } else if (ENABLE_QUICKSTEP_LIVE_TILE.get() && activityControl.isInLiveTileMode()) { return createOverviewInputConsumer(event); @@ -617,7 +621,7 @@ public class TouchInteractionService extends Service implements return mResetGestureInputConsumer; } else if (mMode == Mode.NO_BUTTON && !mOverviewComponentObserver.isHomeAndOverviewSame()) { return new FallbackNoButtonInputConsumer(this, activityControl, - mInputMonitorCompat, mSwipeSharedState, mSwipeTouchRegion, + mInputMonitorCompat, sSwipeSharedState, mSwipeTouchRegion, mOverviewComponentObserver, disableHorizontalSwipe(event), runningTaskInfo); } else { return createOtherActivityInputConsumer(event, runningTaskInfo); @@ -640,13 +644,13 @@ public class TouchInteractionService extends Service implements return new OtherActivityInputConsumer(this, runningTaskInfo, mRecentsModel, mOverviewComponentObserver.getOverviewIntent(), activityControl, shouldDefer, mOverviewCallbacks, mInputConsumer, this::onConsumerInactive, - mSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, + sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, disableHorizontalSwipe(event)); } private InputConsumer createDeviceLockedInputConsumer(RunningTaskInfo taskInfo) { if (mMode == Mode.NO_BUTTON && taskInfo != null) { - return new DeviceLockedInputConsumer(this, mSwipeSharedState, mInputMonitorCompat, + return new DeviceLockedInputConsumer(this, sSwipeSharedState, mInputMonitorCompat, mSwipeTouchRegion, taskInfo.taskId); } else { return mResetGestureInputConsumer; @@ -661,7 +665,7 @@ public class TouchInteractionService extends Service implements return mResetGestureInputConsumer; } - if (activity.getRootView().hasWindowFocus() || mSwipeSharedState.goingToLauncher) { + if (activity.getRootView().hasWindowFocus() || sSwipeSharedState.goingToLauncher) { return new OverviewInputConsumer(activity, mInputMonitorCompat, false /* startingInActivityBounds */); } else { @@ -708,7 +712,7 @@ public class TouchInteractionService extends Service implements + mOverviewComponentObserver.getActivityControlHelper().isResumed()); pw.println(" useSharedState=" + mConsumer.useSharedSwipeState()); if (mConsumer.useSharedSwipeState()) { - mSwipeSharedState.dump(" ", pw); + sSwipeSharedState.dump(" ", pw); } pw.println(" mConsumer=" + mConsumer.getName()); pw.println("FeatureFlags:"); diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java index 56cba2192a..8eede81b84 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/inputconsumers/ResetGestureInputConsumer.java @@ -39,7 +39,7 @@ public class ResetGestureInputConsumer implements InputConsumer { public void onMotionEvent(MotionEvent ev) { if (ev.getAction() == MotionEvent.ACTION_DOWN && mSwipeSharedState.getActiveListener() != null) { - mSwipeSharedState.clearAllState(); + mSwipeSharedState.clearAllState(false /* finishAnimation */); } } } diff --git a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java index df9efa2477..381c27a284 100644 --- a/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java +++ b/quickstep/recents_ui_overrides/src/com/android/quickstep/util/SwipeAnimationTargetSet.java @@ -106,6 +106,10 @@ public class SwipeAnimationTargetSet extends RemoteAnimationTargetSet { finishController(false /* toRecents */, null, false /* sendUserLeaveHint */); } + public void finishAnimation() { + finishController(true /* toRecents */, null, false /* sendUserLeaveHint */); + } + public interface SwipeAnimationListener { void onRecentsAnimationStart(SwipeAnimationTargetSet targetSet); diff --git a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java index 8643160950..44324cb2e4 100644 --- a/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java +++ b/quickstep/src/com/android/launcher3/QuickstepAppTransitionManagerImpl.java @@ -765,7 +765,7 @@ public abstract class QuickstepAppTransitionManagerImpl extends LauncherAppTrans LauncherAnimationRunner.AnimationResult result) { if (!mLauncher.hasBeenResumed()) { // If launcher is not resumed, wait until new async-frame after resume - mLauncher.setOnResumeCallback(() -> + mLauncher.addOnResumeCallback(() -> postAsyncCallback(mHandler, () -> onCreateAnimation(targetCompats, result))); return; diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index ad2783e0c6..d9af4da8e8 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -244,7 +244,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Thunk boolean mWorkspaceLoading = true; - private OnResumeCallback mOnResumeCallback; + private ArrayList mOnResumeCallbacks = new ArrayList<>(); private ViewOnDrawExecutor mPendingExecutor; @@ -869,6 +869,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, @Override protected void onStop() { super.onStop(); + if (mLauncherCallbacks != null) { mLauncherCallbacks.onStop(); } @@ -951,7 +952,10 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, mHandler.removeCallbacks(mHandleDeferredResume); Utilities.postAsyncCallback(mHandler, mHandleDeferredResume); - setOnResumeCallback(null); + for (OnResumeCallback cb : mOnResumeCallbacks) { + cb.onLauncherResume(); + } + mOnResumeCallbacks.clear(); if (mLauncherCallbacks != null) { mLauncherCallbacks.onResume(); @@ -1805,6 +1809,16 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, android.util.Log.d(TestProtocol.NO_START_TAG, "startActivitySafely outer"); } + + if (!hasBeenResumed()) { + // Workaround an issue where the WM launch animation is clobbered when finishing the + // recents animation into launcher. Defer launching the activity until Launcher is + // next resumed. + addOnResumeCallback(() -> startActivitySafely(v, intent, item, sourceContainer)); + UiFactory.clearSwipeSharedState(true /* finishAnimation */); + return true; + } + boolean success = super.startActivitySafely(v, intent, item, sourceContainer); if (success && v instanceof BubbleTextView) { // This is set to the view that launched the activity that navigated the user away @@ -1813,7 +1827,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, // state when we return to launcher. BubbleTextView btv = (BubbleTextView) v; btv.setStayPressed(true); - setOnResumeCallback(btv); + addOnResumeCallback(btv); } return success; } @@ -1861,11 +1875,8 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, return result; } - public void setOnResumeCallback(OnResumeCallback callback) { - if (mOnResumeCallback != null) { - mOnResumeCallback.onLauncherResume(); - } - mOnResumeCallback = callback; + public void addOnResumeCallback(OnResumeCallback callback) { + mOnResumeCallbacks.add(callback); } /** diff --git a/src/com/android/launcher3/SecondaryDropTarget.java b/src/com/android/launcher3/SecondaryDropTarget.java index 0cf6e44c63..55cb6f2143 100644 --- a/src/com/android/launcher3/SecondaryDropTarget.java +++ b/src/com/android/launcher3/SecondaryDropTarget.java @@ -179,7 +179,7 @@ public class SecondaryDropTarget extends ButtonDropTarget implements OnAlarmList DeferredOnComplete deferred = (DeferredOnComplete) d.dragSource; if (target != null) { deferred.mPackageName = target.getPackageName(); - mLauncher.setOnResumeCallback(deferred); + mLauncher.addOnResumeCallback(deferred); } else { deferred.sendFailure(); } diff --git a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java index 17ff66e92c..5cc64dc9aa 100644 --- a/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java +++ b/src_ui_overrides/com/android/launcher3/uioverrides/UiFactory.java @@ -93,4 +93,6 @@ public class UiFactory { public static void resetPendingActivityResults(Launcher launcher, int requestCode) { } + public static void clearSwipeSharedState(boolean finishAnimation) {} + }