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

Commit af1c069f authored by Winson Chung's avatar Winson Chung Committed by Jeremy Sim
Browse files

Preemptively adjust task info visibility when evicting tasks

- When a child of a split root is evicted, preemptively mark it as
  not visible to ensure that it isn't considered when reporting
  split pair tasks to the recent tasks controller.  This CL does not
  attempt to fix the underlaying problem that mChildrenTaskInfo does
  not track z-order while certain parts of the code already assume
  it does

Bug: 378030938
Bug: 378601156
Flag: EXEMPT bugfix
Test: atest WMShellUnitTests
Change-Id: Ib1bb621c6243f31fa7a4e25bff00714839154ff5
parent f1173e14
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -3182,9 +3182,9 @@ public class StageCoordinator implements SplitLayout.SplitLayoutHandler,
        for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
        for (int i = mPausingTasks.size() - 1; i >= 0; --i) {
            final int taskId = mPausingTasks.get(i);
            final int taskId = mPausingTasks.get(i);
            if (mMainStage.containsTask(taskId)) {
            if (mMainStage.containsTask(taskId)) {
                mMainStage.evictChildren(finishWct, taskId);
                mMainStage.evictChild(finishWct, taskId, "recentsPairToPair");
            } else if (mSideStage.containsTask(taskId)) {
            } else if (mSideStage.containsTask(taskId)) {
                mSideStage.evictChildren(finishWct, taskId);
                mSideStage.evictChild(finishWct, taskId, "recentsPairToPair");
            }
            }
        }
        }
        // If pending enter hasn't consumed, the mix handler will invoke start pending
        // If pending enter hasn't consumed, the mix handler will invoke start pending
+22 −13
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@ import static com.android.wm.shell.shared.split.SplitScreenConstants.CONTROLLED_
import android.annotation.CallSuper;
import android.annotation.CallSuper;
import android.annotation.Nullable;
import android.annotation.Nullable;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.TaskInfo;
import android.content.Context;
import android.content.Context;
import android.graphics.Rect;
import android.graphics.Rect;
import android.os.IBinder;
import android.os.IBinder;
@@ -138,6 +139,8 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
     * Returns the top visible child task's id.
     * Returns the top visible child task's id.
     */
     */
    int getTopVisibleChildTaskId() {
    int getTopVisibleChildTaskId() {
        // TODO(b/378601156): This doesn't get the top task (translucent tasks are also
        //  visible-requested)
        final ActivityManager.RunningTaskInfo taskInfo = getChildTaskInfo(t -> t.isVisible
        final ActivityManager.RunningTaskInfo taskInfo = getChildTaskInfo(t -> t.isVisible
                && t.isVisibleRequested);
                && t.isVisibleRequested);
        return taskInfo != null ? taskInfo.taskId : INVALID_TASK_ID;
        return taskInfo != null ? taskInfo.taskId : INVALID_TASK_ID;
@@ -147,6 +150,7 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
     * Returns the top activity uid for the top child task.
     * Returns the top activity uid for the top child task.
     */
     */
    int getTopChildTaskUid() {
    int getTopChildTaskUid() {
        // TODO(b/378601156): This doesn't get the top task
        final ActivityManager.RunningTaskInfo taskInfo =
        final ActivityManager.RunningTaskInfo taskInfo =
                getChildTaskInfo(t -> t.topActivityInfo != null);
                getChildTaskInfo(t -> t.topActivityInfo != null);
        return taskInfo != null ? taskInfo.topActivityInfo.applicationInfo.uid : 0;
        return taskInfo != null ? taskInfo.topActivityInfo.applicationInfo.uid : 0;
@@ -379,10 +383,9 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {


    /** Collects all the current child tasks and prepares transaction to evict them to display. */
    /** Collects all the current child tasks and prepares transaction to evict them to display. */
    void evictAllChildren(WindowContainerTransaction wct) {
    void evictAllChildren(WindowContainerTransaction wct) {
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Evicting all children");
        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);
            wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
            evictChild(wct, taskInfo, "all");
        }
        }
    }
    }


@@ -390,13 +393,11 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        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 (taskId == taskInfo.taskId) continue;
            ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Evict other child: task=%d", taskId);
            evictChild(wct, taskInfo, "other");
            wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
        }
        }
    }
    }


    void evictNonOpeningChildren(RemoteAnimationTarget[] apps, WindowContainerTransaction wct) {
    void evictNonOpeningChildren(RemoteAnimationTarget[] apps, WindowContainerTransaction wct) {
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "evictNonOpeningChildren");
        final SparseArray<ActivityManager.RunningTaskInfo> toBeEvict = mChildrenTaskInfo.clone();
        final SparseArray<ActivityManager.RunningTaskInfo> toBeEvict = mChildrenTaskInfo.clone();
        for (int i = 0; i < apps.length; i++) {
        for (int i = 0; i < apps.length; i++) {
            if (apps[i].mode == MODE_OPENING) {
            if (apps[i].mode == MODE_OPENING) {
@@ -405,8 +406,7 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        }
        }
        for (int i = toBeEvict.size() - 1; i >= 0; i--) {
        for (int i = toBeEvict.size() - 1; i >= 0; i--) {
            final ActivityManager.RunningTaskInfo taskInfo = toBeEvict.valueAt(i);
            final ActivityManager.RunningTaskInfo taskInfo = toBeEvict.valueAt(i);
            ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Evict non-opening child: task=%d", taskInfo.taskId);
            evictChild(wct, taskInfo, "non-opening");
            wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
        }
        }
    }
    }


@@ -414,19 +414,28 @@ public class StageTaskListener implements ShellTaskOrganizer.TaskListener {
        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 (!taskInfo.isVisible) {
            if (!taskInfo.isVisible) {
                ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Evict invisible child: task=%d",
                evictChild(wct, taskInfo, "invisible");
                        taskInfo.taskId);
                wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
            }
            }
        }
        }
    }
    }


    void evictChildren(WindowContainerTransaction wct, int taskId) {
    void evictChild(WindowContainerTransaction wct, int taskId, String reason) {
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Evict child: task=%d", taskId);
        final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.get(taskId);
        final ActivityManager.RunningTaskInfo taskInfo = mChildrenTaskInfo.get(taskId);
        if (taskInfo != null) {
        if (taskInfo != null) {
            wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
            evictChild(wct, taskInfo, reason);
        }
    }
    }

    private void evictChild(@NonNull WindowContainerTransaction wct, @NonNull TaskInfo taskInfo,
            @NonNull String reason) {
        ProtoLog.d(WM_SHELL_SPLIT_SCREEN, "Evict child: task=%d reason=%s", taskInfo.taskId,
                reason);
        // We are reparenting the task, but not removing the task from mChildrenTaskInfo, so to
        // prevent this task from being considered as a top task for the roots, we need to override
        // the visibility of the soon-to-be-hidden task
        taskInfo.isVisible = false;
        taskInfo.isVisibleRequested = false;
        wct.reparent(taskInfo.token, null /* parent */, false /* onTop */);
    }
    }


    void reparentTopTask(WindowContainerTransaction wct) {
    void reparentTopTask(WindowContainerTransaction wct) {