Loading quickstep/src/com/android/quickstep/DeferredTouchConsumer.java +5 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,11 @@ public class DeferredTouchConsumer implements TouchConsumer { return mTarget.forceToLauncherConsumer(); } @Override public OtherActivityTouchConsumer.RecentsAnimationState getRecentsAnimationStateToReuse() { return mTarget.getRecentsAnimationStateToReuse(); } @Override public boolean deferNextEventToMainThread() { // If our target is still null, defer the next target as well Loading quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +55 −20 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; Loading Loading @@ -102,18 +101,21 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private WindowTransformSwipeHandler mInteractionHandler; private int mDisplayRotation; private Rect mStableInsets = new Rect(); private boolean mCanGestureBeContinued; private VelocityTracker mVelocityTracker; private MotionPauseDetector mMotionPauseDetector; private MotionEventQueue mEventQueue; private boolean mIsGoingToLauncher; private RecentsAnimationState mRecentsAnimationState; public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo, RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl, MainThreadExecutor mainThreadExecutor, Choreographer backgroundThreadChoreographer, @HitTarget int downHitTarget, OverviewCallbacks overviewCallbacks, TaskOverlayFactory taskOverlayFactory, InputConsumerController inputConsumer, VelocityTracker velocityTracker, TouchInteractionLog touchInteractionLog) { VelocityTracker velocityTracker, TouchInteractionLog touchInteractionLog, @Nullable RecentsAnimationState recentsAnimationStateToReuse) { super(base); mRunningTask = runningTaskInfo; Loading @@ -130,6 +132,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTouchInteractionLog = touchInteractionLog; mTouchInteractionLog.setTouchConsumer(this); mInputConsumer = inputConsumer; mRecentsAnimationState = recentsAnimationStateToReuse; } @Override Loading @@ -150,7 +153,8 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mActivePointerId = ev.getPointerId(0); mDownPos.set(ev.getX(), ev.getY()); mLastPos.set(mDownPos); mPassedInitialSlop = false; // If mRecentsAnimationState != null, we are continuing the previous gesture. mPassedInitialSlop = mRecentsAnimationState != null; mQuickStepDragSlop = NavigationBarCompat.getQuickStepDragSlopPx(); // Start the window animation on down to give more time for launcher to draw if the Loading Loading @@ -256,10 +260,15 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTouchInteractionLog.startRecentsAnimation(); // Create the shared handler RecentsAnimationState animationState = new RecentsAnimationState(); boolean reuseOldAnimState = mRecentsAnimationState != null; if (reuseOldAnimState) { mRecentsAnimationState.changeParent(this); } else { mRecentsAnimationState = new RecentsAnimationState(this); } final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler( animationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper, mInputConsumer, mTouchInteractionLog); mRecentsAnimationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper, reuseOldAnimState, mInputConsumer, mTouchInteractionLog); // Preload the plan mRecentsModel.getTasks(null); Loading Loading @@ -291,8 +300,18 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } }; Runnable startActivity = () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mHomeIntent, assistDataReceiver, animationState, null, null); Runnable startActivity; if (reuseOldAnimState) { startActivity = () -> { handler.onRecentsAnimationStart(mRecentsAnimationState.mController, mRecentsAnimationState.mTargets, mRecentsAnimationState.mHomeContentInsets, mRecentsAnimationState.mMinimizedHomeBounds); }; } else { startActivity = () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mHomeIntent, assistDataReceiver, mRecentsAnimationState, null, null); } if (Looper.myLooper() != Looper.getMainLooper()) { startActivity.run(); Loading Loading @@ -353,8 +372,10 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC if (mInteractionHandler != null) { final WindowTransformSwipeHandler handler = mInteractionHandler; mInteractionHandler = null; mIsGoingToLauncher = handler.mIsGoingToRecents || handler.mIsGoingToHome; mMainThreadExecutor.execute(handler::reset); WindowTransformSwipeHandler.GestureEndTarget endTarget = handler.mGestureEndTarget; mIsGoingToLauncher = endTarget != null && endTarget.isLauncher; mCanGestureBeContinued = endTarget != null && endTarget.canBeContinued; mMainThreadExecutor.execute(mCanGestureBeContinued ? handler::cancel : handler::reset); } } Loading Loading @@ -443,26 +464,34 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC return mIsGoingToLauncher; } @Override public @Nullable RecentsAnimationState getRecentsAnimationStateToReuse() { return mCanGestureBeContinued ? mRecentsAnimationState : null; } @Override public boolean deferNextEventToMainThread() { // TODO: Consider also check if the eventQueue is using mainThread of not. return mInteractionHandler != null; } private class RecentsAnimationState implements RecentsAnimationListener { public static class RecentsAnimationState implements RecentsAnimationListener { private static final String ANIMATION_START_EVT = "RecentsAnimationState.onAnimationStart"; private final int id; private OtherActivityTouchConsumer mParent; private RecentsAnimationControllerCompat mController; private RemoteAnimationTargetSet mTargets; private Rect mHomeContentInsets; private Rect mMinimizedHomeBounds; private boolean mCancelled; public RecentsAnimationState() { id = mAnimationStates.size(); mAnimationStates.put(id, this); public RecentsAnimationState(OtherActivityTouchConsumer parent) { mParent = parent; id = mParent.mAnimationStates.size(); mParent.mAnimationStates.put(id, this); } @Override Loading @@ -475,31 +504,37 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTargets = new RemoteAnimationTargetSet(apps, MODE_CLOSING); mHomeContentInsets = homeContentInsets; mMinimizedHomeBounds = minimizedHomeBounds; mEventQueue.onCommand(id); mParent.mEventQueue.onCommand(id); RaceConditionTracker.onEvent(ANIMATION_START_EVT, EXIT); } @Override public void onAnimationCanceled() { mCancelled = true; mEventQueue.onCommand(id); mParent.mEventQueue.onCommand(id); } public void execute() { if (mInteractionHandler == null || mInteractionHandler.id != id) { WindowTransformSwipeHandler handler = mParent.mInteractionHandler; if (handler == null || handler.id != id) { if (!mCancelled && mController != null) { TraceHelper.endSection("RecentsController", "Finishing no handler"); mController.finish(false /* toHome */); } } else if (mCancelled) { TraceHelper.endSection("RecentsController", "Cancelled: " + mInteractionHandler); mInteractionHandler.onRecentsAnimationCanceled(); "Cancelled: " + handler); handler.onRecentsAnimationCanceled(); } else { TraceHelper.partitionSection("RecentsController", "Received"); mInteractionHandler.onRecentsAnimationStart(mController, mTargets, handler.onRecentsAnimationStart(mController, mTargets, mHomeContentInsets, mMinimizedHomeBounds); } } public void changeParent(OtherActivityTouchConsumer newParent) { mParent = newParent; mParent.mAnimationStates.put(id, this); } } } quickstep/src/com/android/quickstep/TouchConsumer.java +10 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,9 @@ import android.view.Choreographer; import android.view.MotionEvent; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.android.quickstep.OtherActivityTouchConsumer.RecentsAnimationState; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -73,5 +76,12 @@ public interface TouchConsumer extends Consumer<MotionEvent> { return false; } /** * When continuing a gesture, return the current non-null animation state that hasn't finished. */ default @Nullable RecentsAnimationState getRecentsAnimationStateToReuse() { return null; } default void onShowOverviewFromAltTab() {} } quickstep/src/com/android/quickstep/TouchInteractionService.java +10 −6 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.OtherActivityTouchConsumer.RecentsAnimationState; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; Loading Loading @@ -237,16 +238,18 @@ public class TouchInteractionService extends Service { if (oldConsumer.deferNextEventToMainThread()) { mEventQueue = new MotionEventQueue(mMainThreadChoreographer, new DeferredTouchConsumer((v) -> getCurrentTouchConsumer(downHitTarget, oldConsumer.forceToLauncherConsumer(), v))); oldConsumer.forceToLauncherConsumer(), oldConsumer.getRecentsAnimationStateToReuse(), v))); mEventQueue.deferInit(); } else { mEventQueue = new MotionEventQueue( mMainThreadChoreographer, getCurrentTouchConsumer(downHitTarget, false, null)); mEventQueue = new MotionEventQueue(mMainThreadChoreographer, getCurrentTouchConsumer(downHitTarget, false, null, null)); } } private TouchConsumer getCurrentTouchConsumer( @HitTarget int downHitTarget, boolean forceToLauncher, VelocityTracker tracker) { private TouchConsumer getCurrentTouchConsumer(@HitTarget int downHitTarget, boolean forceToLauncher, RecentsAnimationState recentsAnimationStateToReuse, VelocityTracker tracker) { RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0); if (runningTaskInfo == null && !forceToLauncher) { Loading @@ -269,7 +272,8 @@ public class TouchInteractionService extends Service { mOverviewComponentObserver.getOverviewIntent(), mOverviewComponentObserver.getActivityControlHelper(), mMainThreadExecutor, mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog); mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog, recentsAnimationStateToReuse); } } Loading quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +58 −31 Original line number Diff line number Diff line Loading @@ -197,19 +197,21 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { }; enum GestureEndTarget { HOME(1, STATE_SCALED_CONTROLLER_HOME, true, ContainerType.WORKSPACE), HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE), RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT | STATE_SCREENSHOT_VIEW_SHOWN, true, ContainerType.TASKSWITCHER), | STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER), NEW_TASK(0, STATE_START_NEW_TASK, false, ContainerType.APP), NEW_TASK(0, STATE_START_NEW_TASK, false, true, ContainerType.APP), LAST_TASK(0, STATE_SCALED_CONTROLLER_LAST_TASK, false, ContainerType.APP); LAST_TASK(0, STATE_SCALED_CONTROLLER_LAST_TASK, false, false, ContainerType.APP); GestureEndTarget(float endShift, int endState, boolean isLauncher, int containerType) { GestureEndTarget(float endShift, int endState, boolean isLauncher, boolean canBeContinued, int containerType) { this.endShift = endShift; this.endState = endState; this.isLauncher = isLauncher; this.canBeContinued = canBeContinued; this.containerType = containerType; } Loading @@ -217,6 +219,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { public final float endShift; public final int endState; public final boolean isLauncher; public final boolean canBeContinued; public final int containerType; } Loading @@ -235,8 +238,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private final ClipAnimationHelper.TransformParams mTransformParams; protected Runnable mGestureEndCallback; protected boolean mIsGoingToRecents; protected boolean mIsGoingToHome; protected GestureEndTarget mGestureEndTarget; private boolean mIsShelfPeeking; private DeviceProfile mDp; private int mTransitionDragLength; Loading @@ -247,6 +249,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { // visible. private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift); private boolean mDispatchedDownEvent; private boolean mContinuingLastGesture; // To avoid UI jump when gesture is started, we offset the animation by the threshold. private float mShiftAtGestureStart = 0; Loading Loading @@ -302,7 +305,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private Bundle mAssistData; WindowTransformSwipeHandler(int id, RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, ActivityControlHelper<T> controller, long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture, InputConsumerController inputConsumer, TouchInteractionLog touchInteractionLog) { this.id = id; mContext = context; Loading @@ -312,6 +315,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { mActivityControlHelper = controller; mActivityInitListener = mActivityControlHelper .createActivityInitListener(this::onActivityInit); mContinuingLastGesture = continuingLastGesture; mTouchInteractionLog = touchInteractionLog; mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer, this::createNewTouchProxyHandler); Loading Loading @@ -480,7 +484,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { }); mRecentsView.setEnableFreeScroll(false); mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { if (!mBgLongSwipeMode && !mIsGoingToHome) { if (!mBgLongSwipeMode && mGestureEndTarget != HOME) { updateFinalShift(); } }); Loading Loading @@ -538,6 +542,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } private void setupRecentsViewUi() { if (mContinuingLastGesture) { return; } mRecentsView.setEnableDrawingLiveTile(false); mRecentsView.showTask(mRunningTaskId); mRecentsView.setRunningTaskHidden(true); Loading Loading @@ -767,16 +774,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } } // Update insets of the adjacent tasks, as we might switch to them. // Update insets of the non-running tasks, as we might switch to them. int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex(); if (mInteractionType == INTERACTION_NORMAL && runningTaskIndex >= 0) { TaskView nextTaskView = mRecentsView.getTaskViewAt(runningTaskIndex + 1); TaskView prevTaskView = mRecentsView.getTaskViewAt(runningTaskIndex - 1); if (nextTaskView != null) { nextTaskView.setFullscreenProgress(1 - mCurrentShift.value); for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) { if (i != runningTaskIndex) { mRecentsView.getTaskViewAt(i).setFullscreenProgress(1 - mCurrentShift.value); } if (prevTaskView != null) { prevTaskView.setFullscreenProgress(1 - mCurrentShift.value); } } Loading @@ -788,7 +792,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } private void updateLauncherTransitionProgress() { if (mIsGoingToHome) { if (mGestureEndTarget == HOME) { return; } float progress = mCurrentShift.value; Loading Loading @@ -909,10 +913,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { float endShift; final float startShift; Interpolator interpolator = DEACCEL; final int nextPage = mRecentsView != null ? mRecentsView.getNextPage() : -1; final int runningTaskIndex = mRecentsView != null ? mRecentsView.getRunningTaskIndex() : -1; boolean goingToNewTask = mRecentsView != null && nextPage != runningTaskIndex && mRecentsView.getTaskViewAt(nextPage) != null; int nextPage = 0; int taskToLaunch = 0; final boolean goingToNewTask; if (mRecentsView != null) { nextPage = mRecentsView.getNextPage(); final int lastTaskIndex = mRecentsView.getTaskViewCount() - 1; final int runningTaskIndex = mRecentsView.getRunningTaskIndex(); taskToLaunch = nextPage <= lastTaskIndex ? nextPage : lastTaskIndex; goingToNewTask = mRecentsView != null && taskToLaunch != runningTaskIndex; } else { goingToNewTask = false; } final boolean reachedOverviewThreshold = currentShift >= MIN_PROGRESS_FOR_OVERVIEW; if (!isFling) { if (SWIPE_HOME.get()) { Loading Loading @@ -973,6 +985,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } } if (mRecentsView != null && !endTarget.isLauncher && taskToLaunch != nextPage) { // Scrolled to Clear all button, snap back to last task and launch it. mRecentsView.snapToPage(taskToLaunch, Math.toIntExact(duration), interpolator); } if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); Loading @@ -989,11 +1006,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { if (mRecentsView != null) { duration = Math.max(duration, mRecentsView.getScroller().getDuration()); } } else if (endTarget == LAST_TASK) { if (mRecentsView != null && nextPage != runningTaskIndex) { // Scrolled to Clear all button, snap back to current task and resume it. mRecentsView.snapToPage(runningTaskIndex, Math.toIntExact(duration)); } } animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); } Loading Loading @@ -1028,11 +1040,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private void animateToProgressInternal(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, float velocityPxPerMs) { mIsGoingToHome = target == HOME; mIsGoingToRecents = target == RECENTS; mGestureEndTarget = target; ActivityControlHelper.HomeAnimationFactory homeAnimFactory; Animator windowAnim; if (mIsGoingToHome) { if (mGestureEndTarget == HOME) { if (mActivity != null) { homeAnimFactory = mActivityControlHelper.prepareHomeUI(mActivity); } else { Loading Loading @@ -1071,7 +1082,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { long startMillis = SystemClock.uptimeMillis(); // Always play the entire launcher animation when going home, since it is separate from // the animation that has been controlled thus far. final float finalStart = mIsGoingToHome ? 0 : start; final float finalStart = mGestureEndTarget == HOME ? 0 : start; executeOnUiThread(() -> { // Animate the launcher components at the same time as the window, always on UI thread. // Adjust start progress and duration in case we are on a different thread. Loading Loading @@ -1144,6 +1155,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { .setSyncTransactionApplier(syncTransactionApplier); mClipAnimationHelper.applyTransform(targetSet, mTransformParams); }); anim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { if (mRecentsView != null) { mRecentsView.post(mRecentsView::resetTaskVisuals); } } }); return anim; } Loading Loading @@ -1187,6 +1206,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } } public void cancel() { mCurrentShift.cancelAnimation(); if (mLauncherTransitionController != null && mLauncherTransitionController .getAnimationPlayer().isStarted()) { mLauncherTransitionController.getAnimationPlayer().cancel(); } } private void invalidateHandler() { mCurrentShift.finishAnimation(); Loading Loading
quickstep/src/com/android/quickstep/DeferredTouchConsumer.java +5 −0 Original line number Diff line number Diff line Loading @@ -95,6 +95,11 @@ public class DeferredTouchConsumer implements TouchConsumer { return mTarget.forceToLauncherConsumer(); } @Override public OtherActivityTouchConsumer.RecentsAnimationState getRecentsAnimationStateToReuse() { return mTarget.getRecentsAnimationStateToReuse(); } @Override public boolean deferNextEventToMainThread() { // If our target is still null, defer the next target as well Loading
quickstep/src/com/android/quickstep/OtherActivityTouchConsumer.java +55 −20 Original line number Diff line number Diff line Loading @@ -21,7 +21,6 @@ import static android.view.MotionEvent.ACTION_MOVE; import static android.view.MotionEvent.ACTION_POINTER_UP; import static android.view.MotionEvent.ACTION_UP; import static android.view.MotionEvent.INVALID_POINTER_ID; import static com.android.launcher3.util.RaceConditionTracker.ENTER; import static com.android.launcher3.util.RaceConditionTracker.EXIT; import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS; Loading Loading @@ -102,18 +101,21 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC private WindowTransformSwipeHandler mInteractionHandler; private int mDisplayRotation; private Rect mStableInsets = new Rect(); private boolean mCanGestureBeContinued; private VelocityTracker mVelocityTracker; private MotionPauseDetector mMotionPauseDetector; private MotionEventQueue mEventQueue; private boolean mIsGoingToLauncher; private RecentsAnimationState mRecentsAnimationState; public OtherActivityTouchConsumer(Context base, RunningTaskInfo runningTaskInfo, RecentsModel recentsModel, Intent homeIntent, ActivityControlHelper activityControl, MainThreadExecutor mainThreadExecutor, Choreographer backgroundThreadChoreographer, @HitTarget int downHitTarget, OverviewCallbacks overviewCallbacks, TaskOverlayFactory taskOverlayFactory, InputConsumerController inputConsumer, VelocityTracker velocityTracker, TouchInteractionLog touchInteractionLog) { VelocityTracker velocityTracker, TouchInteractionLog touchInteractionLog, @Nullable RecentsAnimationState recentsAnimationStateToReuse) { super(base); mRunningTask = runningTaskInfo; Loading @@ -130,6 +132,7 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTouchInteractionLog = touchInteractionLog; mTouchInteractionLog.setTouchConsumer(this); mInputConsumer = inputConsumer; mRecentsAnimationState = recentsAnimationStateToReuse; } @Override Loading @@ -150,7 +153,8 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mActivePointerId = ev.getPointerId(0); mDownPos.set(ev.getX(), ev.getY()); mLastPos.set(mDownPos); mPassedInitialSlop = false; // If mRecentsAnimationState != null, we are continuing the previous gesture. mPassedInitialSlop = mRecentsAnimationState != null; mQuickStepDragSlop = NavigationBarCompat.getQuickStepDragSlopPx(); // Start the window animation on down to give more time for launcher to draw if the Loading Loading @@ -256,10 +260,15 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTouchInteractionLog.startRecentsAnimation(); // Create the shared handler RecentsAnimationState animationState = new RecentsAnimationState(); boolean reuseOldAnimState = mRecentsAnimationState != null; if (reuseOldAnimState) { mRecentsAnimationState.changeParent(this); } else { mRecentsAnimationState = new RecentsAnimationState(this); } final WindowTransformSwipeHandler handler = new WindowTransformSwipeHandler( animationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper, mInputConsumer, mTouchInteractionLog); mRecentsAnimationState.id, mRunningTask, this, touchTimeMs, mActivityControlHelper, reuseOldAnimState, mInputConsumer, mTouchInteractionLog); // Preload the plan mRecentsModel.getTasks(null); Loading Loading @@ -291,8 +300,18 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC } }; Runnable startActivity = () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mHomeIntent, assistDataReceiver, animationState, null, null); Runnable startActivity; if (reuseOldAnimState) { startActivity = () -> { handler.onRecentsAnimationStart(mRecentsAnimationState.mController, mRecentsAnimationState.mTargets, mRecentsAnimationState.mHomeContentInsets, mRecentsAnimationState.mMinimizedHomeBounds); }; } else { startActivity = () -> ActivityManagerWrapper.getInstance().startRecentsActivity( mHomeIntent, assistDataReceiver, mRecentsAnimationState, null, null); } if (Looper.myLooper() != Looper.getMainLooper()) { startActivity.run(); Loading Loading @@ -353,8 +372,10 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC if (mInteractionHandler != null) { final WindowTransformSwipeHandler handler = mInteractionHandler; mInteractionHandler = null; mIsGoingToLauncher = handler.mIsGoingToRecents || handler.mIsGoingToHome; mMainThreadExecutor.execute(handler::reset); WindowTransformSwipeHandler.GestureEndTarget endTarget = handler.mGestureEndTarget; mIsGoingToLauncher = endTarget != null && endTarget.isLauncher; mCanGestureBeContinued = endTarget != null && endTarget.canBeContinued; mMainThreadExecutor.execute(mCanGestureBeContinued ? handler::cancel : handler::reset); } } Loading Loading @@ -443,26 +464,34 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC return mIsGoingToLauncher; } @Override public @Nullable RecentsAnimationState getRecentsAnimationStateToReuse() { return mCanGestureBeContinued ? mRecentsAnimationState : null; } @Override public boolean deferNextEventToMainThread() { // TODO: Consider also check if the eventQueue is using mainThread of not. return mInteractionHandler != null; } private class RecentsAnimationState implements RecentsAnimationListener { public static class RecentsAnimationState implements RecentsAnimationListener { private static final String ANIMATION_START_EVT = "RecentsAnimationState.onAnimationStart"; private final int id; private OtherActivityTouchConsumer mParent; private RecentsAnimationControllerCompat mController; private RemoteAnimationTargetSet mTargets; private Rect mHomeContentInsets; private Rect mMinimizedHomeBounds; private boolean mCancelled; public RecentsAnimationState() { id = mAnimationStates.size(); mAnimationStates.put(id, this); public RecentsAnimationState(OtherActivityTouchConsumer parent) { mParent = parent; id = mParent.mAnimationStates.size(); mParent.mAnimationStates.put(id, this); } @Override Loading @@ -475,31 +504,37 @@ public class OtherActivityTouchConsumer extends ContextWrapper implements TouchC mTargets = new RemoteAnimationTargetSet(apps, MODE_CLOSING); mHomeContentInsets = homeContentInsets; mMinimizedHomeBounds = minimizedHomeBounds; mEventQueue.onCommand(id); mParent.mEventQueue.onCommand(id); RaceConditionTracker.onEvent(ANIMATION_START_EVT, EXIT); } @Override public void onAnimationCanceled() { mCancelled = true; mEventQueue.onCommand(id); mParent.mEventQueue.onCommand(id); } public void execute() { if (mInteractionHandler == null || mInteractionHandler.id != id) { WindowTransformSwipeHandler handler = mParent.mInteractionHandler; if (handler == null || handler.id != id) { if (!mCancelled && mController != null) { TraceHelper.endSection("RecentsController", "Finishing no handler"); mController.finish(false /* toHome */); } } else if (mCancelled) { TraceHelper.endSection("RecentsController", "Cancelled: " + mInteractionHandler); mInteractionHandler.onRecentsAnimationCanceled(); "Cancelled: " + handler); handler.onRecentsAnimationCanceled(); } else { TraceHelper.partitionSection("RecentsController", "Received"); mInteractionHandler.onRecentsAnimationStart(mController, mTargets, handler.onRecentsAnimationStart(mController, mTargets, mHomeContentInsets, mMinimizedHomeBounds); } } public void changeParent(OtherActivityTouchConsumer newParent) { mParent = newParent; mParent.mAnimationStates.put(id, this); } } }
quickstep/src/com/android/quickstep/TouchConsumer.java +10 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,9 @@ import android.view.Choreographer; import android.view.MotionEvent; import androidx.annotation.IntDef; import androidx.annotation.Nullable; import com.android.quickstep.OtherActivityTouchConsumer.RecentsAnimationState; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; Loading Loading @@ -73,5 +76,12 @@ public interface TouchConsumer extends Consumer<MotionEvent> { return false; } /** * When continuing a gesture, return the current non-null animation state that hasn't finished. */ default @Nullable RecentsAnimationState getRecentsAnimationStateToReuse() { return null; } default void onShowOverviewFromAltTab() {} }
quickstep/src/com/android/quickstep/TouchInteractionService.java +10 −6 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import com.android.launcher3.BaseDraggingActivity; import com.android.launcher3.MainThreadExecutor; import com.android.launcher3.util.TraceHelper; import com.android.launcher3.views.BaseDragLayer; import com.android.quickstep.OtherActivityTouchConsumer.RecentsAnimationState; import com.android.quickstep.views.RecentsView; import com.android.systemui.shared.recents.IOverviewProxy; import com.android.systemui.shared.recents.ISystemUiProxy; Loading Loading @@ -237,16 +238,18 @@ public class TouchInteractionService extends Service { if (oldConsumer.deferNextEventToMainThread()) { mEventQueue = new MotionEventQueue(mMainThreadChoreographer, new DeferredTouchConsumer((v) -> getCurrentTouchConsumer(downHitTarget, oldConsumer.forceToLauncherConsumer(), v))); oldConsumer.forceToLauncherConsumer(), oldConsumer.getRecentsAnimationStateToReuse(), v))); mEventQueue.deferInit(); } else { mEventQueue = new MotionEventQueue( mMainThreadChoreographer, getCurrentTouchConsumer(downHitTarget, false, null)); mEventQueue = new MotionEventQueue(mMainThreadChoreographer, getCurrentTouchConsumer(downHitTarget, false, null, null)); } } private TouchConsumer getCurrentTouchConsumer( @HitTarget int downHitTarget, boolean forceToLauncher, VelocityTracker tracker) { private TouchConsumer getCurrentTouchConsumer(@HitTarget int downHitTarget, boolean forceToLauncher, RecentsAnimationState recentsAnimationStateToReuse, VelocityTracker tracker) { RunningTaskInfo runningTaskInfo = mAM.getRunningTask(0); if (runningTaskInfo == null && !forceToLauncher) { Loading @@ -269,7 +272,8 @@ public class TouchInteractionService extends Service { mOverviewComponentObserver.getOverviewIntent(), mOverviewComponentObserver.getActivityControlHelper(), mMainThreadExecutor, mBackgroundThreadChoreographer, downHitTarget, mOverviewCallbacks, mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog); mTaskOverlayFactory, mInputConsumer, tracker, mTouchInteractionLog, recentsAnimationStateToReuse); } } Loading
quickstep/src/com/android/quickstep/WindowTransformSwipeHandler.java +58 −31 Original line number Diff line number Diff line Loading @@ -197,19 +197,21 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { }; enum GestureEndTarget { HOME(1, STATE_SCALED_CONTROLLER_HOME, true, ContainerType.WORKSPACE), HOME(1, STATE_SCALED_CONTROLLER_HOME, true, false, ContainerType.WORKSPACE), RECENTS(1, STATE_SCALED_CONTROLLER_RECENTS | STATE_CAPTURE_SCREENSHOT | STATE_SCREENSHOT_VIEW_SHOWN, true, ContainerType.TASKSWITCHER), | STATE_SCREENSHOT_VIEW_SHOWN, true, false, ContainerType.TASKSWITCHER), NEW_TASK(0, STATE_START_NEW_TASK, false, ContainerType.APP), NEW_TASK(0, STATE_START_NEW_TASK, false, true, ContainerType.APP), LAST_TASK(0, STATE_SCALED_CONTROLLER_LAST_TASK, false, ContainerType.APP); LAST_TASK(0, STATE_SCALED_CONTROLLER_LAST_TASK, false, false, ContainerType.APP); GestureEndTarget(float endShift, int endState, boolean isLauncher, int containerType) { GestureEndTarget(float endShift, int endState, boolean isLauncher, boolean canBeContinued, int containerType) { this.endShift = endShift; this.endState = endState; this.isLauncher = isLauncher; this.canBeContinued = canBeContinued; this.containerType = containerType; } Loading @@ -217,6 +219,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { public final float endShift; public final int endState; public final boolean isLauncher; public final boolean canBeContinued; public final int containerType; } Loading @@ -235,8 +238,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private final ClipAnimationHelper.TransformParams mTransformParams; protected Runnable mGestureEndCallback; protected boolean mIsGoingToRecents; protected boolean mIsGoingToHome; protected GestureEndTarget mGestureEndTarget; private boolean mIsShelfPeeking; private DeviceProfile mDp; private int mTransitionDragLength; Loading @@ -247,6 +249,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { // visible. private final AnimatedFloat mCurrentShift = new AnimatedFloat(this::updateFinalShift); private boolean mDispatchedDownEvent; private boolean mContinuingLastGesture; // To avoid UI jump when gesture is started, we offset the animation by the threshold. private float mShiftAtGestureStart = 0; Loading Loading @@ -302,7 +305,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private Bundle mAssistData; WindowTransformSwipeHandler(int id, RunningTaskInfo runningTaskInfo, Context context, long touchTimeMs, ActivityControlHelper<T> controller, long touchTimeMs, ActivityControlHelper<T> controller, boolean continuingLastGesture, InputConsumerController inputConsumer, TouchInteractionLog touchInteractionLog) { this.id = id; mContext = context; Loading @@ -312,6 +315,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { mActivityControlHelper = controller; mActivityInitListener = mActivityControlHelper .createActivityInitListener(this::onActivityInit); mContinuingLastGesture = continuingLastGesture; mTouchInteractionLog = touchInteractionLog; mRecentsAnimationWrapper = new RecentsAnimationWrapper(inputConsumer, this::createNewTouchProxyHandler); Loading Loading @@ -480,7 +484,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { }); mRecentsView.setEnableFreeScroll(false); mRecentsView.setOnScrollChangeListener((v, scrollX, scrollY, oldScrollX, oldScrollY) -> { if (!mBgLongSwipeMode && !mIsGoingToHome) { if (!mBgLongSwipeMode && mGestureEndTarget != HOME) { updateFinalShift(); } }); Loading Loading @@ -538,6 +542,9 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } private void setupRecentsViewUi() { if (mContinuingLastGesture) { return; } mRecentsView.setEnableDrawingLiveTile(false); mRecentsView.showTask(mRunningTaskId); mRecentsView.setRunningTaskHidden(true); Loading Loading @@ -767,16 +774,13 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { HapticFeedbackConstants.FLAG_IGNORE_VIEW_SETTING); } } // Update insets of the adjacent tasks, as we might switch to them. // Update insets of the non-running tasks, as we might switch to them. int runningTaskIndex = mRecentsView == null ? -1 : mRecentsView.getRunningTaskIndex(); if (mInteractionType == INTERACTION_NORMAL && runningTaskIndex >= 0) { TaskView nextTaskView = mRecentsView.getTaskViewAt(runningTaskIndex + 1); TaskView prevTaskView = mRecentsView.getTaskViewAt(runningTaskIndex - 1); if (nextTaskView != null) { nextTaskView.setFullscreenProgress(1 - mCurrentShift.value); for (int i = 0; i < mRecentsView.getTaskViewCount(); i++) { if (i != runningTaskIndex) { mRecentsView.getTaskViewAt(i).setFullscreenProgress(1 - mCurrentShift.value); } if (prevTaskView != null) { prevTaskView.setFullscreenProgress(1 - mCurrentShift.value); } } Loading @@ -788,7 +792,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } private void updateLauncherTransitionProgress() { if (mIsGoingToHome) { if (mGestureEndTarget == HOME) { return; } float progress = mCurrentShift.value; Loading Loading @@ -909,10 +913,18 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { float endShift; final float startShift; Interpolator interpolator = DEACCEL; final int nextPage = mRecentsView != null ? mRecentsView.getNextPage() : -1; final int runningTaskIndex = mRecentsView != null ? mRecentsView.getRunningTaskIndex() : -1; boolean goingToNewTask = mRecentsView != null && nextPage != runningTaskIndex && mRecentsView.getTaskViewAt(nextPage) != null; int nextPage = 0; int taskToLaunch = 0; final boolean goingToNewTask; if (mRecentsView != null) { nextPage = mRecentsView.getNextPage(); final int lastTaskIndex = mRecentsView.getTaskViewCount() - 1; final int runningTaskIndex = mRecentsView.getRunningTaskIndex(); taskToLaunch = nextPage <= lastTaskIndex ? nextPage : lastTaskIndex; goingToNewTask = mRecentsView != null && taskToLaunch != runningTaskIndex; } else { goingToNewTask = false; } final boolean reachedOverviewThreshold = currentShift >= MIN_PROGRESS_FOR_OVERVIEW; if (!isFling) { if (SWIPE_HOME.get()) { Loading Loading @@ -973,6 +985,11 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } } if (mRecentsView != null && !endTarget.isLauncher && taskToLaunch != nextPage) { // Scrolled to Clear all button, snap back to last task and launch it. mRecentsView.snapToPage(taskToLaunch, Math.toIntExact(duration), interpolator); } if (endTarget == HOME) { setShelfState(ShelfAnimState.CANCEL, LINEAR, 0); duration = Math.max(MIN_OVERSHOOT_DURATION, duration); Loading @@ -989,11 +1006,6 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { if (mRecentsView != null) { duration = Math.max(duration, mRecentsView.getScroller().getDuration()); } } else if (endTarget == LAST_TASK) { if (mRecentsView != null && nextPage != runningTaskIndex) { // Scrolled to Clear all button, snap back to current task and resume it. mRecentsView.snapToPage(runningTaskIndex, Math.toIntExact(duration)); } } animateToProgress(startShift, endShift, duration, interpolator, endTarget, velocityPxPerMs); } Loading Loading @@ -1028,11 +1040,10 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { private void animateToProgressInternal(float start, float end, long duration, Interpolator interpolator, GestureEndTarget target, float velocityPxPerMs) { mIsGoingToHome = target == HOME; mIsGoingToRecents = target == RECENTS; mGestureEndTarget = target; ActivityControlHelper.HomeAnimationFactory homeAnimFactory; Animator windowAnim; if (mIsGoingToHome) { if (mGestureEndTarget == HOME) { if (mActivity != null) { homeAnimFactory = mActivityControlHelper.prepareHomeUI(mActivity); } else { Loading Loading @@ -1071,7 +1082,7 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { long startMillis = SystemClock.uptimeMillis(); // Always play the entire launcher animation when going home, since it is separate from // the animation that has been controlled thus far. final float finalStart = mIsGoingToHome ? 0 : start; final float finalStart = mGestureEndTarget == HOME ? 0 : start; executeOnUiThread(() -> { // Animate the launcher components at the same time as the window, always on UI thread. // Adjust start progress and duration in case we are on a different thread. Loading Loading @@ -1144,6 +1155,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { .setSyncTransactionApplier(syncTransactionApplier); mClipAnimationHelper.applyTransform(targetSet, mTransformParams); }); anim.addListener(new AnimationSuccessListener() { @Override public void onAnimationSuccess(Animator animator) { if (mRecentsView != null) { mRecentsView.post(mRecentsView::resetTaskVisuals); } } }); return anim; } Loading Loading @@ -1187,6 +1206,14 @@ public class WindowTransformSwipeHandler<T extends BaseDraggingActivity> { } } public void cancel() { mCurrentShift.cancelAnimation(); if (mLauncherTransitionController != null && mLauncherTransitionController .getAnimationPlayer().isStarted()) { mLauncherTransitionController.getAnimationPlayer().cancel(); } } private void invalidateHandler() { mCurrentShift.finishAnimation(); Loading