Loading services/core/java/com/android/server/wm/ActivityMetricsLogger.java +13 −3 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.apphibernation.AppHibernationManagerInternal; import com.android.server.apphibernation.AppHibernationService; import com.android.window.flags.Flags; import java.util.ArrayList; import java.util.concurrent.TimeUnit; Loading Loading @@ -778,11 +779,12 @@ class ActivityMetricsLogger { */ private void updateSplitPairLaunches(@NonNull TransitionInfo info) { final Task launchedActivityTask = info.mLastLaunchedActivity.getTask(); final Task adjacentToLaunchedTask = launchedActivityTask.getAdjacentTask(); if (adjacentToLaunchedTask == null) { final Task launchedSplitRootTask = launchedActivityTask.getTaskWithAdjacent(); if (launchedSplitRootTask == null) { // Not a part of a split pair return; } for (int i = mTransitionInfoList.size() - 1; i >= 0; i--) { final TransitionInfo otherInfo = mTransitionInfoList.get(i); if (otherInfo == info) { Loading @@ -790,7 +792,15 @@ class ActivityMetricsLogger { } final Task otherTask = otherInfo.mLastLaunchedActivity.getTask(); // The adjacent task is the split root in which activities are started if (otherTask.isDescendantOf(adjacentToLaunchedTask)) { final boolean isDescendantOfAdjacent; if (Flags.allowMultipleAdjacentTaskFragments()) { isDescendantOfAdjacent = launchedSplitRootTask.forOtherAdjacentTasks( otherTask::isDescendantOf); } else { isDescendantOfAdjacent = otherTask.isDescendantOf( launchedSplitRootTask.getAdjacentTask()); } if (isDescendantOfAdjacent) { if (DEBUG_METRICS) { Slog.i(TAG, "Found adjacent tasks t1=" + launchedActivityTask.mTaskId + " t2=" + otherTask.mTaskId); Loading services/core/java/com/android/server/wm/AppTransitionController.java +1 −2 Original line number Diff line number Diff line Loading @@ -996,8 +996,7 @@ public class AppTransitionController { // If the current window container is a task with adjacent task set, the both // adjacent tasks will be opened or closed together. To get their opening or // closing animation target independently, skip promoting their animation targets. if (current.asTask() != null && current.asTask().getAdjacentTask() != null) { if (current.asTask() != null && current.asTask().hasAdjacentTask()) { canPromote = false; } Loading services/core/java/com/android/server/wm/DisplayPolicy.java +1 −1 Original line number Diff line number Diff line Loading @@ -2485,7 +2485,7 @@ public class DisplayPolicy { final TaskDisplayArea defaultTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea(); final boolean adjacentTasksVisible = defaultTaskDisplayArea.getRootTask(task -> task.isVisible() && task.getTopLeafTask().getAdjacentTask() != null) && task.getTopLeafTask().hasAdjacentTask()) != null; final Task topFreeformTask = defaultTaskDisplayArea .getTopRootTaskInWindowingMode(WINDOWING_MODE_FREEFORM); Loading services/core/java/com/android/server/wm/RootWindowContainer.java +18 −6 Original line number Diff line number Diff line Loading @@ -1796,12 +1796,24 @@ class RootWindowContainer extends WindowContainer<DisplayContent> activityAssistInfos.clear(); activityAssistInfos.add(new ActivityAssistInfo(top)); // Check if the activity on the split screen. if (Flags.allowMultipleAdjacentTaskFragments()) { top.getTask().forOtherAdjacentTasks(task -> { final ActivityRecord adjacentActivityRecord = task.getTopNonFinishingActivity(); if (adjacentActivityRecord != null) { activityAssistInfos.add( new ActivityAssistInfo(adjacentActivityRecord)); } }); } else { final Task adjacentTask = top.getTask().getAdjacentTask(); if (adjacentTask != null) { final ActivityRecord adjacentActivityRecord = adjacentTask.getTopNonFinishingActivity(); if (adjacentActivityRecord != null) { activityAssistInfos.add(new ActivityAssistInfo(adjacentActivityRecord)); activityAssistInfos.add( new ActivityAssistInfo(adjacentActivityRecord)); } } } if (rootTask == topFocusedRootTask) { Loading services/core/java/com/android/server/wm/Task.java +65 −6 Original line number Diff line number Diff line Loading @@ -2500,20 +2500,79 @@ class Task extends TaskFragment { return parentTask == null ? null : parentTask.getCreatedByOrganizerTask(); } /** @return the first adjacent task of this task or its parent. */ /** @deprecated b/373709676 replace with {@link #forOtherAdjacentTasks(Consumer)} ()}. */ @Deprecated @Nullable Task getAdjacentTask() { final TaskFragment adjacentTaskFragment = getAdjacentTaskFragment(); if (adjacentTaskFragment != null && adjacentTaskFragment.asTask() != null) { return adjacentTaskFragment.asTask(); if (Flags.allowMultipleAdjacentTaskFragments()) { throw new IllegalStateException("allowMultipleAdjacentTaskFragments is enabled. " + "Use #forOtherAdjacentTasks instead"); } final Task taskWithAdjacent = getTaskWithAdjacent(); if (taskWithAdjacent == null) { return null; } return taskWithAdjacent.getAdjacentTaskFragment().asTask(); } /** Finds the first Task parent (or itself) that has adjacent. */ @Nullable Task getTaskWithAdjacent() { if (hasAdjacentTaskFragment()) { return this; } final WindowContainer parent = getParent(); if (parent == null || parent.asTask() == null) { return null; } return parent.asTask().getTaskWithAdjacent(); } /** Returns true if this or its parent has adjacent Task. */ boolean hasAdjacentTask() { return getTaskWithAdjacent() != null; } return parent.asTask().getAdjacentTask(); /** * Finds the first Task parent (or itself) that has adjacent. Runs callback on all the adjacent * Tasks. The invoke order is not guaranteed. */ void forOtherAdjacentTasks(@NonNull Consumer<Task> callback) { if (!Flags.allowMultipleAdjacentTaskFragments()) { throw new IllegalStateException("allowMultipleAdjacentTaskFragments is not enabled. " + "Use #getAdjacentTask instead"); } final Task taskWithAdjacent = getTaskWithAdjacent(); if (taskWithAdjacent == null) { return; } final AdjacentSet adjacentTasks = taskWithAdjacent.getAdjacentTaskFragments(); adjacentTasks.forAllTaskFragments(tf -> { // We don't support Task adjacent to non-Task TaskFragment. callback.accept(tf.asTask()); }, taskWithAdjacent /* exclude */); } /** * Finds the first Task parent (or itself) that has adjacent. Runs callback on all the adjacent * Tasks. Returns early if callback returns true on any of them. The invoke order is not * guaranteed. */ boolean forOtherAdjacentTasks(@NonNull Predicate<Task> callback) { if (!Flags.allowMultipleAdjacentTaskFragments()) { throw new IllegalStateException("allowMultipleAdjacentTaskFragments is not enabled. " + "Use getAdjacentTask instead"); } final Task taskWithAdjacent = getTaskWithAdjacent(); if (taskWithAdjacent == null) { return false; } final AdjacentSet adjacentTasks = taskWithAdjacent.getAdjacentTaskFragments(); return adjacentTasks.forAllTaskFragments(tf -> { // We don't support Task adjacent to non-Task TaskFragment. return callback.test(tf.asTask()); }, taskWithAdjacent /* exclude */); } // TODO(task-merge): Figure out what's the right thing to do for places that used it. Loading Loading @@ -2907,7 +2966,7 @@ class Task extends TaskFragment { Rect outSurfaceInsets) { // If this task has its adjacent task, it means they should animate together. Use display // bounds for them could move same as full screen task. if (getAdjacentTask() != null) { if (hasAdjacentTask()) { super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); return; } Loading Loading
services/core/java/com/android/server/wm/ActivityMetricsLogger.java +13 −3 Original line number Diff line number Diff line Loading @@ -110,6 +110,7 @@ import com.android.server.FgThread; import com.android.server.LocalServices; import com.android.server.apphibernation.AppHibernationManagerInternal; import com.android.server.apphibernation.AppHibernationService; import com.android.window.flags.Flags; import java.util.ArrayList; import java.util.concurrent.TimeUnit; Loading Loading @@ -778,11 +779,12 @@ class ActivityMetricsLogger { */ private void updateSplitPairLaunches(@NonNull TransitionInfo info) { final Task launchedActivityTask = info.mLastLaunchedActivity.getTask(); final Task adjacentToLaunchedTask = launchedActivityTask.getAdjacentTask(); if (adjacentToLaunchedTask == null) { final Task launchedSplitRootTask = launchedActivityTask.getTaskWithAdjacent(); if (launchedSplitRootTask == null) { // Not a part of a split pair return; } for (int i = mTransitionInfoList.size() - 1; i >= 0; i--) { final TransitionInfo otherInfo = mTransitionInfoList.get(i); if (otherInfo == info) { Loading @@ -790,7 +792,15 @@ class ActivityMetricsLogger { } final Task otherTask = otherInfo.mLastLaunchedActivity.getTask(); // The adjacent task is the split root in which activities are started if (otherTask.isDescendantOf(adjacentToLaunchedTask)) { final boolean isDescendantOfAdjacent; if (Flags.allowMultipleAdjacentTaskFragments()) { isDescendantOfAdjacent = launchedSplitRootTask.forOtherAdjacentTasks( otherTask::isDescendantOf); } else { isDescendantOfAdjacent = otherTask.isDescendantOf( launchedSplitRootTask.getAdjacentTask()); } if (isDescendantOfAdjacent) { if (DEBUG_METRICS) { Slog.i(TAG, "Found adjacent tasks t1=" + launchedActivityTask.mTaskId + " t2=" + otherTask.mTaskId); Loading
services/core/java/com/android/server/wm/AppTransitionController.java +1 −2 Original line number Diff line number Diff line Loading @@ -996,8 +996,7 @@ public class AppTransitionController { // If the current window container is a task with adjacent task set, the both // adjacent tasks will be opened or closed together. To get their opening or // closing animation target independently, skip promoting their animation targets. if (current.asTask() != null && current.asTask().getAdjacentTask() != null) { if (current.asTask() != null && current.asTask().hasAdjacentTask()) { canPromote = false; } Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +1 −1 Original line number Diff line number Diff line Loading @@ -2485,7 +2485,7 @@ public class DisplayPolicy { final TaskDisplayArea defaultTaskDisplayArea = mDisplayContent.getDefaultTaskDisplayArea(); final boolean adjacentTasksVisible = defaultTaskDisplayArea.getRootTask(task -> task.isVisible() && task.getTopLeafTask().getAdjacentTask() != null) && task.getTopLeafTask().hasAdjacentTask()) != null; final Task topFreeformTask = defaultTaskDisplayArea .getTopRootTaskInWindowingMode(WINDOWING_MODE_FREEFORM); Loading
services/core/java/com/android/server/wm/RootWindowContainer.java +18 −6 Original line number Diff line number Diff line Loading @@ -1796,12 +1796,24 @@ class RootWindowContainer extends WindowContainer<DisplayContent> activityAssistInfos.clear(); activityAssistInfos.add(new ActivityAssistInfo(top)); // Check if the activity on the split screen. if (Flags.allowMultipleAdjacentTaskFragments()) { top.getTask().forOtherAdjacentTasks(task -> { final ActivityRecord adjacentActivityRecord = task.getTopNonFinishingActivity(); if (adjacentActivityRecord != null) { activityAssistInfos.add( new ActivityAssistInfo(adjacentActivityRecord)); } }); } else { final Task adjacentTask = top.getTask().getAdjacentTask(); if (adjacentTask != null) { final ActivityRecord adjacentActivityRecord = adjacentTask.getTopNonFinishingActivity(); if (adjacentActivityRecord != null) { activityAssistInfos.add(new ActivityAssistInfo(adjacentActivityRecord)); activityAssistInfos.add( new ActivityAssistInfo(adjacentActivityRecord)); } } } if (rootTask == topFocusedRootTask) { Loading
services/core/java/com/android/server/wm/Task.java +65 −6 Original line number Diff line number Diff line Loading @@ -2500,20 +2500,79 @@ class Task extends TaskFragment { return parentTask == null ? null : parentTask.getCreatedByOrganizerTask(); } /** @return the first adjacent task of this task or its parent. */ /** @deprecated b/373709676 replace with {@link #forOtherAdjacentTasks(Consumer)} ()}. */ @Deprecated @Nullable Task getAdjacentTask() { final TaskFragment adjacentTaskFragment = getAdjacentTaskFragment(); if (adjacentTaskFragment != null && adjacentTaskFragment.asTask() != null) { return adjacentTaskFragment.asTask(); if (Flags.allowMultipleAdjacentTaskFragments()) { throw new IllegalStateException("allowMultipleAdjacentTaskFragments is enabled. " + "Use #forOtherAdjacentTasks instead"); } final Task taskWithAdjacent = getTaskWithAdjacent(); if (taskWithAdjacent == null) { return null; } return taskWithAdjacent.getAdjacentTaskFragment().asTask(); } /** Finds the first Task parent (or itself) that has adjacent. */ @Nullable Task getTaskWithAdjacent() { if (hasAdjacentTaskFragment()) { return this; } final WindowContainer parent = getParent(); if (parent == null || parent.asTask() == null) { return null; } return parent.asTask().getTaskWithAdjacent(); } /** Returns true if this or its parent has adjacent Task. */ boolean hasAdjacentTask() { return getTaskWithAdjacent() != null; } return parent.asTask().getAdjacentTask(); /** * Finds the first Task parent (or itself) that has adjacent. Runs callback on all the adjacent * Tasks. The invoke order is not guaranteed. */ void forOtherAdjacentTasks(@NonNull Consumer<Task> callback) { if (!Flags.allowMultipleAdjacentTaskFragments()) { throw new IllegalStateException("allowMultipleAdjacentTaskFragments is not enabled. " + "Use #getAdjacentTask instead"); } final Task taskWithAdjacent = getTaskWithAdjacent(); if (taskWithAdjacent == null) { return; } final AdjacentSet adjacentTasks = taskWithAdjacent.getAdjacentTaskFragments(); adjacentTasks.forAllTaskFragments(tf -> { // We don't support Task adjacent to non-Task TaskFragment. callback.accept(tf.asTask()); }, taskWithAdjacent /* exclude */); } /** * Finds the first Task parent (or itself) that has adjacent. Runs callback on all the adjacent * Tasks. Returns early if callback returns true on any of them. The invoke order is not * guaranteed. */ boolean forOtherAdjacentTasks(@NonNull Predicate<Task> callback) { if (!Flags.allowMultipleAdjacentTaskFragments()) { throw new IllegalStateException("allowMultipleAdjacentTaskFragments is not enabled. " + "Use getAdjacentTask instead"); } final Task taskWithAdjacent = getTaskWithAdjacent(); if (taskWithAdjacent == null) { return false; } final AdjacentSet adjacentTasks = taskWithAdjacent.getAdjacentTaskFragments(); return adjacentTasks.forAllTaskFragments(tf -> { // We don't support Task adjacent to non-Task TaskFragment. return callback.test(tf.asTask()); }, taskWithAdjacent /* exclude */); } // TODO(task-merge): Figure out what's the right thing to do for places that used it. Loading Loading @@ -2907,7 +2966,7 @@ class Task extends TaskFragment { Rect outSurfaceInsets) { // If this task has its adjacent task, it means they should animate together. Use display // bounds for them could move same as full screen task. if (getAdjacentTask() != null) { if (hasAdjacentTask()) { super.getAnimationFrames(outFrame, outInsets, outStableInsets, outSurfaceInsets); return; } Loading