Finish recents animation when starting a new activity
- Defer starting the activity when an activity is paused, and finish the current animation to trigger launcher to be resumed Bug: 132811175 Test: Swipe up and launch a new app Change-Id: I78b76800052512eb93f69ccf0523f4d752a82ece
This commit is contained in:
parent
a730a233b8
commit
0b70cd4ca4
|
@ -89,4 +89,6 @@ public abstract class RecentsUiFactory {
|
|||
public static RotationMode getRotationMode(DeviceProfile dp) {
|
||||
return RotationMode.NORMAL;
|
||||
}
|
||||
|
||||
public static void clearSwipeSharedState(boolean finishAnimation) {}
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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:");
|
||||
|
|
|
@ -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 */);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -244,7 +244,7 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns,
|
|||
|
||||
@Thunk boolean mWorkspaceLoading = true;
|
||||
|
||||
private OnResumeCallback mOnResumeCallback;
|
||||
private ArrayList<OnResumeCallback> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -93,4 +93,6 @@ public class UiFactory {
|
|||
|
||||
public static void resetPendingActivityResults(Launcher launcher, int requestCode) { }
|
||||
|
||||
public static void clearSwipeSharedState(boolean finishAnimation) {}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue