Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 80fddb6e authored by Vinit Nayak's avatar Vinit Nayak Committed by Android (Google) Code Review
Browse files

Merge "Keep track of multiple TasksIDs and Targets in GestureState" into udc-qpr-dev

parents b9a5c455 e7e7a6e5
Loading
Loading
Loading
Loading
+55 −29
Original line number Diff line number Diff line
@@ -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;
@@ -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;

/**
@@ -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
@@ -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) {
@@ -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;
@@ -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 */);
@@ -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
@@ -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));
                });
@@ -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;
@@ -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) {
@@ -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
@@ -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");
@@ -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();
    }

@@ -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;
    }

    /**
+59 −17
Original line number Diff line number Diff line
@@ -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;
@@ -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,
@@ -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.
     */
@@ -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;

@@ -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;
    }
@@ -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];
    }

    /**
@@ -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) {
@@ -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;
    }

@@ -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;
    }

@@ -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());
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -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
@@ -167,7 +167,6 @@ public class RecentsAnimationController {
                /* event= */ "finishRecentsAnimation",
                /* extras= */ toRecents,
                /* gestureEvent= */ FINISH_RECENTS_ANIMATION);

        // Finish not yet requested
        mFinishRequested = true;
        mFinishTargetIsLauncher = toRecents;
+21 −11
Original line number Diff line number Diff line
@@ -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;

@@ -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
@@ -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);
                }
            }

@@ -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;
    }

@@ -369,7 +379,7 @@ public class TaskAnimationManager implements RecentsAnimationCallbacks.RecentsAn
        mCallbacks = null;
        mTargets = null;
        mLastGestureState = null;
        mLastAppearedTaskTarget = null;
        mLastAppearedTaskTargets = null;
    }

    @Nullable
+1 −1
Original line number Diff line number Diff line
@@ -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