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

Commit 2d70157d authored by Evan Rosky's avatar Evan Rosky
Browse files

Add a TaskState tracking mechanism to Recents transition

This is a further re-arrangement. No logic should change.

This intrudeces a TaskState class which can track some
properties of a task which recents animation cares about.
This change is separated from the one that actually changes
logic to minimize mixing of rearrangement and logic change.

In order to have the right information for the task-states
(in particular, both the task surface and the wrapper leash),
this had to localize the RemoteAnimationTarget wrapping into
the recents wrapper. This should do the same thing though as
its using the same filters.

Bug: 269691848
Bug: 269691226
Test: no logic changes... existing tests pass
Change-Id: Ibc208bd147d84069ae30b010768a6112c57c09b1
parent 9621dce5
Loading
Loading
Loading
Loading
+84 −49
Original line number Diff line number Diff line
@@ -18,7 +18,6 @@ package com.android.systemui.shared.system;

import static android.app.WindowConfiguration.ACTIVITY_TYPE_HOME;
import static android.app.WindowConfiguration.ACTIVITY_TYPE_RECENTS;
import static android.view.RemoteAnimationTarget.MODE_CLOSING;
import static android.view.WindowManager.TRANSIT_CHANGE;
import static android.view.WindowManager.TRANSIT_CLOSE;
import static android.view.WindowManager.TRANSIT_FLAG_KEYGUARD_LOCKED;
@@ -107,7 +106,7 @@ public class RemoteTransitionCompat {
        private RecentsAnimationListener mListener = null;
        private RecentsAnimationControllerCompat mWrapped = null;
        private IRemoteTransitionFinishedCallback mFinishCB = null;
        private ArrayList<WindowContainerToken> mPausingTasks = null;
        private ArrayList<TaskState> mPausingTasks = null;
        private WindowContainerToken mPipTask = null;
        private WindowContainerToken mRecentsTask = null;
        private int mRecentsTaskId = 0;
@@ -140,34 +139,40 @@ public class RemoteTransitionCompat {
            mTransition = transition;
            mKeyguardLocked = (info.getFlags() & TRANSIT_FLAG_KEYGUARD_LOCKED) != 0;

            final RemoteAnimationTarget[] apps =
                    RemoteAnimationTargetCompat.wrapApps(info, t, mLeashMap);
            final RemoteAnimationTarget[] wallpapers =
                    RemoteAnimationTargetCompat.wrapNonApps(
                            info, true /* wallpapers */, t, mLeashMap);

            // This transition is for opening recents, so recents is on-top. We want to draw
            // the current going-away tasks on top of recents, though, so move them to front.
            // Note that we divide up the "layer space" into 3 regions each the size of
            // the change count. This way we can easily move changes into above/below/between
            final ArrayList<RemoteAnimationTarget> apps = new ArrayList<>();
            final ArrayList<RemoteAnimationTarget> wallpapers = new ArrayList<>();
            RemoteAnimationTargetCompat.LeafTaskFilter leafTaskFilter =
                    new RemoteAnimationTargetCompat.LeafTaskFilter();
            // About layering: we divide up the "layer space" into 3 regions (each the size of
            // the change count). This lets us categorize things into above/below/between
            // while maintaining their relative ordering.
            for (int i = apps.length - 1; i >= 0; --i) {
                final ActivityManager.RunningTaskInfo taskInfo = apps[i].taskInfo;
                if (apps[i].mode == MODE_CLOSING) {
                    t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
                    if (taskInfo == null) {
                        continue;
                    }
                    // Add to front since we are iterating backwards.
                    mPausingTasks.add(0, taskInfo.token);
            for (int i = 0; i < info.getChanges().size(); ++i) {
                final TransitionInfo.Change change = info.getChanges().get(i);
                final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                if (RemoteAnimationTargetCompat.isWallpaper(change)) {
                    final RemoteAnimationTarget target = newTarget(change,
                            // wallpapers go into the "below" layer space
                            info.getChanges().size() - i, info, t, mLeashMap);
                    wallpapers.add(target);
                    // Make all the wallpapers opaque since we want them visible from the start
                    t.setAlpha(target.leash, 1);
                } else if (leafTaskFilter.test(change)) {
                    // start by putting everything into the "below" layer space.
                    final RemoteAnimationTarget target = newTarget(change,
                            info.getChanges().size() - i, info, t, mLeashMap);
                    apps.add(target);
                    if (change.getMode() == TRANSIT_CLOSE || change.getMode() == TRANSIT_TO_BACK) {
                        // raise closing (pausing) task to "above" layer so it isn't covered
                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
                        mPausingTasks.add(new TaskState(change, target.leash));
                        if (taskInfo.pictureInPictureParams != null
                                && taskInfo.pictureInPictureParams.isAutoEnterEnabled()) {
                            mPipTask = taskInfo.token;
                        }
                    } else if (taskInfo != null
                            && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
                    // This task is for recents, keep it on top.
                    t.setLayer(apps[i].leash, info.getChanges().size() * 3 - i);
                        // There's a 3p launcher, so make sure recents goes above that.
                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
                        mRecentsTask = taskInfo.token;
                        mRecentsTaskId = taskInfo.taskId;
                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
@@ -175,12 +180,11 @@ public class RemoteTransitionCompat {
                        mRecentsTaskId = taskInfo.taskId;
                    }
                }
            // Also make all the wallpapers opaque since we want the visible from the start
            for (int i = wallpapers.length - 1; i >= 0; --i) {
                t.setAlpha(wallpapers[i].leash, 1);
            }
            t.apply();
            mListener.onAnimationStart(this, apps, wallpapers, new Rect(0, 0, 0, 0), new Rect());
            mListener.onAnimationStart(this, apps.toArray(new RemoteAnimationTarget[apps.size()]),
                    wallpapers.toArray(new RemoteAnimationTarget[wallpapers.size()]),
                    new Rect(0, 0, 0, 0), new Rect());
        }

        @SuppressLint("NewApi")
@@ -234,7 +238,7 @@ public class RemoteTransitionCompat {
            int pauseMatches = 0;
            if (!foundHomeOpening) {
                for (int i = 0; i < openingTasks.size(); ++i) {
                    if (mPausingTasks.contains(openingTasks.valueAt(i).getContainer())) {
                    if (TaskState.indexOf(mPausingTasks, openingTasks.valueAt(i)) >= 0) {
                        ++pauseMatches;
                    }
                }
@@ -338,8 +342,8 @@ public class RemoteTransitionCompat {
                // re-showing it's task).
                for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
                    // reverse order so that index 0 ends up on top
                    wct.reorder(mPausingTasks.get(i), true /* onTop */);
                    t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
                    wct.reorder(mPausingTasks.get(i).mToken, true /* onTop */);
                    t.show(mPausingTasks.get(i).mTaskSurface);
                }
                if (!mKeyguardLocked && mRecentsTask != null) {
                    wct.restoreTransientOrder(mRecentsTask);
@@ -350,15 +354,14 @@ public class RemoteTransitionCompat {
                // This is basically going home, but we have to restore recents order and also
                // treat the home "pausing" task properly.
                for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
                    final TransitionInfo.Change change = mInfo.getChange(mPausingTasks.get(i));
                    final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                    if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                    final TaskState state = mPausingTasks.get(i);
                    if (state.mTaskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                        // Treat as opening (see above)
                        wct.reorder(mPausingTasks.get(i), true /* onTop */);
                        t.show(mInfo.getChange(mPausingTasks.get(i)).getLeash());
                        wct.reorder(state.mToken, true /* onTop */);
                        t.show(state.mTaskSurface);
                    } else {
                        // Treat as hiding (see below)
                        t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash());
                        t.hide(state.mTaskSurface);
                    }
                }
                if (!mKeyguardLocked && mRecentsTask != null) {
@@ -369,13 +372,13 @@ public class RemoteTransitionCompat {
                    if (!sendUserLeaveHint) {
                        // This means recents is not *actually* finishing, so of course we gotta
                        // do special stuff in WMCore to accommodate.
                        wct.setDoNotPip(mPausingTasks.get(i));
                        wct.setDoNotPip(mPausingTasks.get(i).mToken);
                    }
                    // Since we will reparent out of the leashes, pre-emptively hide the child
                    // surface to match the leash. Otherwise, there will be a flicker before the
                    // visibility gets committed in Core when using split-screen (in splitscreen,
                    // the leaf-tasks are not "independent" so aren't hidden by normal setup).
                    t.hide(mInfo.getChange(mPausingTasks.get(i)).getLeash());
                    t.hide(mPausingTasks.get(i).mTaskSurface);
                }
                if (mPipTask != null && mPipTransaction != null && sendUserLeaveHint) {
                    t.show(mInfo.getChange(mPipTask).getLeash());
@@ -444,4 +447,36 @@ public class RemoteTransitionCompat {
        @Override public void animateNavigationBarToApp(long duration) {
        }
    }

    /** Utility class to track the state of a task as-seen by recents. */
    private static class TaskState {
        WindowContainerToken mToken;
        ActivityManager.RunningTaskInfo mTaskInfo;

        /** The surface/leash of the task provided by Core. */
        SurfaceControl mTaskSurface;

        /** The (local) animation-leash created for this task. */
        SurfaceControl mLeash;

        TaskState(TransitionInfo.Change change, SurfaceControl leash) {
            mToken = change.getContainer();
            mTaskInfo = change.getTaskInfo();
            mTaskSurface = change.getLeash();
            mLeash = leash;
        }

        static int indexOf(ArrayList<TaskState> list, TransitionInfo.Change change) {
            for (int i = list.size() - 1; i >= 0; --i) {
                if (list.get(i).mToken.equals(change.getContainer())) {
                    return i;
                }
            }
            return -1;
        }

        public String toString() {
            return "" + mToken + " : " + mLeash;
        }
    }
}