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

Commit 5b3aa269 authored by Evan Rosky's avatar Evan Rosky
Browse files

Support nesting in leaftaskfilter and make recents compatible

The filter only checked "every-other" level because it would
return early if it found a child; however, split-screen is
>1 layer deep, so we actually need to still record the task
as a child so its parents will also be rejected.

This exposed an issue in RecentsHandler where it wouldn't
reset the task surface visibility of root tasks when
cancelling (going-back to app), so this fixes that as well
by tracking leafs and roots but only forwarding the leafs to
launcher

Bug: 283176051
Test: put windows in split, swipe into overview, observe transition
      info in logs.
Change-Id: Ib545792891bad93104892a55ad7059eff7b7a623
parent 75024846
Loading
Loading
Loading
Loading
+76 −26
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.ArrayMap;
import android.util.IntArray;
import android.util.Pair;
import android.util.Slog;
import android.view.Display;
@@ -422,26 +423,28 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
            // 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.
            final int belowLayers = info.getChanges().size();
            final int aboveLayers = info.getChanges().size() * 3;
            for (int i = 0; i < info.getChanges().size(); ++i) {
                final TransitionInfo.Change change = info.getChanges().get(i);
                final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
                if (TransitionUtil.isWallpaper(change)) {
                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                            // wallpapers go into the "below" layer space
                            info.getChanges().size() - i, info, t, mLeashMap);
                            belowLayers - 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 = TransitionUtil.newTarget(change,
                            info.getChanges().size() - i, info, t, mLeashMap);
                            belowLayers - i, info, t, mLeashMap);
                    apps.add(target);
                    if (TransitionUtil.isClosingType(change.getMode())) {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  adding pausing taskId=%d", taskInfo.taskId);
                                "  adding pausing leaf taskId=%d", taskInfo.taskId);
                        // raise closing (pausing) task to "above" layer so it isn't covered
                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
                        t.setLayer(target.leash, aboveLayers - i);
                        mPausingTasks.add(new TaskState(change, target.leash));
                        if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                            // This can only happen if we have a separate recents/home (3p launcher)
@@ -454,17 +457,32 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                    } else if (taskInfo != null
                            && taskInfo.topActivityType == ACTIVITY_TYPE_RECENTS) {
                        // There's a 3p launcher, so make sure recents goes above that.
                        t.setLayer(target.leash, info.getChanges().size() * 3 - i);
                        t.setLayer(target.leash, aboveLayers - i);
                    } else if (taskInfo != null && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                        // do nothing
                    } else if (TransitionUtil.isOpeningType(change.getMode())) {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  adding opening taskId=%d", taskInfo.taskId);
                                "  adding opening leaf taskId=%d", taskInfo.taskId);
                        mOpeningTasks.add(new TaskState(change, target.leash));
                    }
                } else if (taskInfo != null && TransitionInfo.isIndependent(change, info)) {
                    // Root tasks
                    if (TransitionUtil.isClosingType(change.getMode())) {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  adding pausing taskId=%d", taskInfo.taskId);
                        // raise closing (pausing) task to "above" layer so it isn't covered
                        t.setLayer(change.getLeash(), aboveLayers - i);
                        mPausingTasks.add(new TaskState(change, null /* leash */));
                    } else if (TransitionUtil.isOpeningType(change.getMode())) {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  adding opening taskId=%d", taskInfo.taskId);
                        // Put into the "below" layer space.
                        t.setLayer(change.getLeash(), belowLayers - i);
                        mOpeningTasks.add(new TaskState(change, null /* leash */));
                    }
                } else if (TransitionUtil.isDividerBar(change)) {
                    final RemoteAnimationTarget target = TransitionUtil.newTarget(change,
                            info.getChanges().size() - i, info, t, mLeashMap);
                            belowLayers - i, info, t, mLeashMap);
                    // Add this as a app and we will separate them on launcher side by window type.
                    apps.add(target);
                }
@@ -519,7 +537,9 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
            }
            ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                    "[%d] RecentsController.merge", mInstanceId);
            // Keep all tasks in one list because order matters.
            ArrayList<TransitionInfo.Change> openingTasks = null;
            IntArray openingTaskIsLeafs = null;
            ArrayList<TransitionInfo.Change> closingTasks = null;
            mOpeningSeparateHome = false;
            TransitionInfo.Change recentsOpening = null;
@@ -538,25 +558,29 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                    cancel("task #" + taskInfo.taskId + " is always_on_top");
                    return;
                }
                hasTaskChange = hasTaskChange || taskInfo != null;
                final boolean isRootTask = taskInfo != null
                        && TransitionInfo.isIndependent(change, info);
                hasTaskChange = hasTaskChange || isRootTask;
                final boolean isLeafTask = leafTaskFilter.test(change);
                if (TransitionUtil.isOpeningType(change.getMode())) {
                    if (mRecentsTask != null && mRecentsTask.equals(change.getContainer())) {
                        recentsOpening = change;
                    } else if (isLeafTask) {
                        if (taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                    } else if (isRootTask || isLeafTask) {
                        if (isLeafTask && taskInfo.topActivityType == ACTIVITY_TYPE_HOME) {
                            // This is usually a 3p launcher
                            mOpeningSeparateHome = true;
                        }
                        if (openingTasks == null) {
                            openingTasks = new ArrayList<>();
                            openingTaskIsLeafs = new IntArray();
                        }
                        openingTasks.add(change);
                        openingTaskIsLeafs.add(isLeafTask ? 1 : 0);
                    }
                } else if (TransitionUtil.isClosingType(change.getMode())) {
                    if (mRecentsTask != null && mRecentsTask.equals(change.getContainer())) {
                        foundRecentsClosing = true;
                    } else if (isLeafTask) {
                    } else if (isRootTask || isLeafTask) {
                        if (closingTasks == null) {
                            closingTasks = new ArrayList<>();
                        }
@@ -622,7 +646,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                    }
                    final TaskState openingTask = mOpeningTasks.remove(openingIdx);
                    ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                            "  pausing opening taskId=%d", openingTask.mTaskInfo.taskId);
                            "  pausing opening %staskId=%d", openingTask.isLeaf() ? "leaf " : "",
                            openingTask.mTaskInfo.taskId);
                    mPausingTasks.add(openingTask);
                    didMergeThings = true;
                }
@@ -632,35 +657,55 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                // Switching to some new tasks, add to mOpening and remove from mPausing. Also,
                // enter NEW_TASK state since this will start the switch-to animation.
                final int layer = mInfo.getChanges().size() * 3;
                appearedTargets = new RemoteAnimationTarget[openingTasks.size()];
                int openingLeafCount = 0;
                for (int i = 0; i < openingTaskIsLeafs.size(); ++i) {
                    openingLeafCount += openingTaskIsLeafs.get(i);
                }
                if (openingLeafCount > 0) {
                    appearedTargets = new RemoteAnimationTarget[openingLeafCount];
                }
                int nextTargetIdx = 0;
                for (int i = 0; i < openingTasks.size(); ++i) {
                    final TransitionInfo.Change change = openingTasks.get(i);
                    final boolean isLeaf = openingTaskIsLeafs.get(i) == 1;
                    int pausingIdx = TaskState.indexOf(mPausingTasks, change);
                    if (pausingIdx >= 0) {
                        // Something is showing/opening a previously-pausing app.
                        appearedTargets[i] = TransitionUtil.newTarget(
                        if (isLeaf) {
                            appearedTargets[nextTargetIdx++] = TransitionUtil.newTarget(
                                    change, layer, mPausingTasks.get(pausingIdx).mLeash);
                        }
                        final TaskState pausingTask = mPausingTasks.remove(pausingIdx);
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  opening pausing taskId=%d", pausingTask.mTaskInfo.taskId);
                                "  opening pausing %staskId=%d", isLeaf ? "leaf " : "",
                                pausingTask.mTaskInfo.taskId);
                        mOpeningTasks.add(pausingTask);
                        // Setup hides opening tasks initially, so make it visible again (since we
                        // are already showing it).
                        t.show(change.getLeash());
                        t.setAlpha(change.getLeash(), 1.f);
                    } else {
                        // We are receiving new opening tasks, so convert to onTasksAppeared.
                        appearedTargets[i] = TransitionUtil.newTarget(
                    } else if (isLeaf) {
                        // We are receiving new opening leaf tasks, so convert to onTasksAppeared.
                        final RemoteAnimationTarget target = TransitionUtil.newTarget(
                                change, layer, info, t, mLeashMap);
                        appearedTargets[nextTargetIdx++] = target;
                        // reparent into the original `mInfo` since that's where we are animating.
                        final int rootIdx = TransitionUtil.rootIndexFor(change, mInfo);
                        t.reparent(appearedTargets[i].leash, mInfo.getRoot(rootIdx).getLeash());
                        t.setLayer(appearedTargets[i].leash, layer);
                        t.reparent(target.leash, mInfo.getRoot(rootIdx).getLeash());
                        t.setLayer(target.leash, layer);
                        // Hide the animation leash, let listener show it.
                        t.hide(appearedTargets[i].leash);
                        t.hide(target.leash);
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  opening new leaf taskId=%d", target.taskId);
                        mOpeningTasks.add(new TaskState(change, target.leash));
                    } else {
                        ProtoLog.v(ShellProtoLogGroup.WM_SHELL_RECENTS_TRANSITION,
                                "  opening new taskId=%d", appearedTargets[i].taskId);
                        mOpeningTasks.add(new TaskState(change, appearedTargets[i].leash));
                                "  opening new taskId=%d", change.getTaskInfo().taskId);
                        t.setLayer(change.getLeash(), layer);
                        // Setup hides opening tasks initially, so make it visible since recents
                        // is only animating the leafs.
                        t.show(change.getLeash());
                        mOpeningTasks.add(new TaskState(change, null));
                    }
                }
                didMergeThings = true;
@@ -845,7 +890,7 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
                    t.show(mOpeningTasks.get(i).mTaskSurface);
                }
                for (int i = 0; i < mPausingTasks.size(); ++i) {
                    if (!sendUserLeaveHint) {
                    if (!sendUserLeaveHint && mPausingTasks.get(i).isLeaf()) {
                        // This means recents is not *actually* finishing, so of course we gotta
                        // do special stuff in WMCore to accommodate.
                        wct.setDoNotPip(mPausingTasks.get(i).mToken);
@@ -924,7 +969,8 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
        /** The surface/leash of the task provided by Core. */
        SurfaceControl mTaskSurface;

        /** The (local) animation-leash created for this task. */
        /** The (local) animation-leash created for this task. Only non-null for leafs. */
        @Nullable
        SurfaceControl mLeash;

        TaskState(TransitionInfo.Change change, SurfaceControl leash) {
@@ -943,6 +989,10 @@ public class RecentsTransitionHandler implements Transitions.TransitionHandler {
            return -1;
        }

        boolean isLeaf() {
            return mLeash != null;
        }

        public String toString() {
            return "" + mToken + " : " + mLeash;
        }
+4 −5
Original line number Diff line number Diff line
@@ -121,15 +121,14 @@ public class TransitionUtil {
        @Override
        public boolean test(TransitionInfo.Change change) {
            final ActivityManager.RunningTaskInfo taskInfo = change.getTaskInfo();
            if (taskInfo == null) return false;
            // Children always come before parent since changes are in top-to-bottom z-order.
            if ((taskInfo == null) || mChildTaskTargets.get(taskInfo.taskId)) {
                // has children, so not a leaf. Skip.
                return false;
            }
            boolean hasChildren = mChildTaskTargets.get(taskInfo.taskId);
            if (taskInfo.hasParentTask()) {
                mChildTaskTargets.put(taskInfo.parentTaskId, true);
            }
            return true;
            // If it has children, it's not a leaf.
            return !hasChildren;
        }
    }