Loading quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +55 −29 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.views.DesktopTaskView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading @@ -150,6 +151,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Objects; import java.util.Optional; import java.util.OptionalInt; import java.util.function.Consumer; /** Loading Loading @@ -656,11 +658,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, protected void notifyGestureAnimationStartToRecents() { Task[] runningTasks; TopTaskTracker.CachedTaskInfo cachedTaskInfo = mGestureState.getRunningTask(); if (mIsSwipeForSplit) { int[] splitTaskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds(); runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(splitTaskIds); runningTasks = cachedTaskInfo.getPlaceholderTasks(splitTaskIds); } else { runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(); runningTasks = cachedTaskInfo.getPlaceholderTasks(); } // Safeguard against any null tasks being sent to recents view, happens when quickswitching Loading Loading @@ -733,8 +736,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, || mRecentsView == null) { return; } // looking at single target is fine here since either app of a split pair would // have their "isInRecents" field set? (that's what this is used for below) RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId()) ? mRecentsAnimationTargets .findTask(mGestureState.getTopRunningTaskId()) : null; final boolean recentsAttachedToAppWindow; if (mIsInAllAppsRegion) { Loading Loading @@ -1190,7 +1196,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, return false; } boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTarget).anyMatch( targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId()); mGestureState.mLastStartedTaskIdPredicate); if (mStateCallback.hasStates(STATE_START_NEW_TASK) && hasStartedTaskBefore) { reset(); return true; Loading Loading @@ -1456,9 +1462,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, @Override public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { if (task.taskId == mGestureState.getRunningTaskId() boolean taskRunningAndNotHome = Arrays.stream(mGestureState .getRunningTaskIds(true /*getMultipleTasks*/)) .anyMatch(taskId -> task.taskId == taskId && task.configuration.windowConfiguration.getActivityType() != ACTIVITY_TYPE_HOME) { != ACTIVITY_TYPE_HOME); if (taskRunningAndNotHome) { // Since this is an edge case, just cancel and relaunch with default activity // options (since we don't know if there's an associated app icon to launch from) endRunningWindowAnim(true /* cancel */); Loading Loading @@ -1500,8 +1509,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, if (mGestureState.getEndTarget() == HOME) { getOrientationHandler().adjustFloatingIconStartVelocity(velocityPxPerMs); // Take first task ID, if there are multiple we don't have any special home // animation so doesn't matter for splitscreen.. though the "allowEnterPip" might change // depending on which task it is.. final RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId()) ? mRecentsAnimationTargets .findTask(mGestureState.getTopRunningTaskId()) : null; final ArrayList<IBinder> cookies = runningTaskTarget != null ? runningTaskTarget.taskInfo.launchCookies Loading Loading @@ -1530,7 +1543,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // grab a screenshot before the PipContentOverlay gets parented on top of the task UI_HELPER_EXECUTOR.execute(() -> { final int taskId = mGestureState.getRunningTaskId(); // Directly use top task, split to pip handled on shell side final int taskId = mGestureState.getTopRunningTaskId(); mTaskSnapshotCache.put(taskId, mRecentsAnimationController.screenshotTask(taskId)); }); Loading Loading @@ -1994,13 +2008,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // If there are no targets, then we don't need to capture anything mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); } else { final int runningTaskId = mGestureState.getRunningTaskId(); boolean finishTransitionPosted = false; // If we already have cached screenshot(s) from running tasks, skip update boolean shouldUpdate = false; int[] runningTaskIds = mIsSwipeForSplit ? TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds() : new int[]{runningTaskId}; int[] runningTaskIds = mGestureState.getRunningTaskIds(mIsSwipeForSplit); for (int id : runningTaskIds) { if (!mTaskSnapshotCache.containsKey(id)) { shouldUpdate = true; Loading Loading @@ -2205,16 +2216,27 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, if (!mCanceled) { TaskView nextTask = mRecentsView == null ? null : mRecentsView.getNextPageTaskView(); if (nextTask != null) { Task.TaskKey nextTaskKey = nextTask.getTask().key; int taskId = nextTaskKey.id; mGestureState.updateLastStartedTaskId(taskId); boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds() .contains(taskId); int[] taskIds = nextTask.getTaskIds(); StringBuilder nextTaskLog = new StringBuilder(); for (TaskIdAttributeContainer c : nextTask.getTaskIdAttributeContainers()) { if (c == null) { continue; } nextTaskLog .append("[id: ") .append(c.getTask().key.id) .append(", pkg: ") .append(c.getTask().key.getPackageName()) .append("] | "); } mGestureState.updateLastStartedTaskIds(taskIds); boolean hasTaskPreviouslyAppeared = Arrays.stream(taskIds).anyMatch( taskId -> mGestureState.getPreviouslyAppearedTaskIds() .contains(taskId)); if (!hasTaskPreviouslyAppeared) { ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED); } ActiveGestureLog.INSTANCE.addLog("Launching task: id=" + taskId + " pkg=" + nextTaskKey.getPackageName()); ActiveGestureLog.INSTANCE.addLog("Launching task: " + nextTaskLog); nextTask.launchTask(success -> { resultCallback.accept(success); if (success) { Loading Loading @@ -2284,7 +2306,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) { if (mRecentsAnimationController != null) { boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTargets).anyMatch( targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId()); mGestureState.mLastStartedTaskIdPredicate); if (!mStateCallback.hasStates(STATE_GESTURE_COMPLETED) && !hasStartedTaskBefore) { // This is a special case, if a task is started mid-gesture that wasn't a part of a // previous quickswitch task launch, then cancel the animation back to the app Loading @@ -2297,8 +2319,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } else if (handleTaskAppeared(appearedTaskTargets)) { Optional<RemoteAnimationTarget> taskTargetOptional = Arrays.stream(appearedTaskTargets) .filter(targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId()) .filter(mGestureState.mLastStartedTaskIdPredicate) .findFirst(); if (!taskTargetOptional.isPresent()) { ActiveGestureLog.INSTANCE.addLog("No appeared task matching started task id"); Loading Loading @@ -2367,10 +2388,15 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * resume if we finish the controller. */ protected int getLastAppearedTaskIndex() { return mRecentsView == null ? -1 : mGestureState.getLastAppearedTaskId() != -1 ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId()) if (mRecentsView == null) { return -1; } OptionalInt firstValidTaskId = Arrays.stream(mGestureState.getLastAppearedTaskIds()) .filter(i -> i != -1) .findFirst(); return firstValidTaskId.isPresent() ? mRecentsView.getTaskIndexForId(firstValidTaskId.getAsInt()) : mRecentsView.getRunningTaskIndex(); } Loading @@ -2379,7 +2405,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * but before that task appeared. */ protected boolean hasStartedNewTask() { return mGestureState.getLastStartedTaskId() != -1; return mGestureState.getLastStartedTaskIds()[0] != -1; } /** Loading quickstep/src/com/android/quickstep/GestureState.java +59 −17 Original line number Diff line number Diff line Loading @@ -15,8 +15,9 @@ */ package com.android.quickstep; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe; import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe; import static com.android.launcher3.MotionEventsUtils.isTrackpadThreeFingerSwipe; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; Loading Loading @@ -44,10 +45,12 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Predicate; /** * Manages the state for an active system gesture, listens for events from the system and Launcher, Loading @@ -56,6 +59,18 @@ import java.util.Set; @TargetApi(Build.VERSION_CODES.R) public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationListener { final Predicate<RemoteAnimationTarget> mLastStartedTaskIdPredicate = new Predicate<>() { @Override public boolean test(RemoteAnimationTarget targetCompat) { for (int taskId : mLastStartedTaskId) { if (targetCompat.taskId == taskId) { return true; } } return false; } }; /** * Defines the end targets of a gesture and the associated state. */ Loading Loading @@ -161,9 +176,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE; private CachedTaskInfo mRunningTask; private GestureEndTarget mEndTarget; private RemoteAnimationTarget mLastAppearedTaskTarget; private RemoteAnimationTarget[] mLastAppearedTaskTargets; private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>(); private int mLastStartedTaskId = -1; private int[] mLastStartedTaskId = new int[]{INVALID_TASK_ID, INVALID_TASK_ID}; private RecentsAnimationController mRecentsAnimationController; private HashMap<Integer, ThumbnailData> mRecentsAnimationCanceledSnapshots; Loading @@ -189,7 +204,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL mGestureId = other.mGestureId; mRunningTask = other.mRunningTask; mEndTarget = other.mEndTarget; mLastAppearedTaskTarget = other.mLastAppearedTaskTarget; mLastAppearedTaskTargets = other.mLastAppearedTaskTargets; mPreviouslyAppearedTaskIds = other.mPreviouslyAppearedTaskIds; mLastStartedTaskId = other.mLastStartedTaskId; } Loading Loading @@ -293,10 +308,29 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL } /** * @return the running task id for this gesture. * @param getMultipleTasks Whether multiple tasks or not are to be returned (for split) * @return the running task ids for this gesture. */ public int[] getRunningTaskIds(boolean getMultipleTasks) { if (mRunningTask == null) { return new int[]{INVALID_TASK_ID, INVALID_TASK_ID}; } else { int cachedTasksSize = mRunningTask.mAllCachedTasks.size(); int count = Math.min(cachedTasksSize, getMultipleTasks ? 2 : 1); int[] runningTaskIds = new int[count]; for (int i = 0; i < count; i++) { runningTaskIds[i] = mRunningTask.mAllCachedTasks.get(i).taskId; } return runningTaskIds; } } /** * @see #getRunningTaskIds(boolean) * @return the single top-most running taskId for this gesture */ public int getRunningTaskId() { return mRunningTask != null ? mRunningTask.getTaskId() : -1; public int getTopRunningTaskId() { return getRunningTaskIds(false /*getMultipleTasks*/)[0]; } /** Loading @@ -309,18 +343,26 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * Updates the last task that appeared during this gesture. */ public void updateLastAppearedTaskTarget(RemoteAnimationTarget lastAppearedTaskTarget) { mLastAppearedTaskTarget = lastAppearedTaskTarget; if (lastAppearedTaskTarget != null) { mPreviouslyAppearedTaskIds.add(lastAppearedTaskTarget.taskId); public void updateLastAppearedTaskTargets(RemoteAnimationTarget[] lastAppearedTaskTargets) { mLastAppearedTaskTargets = lastAppearedTaskTargets; for (RemoteAnimationTarget target : lastAppearedTaskTargets) { if (target == null) { continue; } mPreviouslyAppearedTaskIds.add(target.taskId); } } /** * @return The id of the task that appeared during this gesture. */ public int getLastAppearedTaskId() { return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1; public int[] getLastAppearedTaskIds() { if (mLastAppearedTaskTargets == null) { return new int[]{INVALID_TASK_ID, INVALID_TASK_ID}; } else { return Arrays.stream(mLastAppearedTaskTargets) .mapToInt(target -> target != null ? target.taskId : INVALID_TASK_ID).toArray(); } } public void updatePreviouslyAppearedTaskIds(Set<Integer> previouslyAppearedTaskIds) { Loading @@ -334,7 +376,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * Updates the last task that we started via startActivityFromRecents() during this gesture. */ public void updateLastStartedTaskId(int lastStartedTaskId) { public void updateLastStartedTaskIds(int[] lastStartedTaskId) { mLastStartedTaskId = lastStartedTaskId; } Loading @@ -342,7 +384,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL * @return The id of the task that was most recently started during this gesture, or -1 if * no task has been started yet (i.e. we haven't settled on a new task). */ public int getLastStartedTaskId() { public int[] getLastStartedTaskIds() { return mLastStartedTaskId; } Loading Loading @@ -478,8 +520,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL pw.println(" gestureID=" + mGestureId); pw.println(" runningTask=" + mRunningTask); pw.println(" endTarget=" + mEndTarget); pw.println(" lastAppearedTaskTargetId=" + getLastAppearedTaskId()); pw.println(" lastStartedTaskId=" + mLastStartedTaskId); pw.println(" lastAppearedTaskTargetId=" + Arrays.toString(mLastAppearedTaskTargets)); pw.println(" lastStartedTaskId=" + Arrays.toString(mLastStartedTaskId)); pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning()); } } quickstep/src/com/android/quickstep/RecentsAnimationController.java +2 −3 Original line number Diff line number Diff line Loading @@ -115,8 +115,8 @@ public class RecentsAnimationController { * {@link RecentsAnimationCallbacks#onTasksAppeared}}. */ @UiThread public void removeTaskTarget(@NonNull RemoteAnimationTarget target) { UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(target.taskId)); public void removeTaskTarget(int targetTaskId) { UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(targetTaskId)); } @UiThread Loading Loading @@ -167,7 +167,6 @@ public class RecentsAnimationController { /* event= */ "finishRecentsAnimation", /* extras= */ toRecents, /* gestureEvent= */ FINISH_RECENTS_ANIMATION); // Finish not yet requested mFinishRequested = true; mFinishTargetIsLauncher = toRecents; Loading quickstep/src/com/android/quickstep/TaskAnimationManager.java +21 −11 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn private RecentsAnimationTargets mTargets; // Temporary until we can hook into gesture state events private GestureState mLastGestureState; private RemoteAnimationTarget mLastAppearedTaskTarget; private RemoteAnimationTarget[] mLastAppearedTaskTargets; private Runnable mLiveTileCleanUpHandler; private Context mCtx; Loading Loading @@ -141,8 +141,15 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn } mController = controller; mTargets = targets; mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId()); mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); // TODO(b/236226779): We can probably get away w/ setting mLastAppearedTaskTargets // to all appeared targets directly vs just looking at running ones int[] runningTaskIds = mLastGestureState.getRunningTaskIds(targets.apps.length > 1); mLastAppearedTaskTargets = new RemoteAnimationTarget[runningTaskIds.length]; for (int i = 0; i < runningTaskIds.length; i++) { RemoteAnimationTarget task = mTargets.findTask(runningTaskIds[i]); mLastAppearedTaskTargets[i] = task; } mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets); } @Override Loading Loading @@ -196,14 +203,17 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn true /*shown*/, null /* animatorHandler */); } if (mController != null) { if (mLastAppearedTaskTarget == null || appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) { if (mLastAppearedTaskTarget != null) { mController.removeTaskTarget(mLastAppearedTaskTarget); if (mLastAppearedTaskTargets != null) { for (RemoteAnimationTarget lastTarget : mLastAppearedTaskTargets) { for (RemoteAnimationTarget appearedTarget : appearedTaskTargets) { if (appearedTarget.taskId != lastTarget.taskId) { mController.removeTaskTarget(lastTarget.taskId); } } } mLastAppearedTaskTarget = appearedTaskTarget; mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); } mLastAppearedTaskTargets = appearedTaskTargets; mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets); } } Loading Loading @@ -268,7 +278,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks.addListener(gestureState); gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED | STATE_RECENTS_ANIMATION_STARTED); gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); gestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets); return mCallbacks; } Loading Loading @@ -369,7 +379,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks = null; mTargets = null; mLastGestureState = null; mLastAppearedTaskTarget = null; mLastAppearedTaskTargets = null; } @Nullable Loading quickstep/src/com/android/quickstep/TopTaskTracker.java +1 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta @Nullable private final RunningTaskInfo mTopTask; private final List<RunningTaskInfo> mAllCachedTasks; public final List<RunningTaskInfo> mAllCachedTasks; CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) { mAllCachedTasks = allCachedTasks; Loading Loading
quickstep/src/com/android/quickstep/AbsSwipeUpHandler.java +55 −29 Original line number Diff line number Diff line Loading @@ -134,6 +134,7 @@ import com.android.quickstep.util.TaskViewSimulator; import com.android.quickstep.views.DesktopTaskView; import com.android.quickstep.views.RecentsView; import com.android.quickstep.views.TaskView; import com.android.quickstep.views.TaskView.TaskIdAttributeContainer; import com.android.systemui.shared.recents.model.Task; import com.android.systemui.shared.recents.model.ThumbnailData; import com.android.systemui.shared.system.ActivityManagerWrapper; Loading @@ -150,6 +151,7 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Objects; import java.util.Optional; import java.util.OptionalInt; import java.util.function.Consumer; /** Loading Loading @@ -656,11 +658,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, protected void notifyGestureAnimationStartToRecents() { Task[] runningTasks; TopTaskTracker.CachedTaskInfo cachedTaskInfo = mGestureState.getRunningTask(); if (mIsSwipeForSplit) { int[] splitTaskIds = TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds(); runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(splitTaskIds); runningTasks = cachedTaskInfo.getPlaceholderTasks(splitTaskIds); } else { runningTasks = mGestureState.getRunningTask().getPlaceholderTasks(); runningTasks = cachedTaskInfo.getPlaceholderTasks(); } // Safeguard against any null tasks being sent to recents view, happens when quickswitching Loading Loading @@ -733,8 +736,11 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, || mRecentsView == null) { return; } // looking at single target is fine here since either app of a split pair would // have their "isInRecents" field set? (that's what this is used for below) RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId()) ? mRecentsAnimationTargets .findTask(mGestureState.getTopRunningTaskId()) : null; final boolean recentsAttachedToAppWindow; if (mIsInAllAppsRegion) { Loading Loading @@ -1190,7 +1196,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, return false; } boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTarget).anyMatch( targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId()); mGestureState.mLastStartedTaskIdPredicate); if (mStateCallback.hasStates(STATE_START_NEW_TASK) && hasStartedTaskBefore) { reset(); return true; Loading Loading @@ -1456,9 +1462,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, @Override public void onActivityRestartAttempt(ActivityManager.RunningTaskInfo task, boolean homeTaskVisible, boolean clearedTask, boolean wasVisible) { if (task.taskId == mGestureState.getRunningTaskId() boolean taskRunningAndNotHome = Arrays.stream(mGestureState .getRunningTaskIds(true /*getMultipleTasks*/)) .anyMatch(taskId -> task.taskId == taskId && task.configuration.windowConfiguration.getActivityType() != ACTIVITY_TYPE_HOME) { != ACTIVITY_TYPE_HOME); if (taskRunningAndNotHome) { // Since this is an edge case, just cancel and relaunch with default activity // options (since we don't know if there's an associated app icon to launch from) endRunningWindowAnim(true /* cancel */); Loading Loading @@ -1500,8 +1509,12 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, if (mGestureState.getEndTarget() == HOME) { getOrientationHandler().adjustFloatingIconStartVelocity(velocityPxPerMs); // Take first task ID, if there are multiple we don't have any special home // animation so doesn't matter for splitscreen.. though the "allowEnterPip" might change // depending on which task it is.. final RemoteAnimationTarget runningTaskTarget = mRecentsAnimationTargets != null ? mRecentsAnimationTargets.findTask(mGestureState.getRunningTaskId()) ? mRecentsAnimationTargets .findTask(mGestureState.getTopRunningTaskId()) : null; final ArrayList<IBinder> cookies = runningTaskTarget != null ? runningTaskTarget.taskInfo.launchCookies Loading Loading @@ -1530,7 +1543,8 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // grab a screenshot before the PipContentOverlay gets parented on top of the task UI_HELPER_EXECUTOR.execute(() -> { final int taskId = mGestureState.getRunningTaskId(); // Directly use top task, split to pip handled on shell side final int taskId = mGestureState.getTopRunningTaskId(); mTaskSnapshotCache.put(taskId, mRecentsAnimationController.screenshotTask(taskId)); }); Loading Loading @@ -1994,13 +2008,10 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, // If there are no targets, then we don't need to capture anything mStateCallback.setStateOnUiThread(STATE_SCREENSHOT_CAPTURED); } else { final int runningTaskId = mGestureState.getRunningTaskId(); boolean finishTransitionPosted = false; // If we already have cached screenshot(s) from running tasks, skip update boolean shouldUpdate = false; int[] runningTaskIds = mIsSwipeForSplit ? TopTaskTracker.INSTANCE.get(mContext).getRunningSplitTaskIds() : new int[]{runningTaskId}; int[] runningTaskIds = mGestureState.getRunningTaskIds(mIsSwipeForSplit); for (int id : runningTaskIds) { if (!mTaskSnapshotCache.containsKey(id)) { shouldUpdate = true; Loading Loading @@ -2205,16 +2216,27 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, if (!mCanceled) { TaskView nextTask = mRecentsView == null ? null : mRecentsView.getNextPageTaskView(); if (nextTask != null) { Task.TaskKey nextTaskKey = nextTask.getTask().key; int taskId = nextTaskKey.id; mGestureState.updateLastStartedTaskId(taskId); boolean hasTaskPreviouslyAppeared = mGestureState.getPreviouslyAppearedTaskIds() .contains(taskId); int[] taskIds = nextTask.getTaskIds(); StringBuilder nextTaskLog = new StringBuilder(); for (TaskIdAttributeContainer c : nextTask.getTaskIdAttributeContainers()) { if (c == null) { continue; } nextTaskLog .append("[id: ") .append(c.getTask().key.id) .append(", pkg: ") .append(c.getTask().key.getPackageName()) .append("] | "); } mGestureState.updateLastStartedTaskIds(taskIds); boolean hasTaskPreviouslyAppeared = Arrays.stream(taskIds).anyMatch( taskId -> mGestureState.getPreviouslyAppearedTaskIds() .contains(taskId)); if (!hasTaskPreviouslyAppeared) { ActiveGestureLog.INSTANCE.trackEvent(EXPECTING_TASK_APPEARED); } ActiveGestureLog.INSTANCE.addLog("Launching task: id=" + taskId + " pkg=" + nextTaskKey.getPackageName()); ActiveGestureLog.INSTANCE.addLog("Launching task: " + nextTaskLog); nextTask.launchTask(success -> { resultCallback.accept(success); if (success) { Loading Loading @@ -2284,7 +2306,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, public void onTasksAppeared(RemoteAnimationTarget[] appearedTaskTargets) { if (mRecentsAnimationController != null) { boolean hasStartedTaskBefore = Arrays.stream(appearedTaskTargets).anyMatch( targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId()); mGestureState.mLastStartedTaskIdPredicate); if (!mStateCallback.hasStates(STATE_GESTURE_COMPLETED) && !hasStartedTaskBefore) { // This is a special case, if a task is started mid-gesture that wasn't a part of a // previous quickswitch task launch, then cancel the animation back to the app Loading @@ -2297,8 +2319,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, } else if (handleTaskAppeared(appearedTaskTargets)) { Optional<RemoteAnimationTarget> taskTargetOptional = Arrays.stream(appearedTaskTargets) .filter(targetCompat -> targetCompat.taskId == mGestureState.getLastStartedTaskId()) .filter(mGestureState.mLastStartedTaskIdPredicate) .findFirst(); if (!taskTargetOptional.isPresent()) { ActiveGestureLog.INSTANCE.addLog("No appeared task matching started task id"); Loading Loading @@ -2367,10 +2388,15 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * resume if we finish the controller. */ protected int getLastAppearedTaskIndex() { return mRecentsView == null ? -1 : mGestureState.getLastAppearedTaskId() != -1 ? mRecentsView.getTaskIndexForId(mGestureState.getLastAppearedTaskId()) if (mRecentsView == null) { return -1; } OptionalInt firstValidTaskId = Arrays.stream(mGestureState.getLastAppearedTaskIds()) .filter(i -> i != -1) .findFirst(); return firstValidTaskId.isPresent() ? mRecentsView.getTaskIndexForId(firstValidTaskId.getAsInt()) : mRecentsView.getRunningTaskIndex(); } Loading @@ -2379,7 +2405,7 @@ public abstract class AbsSwipeUpHandler<T extends StatefulActivity<S>, * but before that task appeared. */ protected boolean hasStartedNewTask() { return mGestureState.getLastStartedTaskId() != -1; return mGestureState.getLastStartedTaskIds()[0] != -1; } /** Loading
quickstep/src/com/android/quickstep/GestureState.java +59 −17 Original line number Diff line number Diff line Loading @@ -15,8 +15,9 @@ */ package com.android.quickstep; import static android.app.ActivityTaskManager.INVALID_TASK_ID; import static com.android.launcher3.MotionEventsUtils.isTrackpadFourFingerSwipe; import static com.android.launcher3.MotionEventsUtils.isTrackpadMultiFingerSwipe; import static com.android.launcher3.MotionEventsUtils.isTrackpadThreeFingerSwipe; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS; import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_BACKGROUND; Loading Loading @@ -44,10 +45,12 @@ import com.android.systemui.shared.recents.model.ThumbnailData; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.function.Predicate; /** * Manages the state for an active system gesture, listens for events from the system and Launcher, Loading @@ -56,6 +59,18 @@ import java.util.Set; @TargetApi(Build.VERSION_CODES.R) public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationListener { final Predicate<RemoteAnimationTarget> mLastStartedTaskIdPredicate = new Predicate<>() { @Override public boolean test(RemoteAnimationTarget targetCompat) { for (int taskId : mLastStartedTaskId) { if (targetCompat.taskId == taskId) { return true; } } return false; } }; /** * Defines the end targets of a gesture and the associated state. */ Loading Loading @@ -161,9 +176,9 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL private TrackpadGestureType mTrackpadGestureType = TrackpadGestureType.NONE; private CachedTaskInfo mRunningTask; private GestureEndTarget mEndTarget; private RemoteAnimationTarget mLastAppearedTaskTarget; private RemoteAnimationTarget[] mLastAppearedTaskTargets; private Set<Integer> mPreviouslyAppearedTaskIds = new HashSet<>(); private int mLastStartedTaskId = -1; private int[] mLastStartedTaskId = new int[]{INVALID_TASK_ID, INVALID_TASK_ID}; private RecentsAnimationController mRecentsAnimationController; private HashMap<Integer, ThumbnailData> mRecentsAnimationCanceledSnapshots; Loading @@ -189,7 +204,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL mGestureId = other.mGestureId; mRunningTask = other.mRunningTask; mEndTarget = other.mEndTarget; mLastAppearedTaskTarget = other.mLastAppearedTaskTarget; mLastAppearedTaskTargets = other.mLastAppearedTaskTargets; mPreviouslyAppearedTaskIds = other.mPreviouslyAppearedTaskIds; mLastStartedTaskId = other.mLastStartedTaskId; } Loading Loading @@ -293,10 +308,29 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL } /** * @return the running task id for this gesture. * @param getMultipleTasks Whether multiple tasks or not are to be returned (for split) * @return the running task ids for this gesture. */ public int[] getRunningTaskIds(boolean getMultipleTasks) { if (mRunningTask == null) { return new int[]{INVALID_TASK_ID, INVALID_TASK_ID}; } else { int cachedTasksSize = mRunningTask.mAllCachedTasks.size(); int count = Math.min(cachedTasksSize, getMultipleTasks ? 2 : 1); int[] runningTaskIds = new int[count]; for (int i = 0; i < count; i++) { runningTaskIds[i] = mRunningTask.mAllCachedTasks.get(i).taskId; } return runningTaskIds; } } /** * @see #getRunningTaskIds(boolean) * @return the single top-most running taskId for this gesture */ public int getRunningTaskId() { return mRunningTask != null ? mRunningTask.getTaskId() : -1; public int getTopRunningTaskId() { return getRunningTaskIds(false /*getMultipleTasks*/)[0]; } /** Loading @@ -309,18 +343,26 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * Updates the last task that appeared during this gesture. */ public void updateLastAppearedTaskTarget(RemoteAnimationTarget lastAppearedTaskTarget) { mLastAppearedTaskTarget = lastAppearedTaskTarget; if (lastAppearedTaskTarget != null) { mPreviouslyAppearedTaskIds.add(lastAppearedTaskTarget.taskId); public void updateLastAppearedTaskTargets(RemoteAnimationTarget[] lastAppearedTaskTargets) { mLastAppearedTaskTargets = lastAppearedTaskTargets; for (RemoteAnimationTarget target : lastAppearedTaskTargets) { if (target == null) { continue; } mPreviouslyAppearedTaskIds.add(target.taskId); } } /** * @return The id of the task that appeared during this gesture. */ public int getLastAppearedTaskId() { return mLastAppearedTaskTarget != null ? mLastAppearedTaskTarget.taskId : -1; public int[] getLastAppearedTaskIds() { if (mLastAppearedTaskTargets == null) { return new int[]{INVALID_TASK_ID, INVALID_TASK_ID}; } else { return Arrays.stream(mLastAppearedTaskTargets) .mapToInt(target -> target != null ? target.taskId : INVALID_TASK_ID).toArray(); } } public void updatePreviouslyAppearedTaskIds(Set<Integer> previouslyAppearedTaskIds) { Loading @@ -334,7 +376,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL /** * Updates the last task that we started via startActivityFromRecents() during this gesture. */ public void updateLastStartedTaskId(int lastStartedTaskId) { public void updateLastStartedTaskIds(int[] lastStartedTaskId) { mLastStartedTaskId = lastStartedTaskId; } Loading @@ -342,7 +384,7 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL * @return The id of the task that was most recently started during this gesture, or -1 if * no task has been started yet (i.e. we haven't settled on a new task). */ public int getLastStartedTaskId() { public int[] getLastStartedTaskIds() { return mLastStartedTaskId; } Loading Loading @@ -478,8 +520,8 @@ public class GestureState implements RecentsAnimationCallbacks.RecentsAnimationL pw.println(" gestureID=" + mGestureId); pw.println(" runningTask=" + mRunningTask); pw.println(" endTarget=" + mEndTarget); pw.println(" lastAppearedTaskTargetId=" + getLastAppearedTaskId()); pw.println(" lastStartedTaskId=" + mLastStartedTaskId); pw.println(" lastAppearedTaskTargetId=" + Arrays.toString(mLastAppearedTaskTargets)); pw.println(" lastStartedTaskId=" + Arrays.toString(mLastStartedTaskId)); pw.println(" isRecentsAnimationRunning=" + isRecentsAnimationRunning()); } }
quickstep/src/com/android/quickstep/RecentsAnimationController.java +2 −3 Original line number Diff line number Diff line Loading @@ -115,8 +115,8 @@ public class RecentsAnimationController { * {@link RecentsAnimationCallbacks#onTasksAppeared}}. */ @UiThread public void removeTaskTarget(@NonNull RemoteAnimationTarget target) { UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(target.taskId)); public void removeTaskTarget(int targetTaskId) { UI_HELPER_EXECUTOR.execute(() -> mController.removeTask(targetTaskId)); } @UiThread Loading Loading @@ -167,7 +167,6 @@ public class RecentsAnimationController { /* event= */ "finishRecentsAnimation", /* extras= */ toRecents, /* gestureEvent= */ FINISH_RECENTS_ANIMATION); // Finish not yet requested mFinishRequested = true; mFinishTargetIsLauncher = toRecents; Loading
quickstep/src/com/android/quickstep/TaskAnimationManager.java +21 −11 Original line number Diff line number Diff line Loading @@ -59,7 +59,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn private RecentsAnimationTargets mTargets; // Temporary until we can hook into gesture state events private GestureState mLastGestureState; private RemoteAnimationTarget mLastAppearedTaskTarget; private RemoteAnimationTarget[] mLastAppearedTaskTargets; private Runnable mLiveTileCleanUpHandler; private Context mCtx; Loading Loading @@ -141,8 +141,15 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn } mController = controller; mTargets = targets; mLastAppearedTaskTarget = mTargets.findTask(mLastGestureState.getRunningTaskId()); mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); // TODO(b/236226779): We can probably get away w/ setting mLastAppearedTaskTargets // to all appeared targets directly vs just looking at running ones int[] runningTaskIds = mLastGestureState.getRunningTaskIds(targets.apps.length > 1); mLastAppearedTaskTargets = new RemoteAnimationTarget[runningTaskIds.length]; for (int i = 0; i < runningTaskIds.length; i++) { RemoteAnimationTarget task = mTargets.findTask(runningTaskIds[i]); mLastAppearedTaskTargets[i] = task; } mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets); } @Override Loading Loading @@ -196,14 +203,17 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn true /*shown*/, null /* animatorHandler */); } if (mController != null) { if (mLastAppearedTaskTarget == null || appearedTaskTarget.taskId != mLastAppearedTaskTarget.taskId) { if (mLastAppearedTaskTarget != null) { mController.removeTaskTarget(mLastAppearedTaskTarget); if (mLastAppearedTaskTargets != null) { for (RemoteAnimationTarget lastTarget : mLastAppearedTaskTargets) { for (RemoteAnimationTarget appearedTarget : appearedTaskTargets) { if (appearedTarget.taskId != lastTarget.taskId) { mController.removeTaskTarget(lastTarget.taskId); } } } mLastAppearedTaskTarget = appearedTaskTarget; mLastGestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); } mLastAppearedTaskTargets = appearedTaskTargets; mLastGestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets); } } Loading Loading @@ -268,7 +278,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks.addListener(gestureState); gestureState.setState(STATE_RECENTS_ANIMATION_INITIALIZED | STATE_RECENTS_ANIMATION_STARTED); gestureState.updateLastAppearedTaskTarget(mLastAppearedTaskTarget); gestureState.updateLastAppearedTaskTargets(mLastAppearedTaskTargets); return mCallbacks; } Loading Loading @@ -369,7 +379,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn mCallbacks = null; mTargets = null; mLastGestureState = null; mLastAppearedTaskTarget = null; mLastAppearedTaskTargets = null; } @Nullable Loading
quickstep/src/com/android/quickstep/TopTaskTracker.java +1 −1 Original line number Diff line number Diff line Loading @@ -210,7 +210,7 @@ public class TopTaskTracker extends ISplitScreenListener.Stub implements TaskSta @Nullable private final RunningTaskInfo mTopTask; private final List<RunningTaskInfo> mAllCachedTasks; public final List<RunningTaskInfo> mAllCachedTasks; CachedTaskInfo(List<RunningTaskInfo> allCachedTasks) { mAllCachedTasks = allCachedTasks; Loading