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

Commit 40314fe5 authored by Winson Chung's avatar Winson Chung
Browse files

Skip evicting children that are opening when entering split

- When launching a trampoline activity into split, the trampolining can
  result in the launch of the next activity in the same transition as
  the launch transition (but in an incorrect order), which can result
  in the wrong child being retained (the original activity which will
  end up being closed).  Instead, track all the opening tasks in the
  enter transition (not just the top most), and only evict the other
  tasks but those

Bug: 385674612
Flag: EXEMPT bugfix
Test: Manual, launch trampoline activity into split, quickswitch
      split again with same trampoline activity (repeat multiple times)
Change-Id: Id08cceef94b109cc6bc43add263bbe2ccc5148fc
parent 29967216
Loading
Loading
Loading
Loading
+22 −11
Original line number Original line Diff line number Diff line
@@ -3756,6 +3756,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        // First, verify that we actually have opened apps in both splits.
        // First, verify that we actually have opened apps in both splits.
        TransitionInfo.Change mainChild = null;
        TransitionInfo.Change mainChild = null;
        TransitionInfo.Change sideChild = null;
        TransitionInfo.Change sideChild = null;
        // Tracks the set of opening tasks in the transition
        final Set<Integer> openingMainTaskIds = new HashSet<>();
        final Set<Integer> openingSideTaskIds = new HashSet<>();
        StageTaskListener firstAppStage = null;
        StageTaskListener firstAppStage = null;
        StageTaskListener secondAppStage = null;
        StageTaskListener secondAppStage = null;
        boolean foundPausingTask = false;
        boolean foundPausingTask = false;
@@ -3770,21 +3773,30 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            }
            }
            StageTaskListener stage = getStageOfTask(taskInfo);
            StageTaskListener stage = getStageOfTask(taskInfo);
            final @StageType int stageType = getStageType(stage);
            final @StageType int stageType = getStageType(stage);
            if (mainChild == null
            final boolean isMainStage = stageType
                    && stageType == (enableFlexibleSplit() ? STAGE_TYPE_A : STAGE_TYPE_MAIN)
                    == (enableFlexibleSplit() ? STAGE_TYPE_A : STAGE_TYPE_MAIN);
                    && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) {
            final boolean isSideStage = stageType
                    == (enableFlexibleSplit() ? STAGE_TYPE_B : STAGE_TYPE_SIDE);
            final boolean isVisibleTask = isOpeningType(change.getMode())
                    || change.getMode() == TRANSIT_CHANGE;
            if (mainChild == null && isMainStage && isVisibleTask) {
                // Includes TRANSIT_CHANGE to cover reparenting top-most task to split.
                // Includes TRANSIT_CHANGE to cover reparenting top-most task to split.
                mainChild = change;
                mainChild = change;
                firstAppStage = getStageOfTask(taskInfo);
                firstAppStage = getStageOfTask(taskInfo);
            } else if (sideChild == null
            } else if (sideChild == null && isSideStage && isVisibleTask) {
                    && stageType == (enableFlexibleSplit() ? STAGE_TYPE_B : STAGE_TYPE_SIDE)
                    && (isOpeningType(change.getMode()) || change.getMode() == TRANSIT_CHANGE)) {
                sideChild = change;
                sideChild = change;
                secondAppStage = stage;
                secondAppStage = stage;
            } else if (stageType != STAGE_TYPE_UNDEFINED && change.getMode() == TRANSIT_TO_BACK) {
            } else if (stageType != STAGE_TYPE_UNDEFINED && change.getMode() == TRANSIT_TO_BACK) {
                // Collect all to back task's and evict them when transition finished.
                // Collect all to back task's and evict them when transition finished.
                evictWct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
                evictWct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
            }
            }
            if (isVisibleTask) {
                if (isMainStage) {
                    openingMainTaskIds.add(taskInfo.taskId);
                } else if (isSideStage) {
                    openingSideTaskIds.add(taskInfo.taskId);
                }
            }
        }
        }


        SplitScreenTransitions.EnterSession pendingEnter = mSplitTransitions.mPendingEnter;
        SplitScreenTransitions.EnterSession pendingEnter = mSplitTransitions.mPendingEnter;
@@ -3860,16 +3872,14 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
            }
            }
            if (finalMainChild != null) {
            if (finalMainChild != null) {
                if (!mainNotContainOpenTask) {
                if (!mainNotContainOpenTask) {
                    finalFirstAppStage.evictOtherChildren(callbackWct,
                    finalFirstAppStage.evictOtherChildren(callbackWct, openingMainTaskIds);
                            finalMainChild.getTaskInfo().taskId);
                } else {
                } else {
                    finalFirstAppStage.evictInvisibleChildren(callbackWct);
                    finalFirstAppStage.evictInvisibleChildren(callbackWct);
                }
                }
            }
            }
            if (finalSideChild != null) {
            if (finalSideChild != null) {
                if (!sideNotContainOpenTask) {
                if (!sideNotContainOpenTask) {
                    finalSecondAppStage.evictOtherChildren(callbackWct,
                    finalSecondAppStage.evictOtherChildren(callbackWct, openingSideTaskIds);
                            finalSideChild.getTaskInfo().taskId);
                } else {
                } else {
                    finalSecondAppStage.evictInvisibleChildren(callbackWct);
                    finalSecondAppStage.evictInvisibleChildren(callbackWct);
                }
                }
@@ -3971,7 +3981,8 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        }
        }


        boolean replacingMainStage = getMainStagePosition() == mSplitRequest.mActivatePosition;
        boolean replacingMainStage = getMainStagePosition() == mSplitRequest.mActivatePosition;
        (replacingMainStage ? mMainStage : mSideStage).evictOtherChildren(wct, taskInfo.taskId);
        (replacingMainStage ? mMainStage : mSideStage).evictOtherChildren(wct,
                Set.of(taskInfo.taskId));
    }
    }


    boolean isLaunchToSplit(TaskInfo taskInfo) {
    boolean isLaunchToSplit(TaskInfo taskInfo) {
+4 −3
Original line number Original line Diff line number Diff line
@@ -60,6 +60,7 @@ import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.ArrayList;
import java.util.List;
import java.util.List;
import java.util.Optional;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Collectors;
@@ -432,11 +433,11 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        }
        }
    }
    }


    void evictOtherChildren(WindowContainerTransaction wct, int taskId) {
    void evictOtherChildren(WindowContainerTransaction wct, Set<Integer> keepTaskIds) {
        for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
        for (int i = mChildrenTaskInfo.size() - 1; i >= 0; i--) {
            final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
            final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.valueAt(i);
            if (taskId == taskInfo.taskId) continue;
            if (keepTaskIds.contains(taskInfo.taskId)) continue;
            evictChild(wct, taskInfo, "other");
            evictChild(wct, taskInfo, "other_" + stageTypeToString(mId));
        }
        }
    }
    }