diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java index fe6c7ba3b24c9..e8d6f31459b7e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -293,11 +293,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen @NonNull TaskFragmentContainer primaryContainer, @NonNull Activity primaryActivity, @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule) { + SplitContainer splitContainer = new SplitContainer(primaryContainer, primaryActivity, + secondaryContainer, splitRule); + // Remove container later to prevent pinning escaping toast showing in lock task mode. if (splitRule instanceof SplitPairRule && ((SplitPairRule) splitRule).shouldClearTop()) { removeExistingSecondaryContainers(wct, primaryContainer); } - SplitContainer splitContainer = new SplitContainer(primaryContainer, primaryActivity, - secondaryContainer, splitRule); mSplitContainers.add(splitContainer); } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java index 81be21cbd7aa9..ade573132eef7 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitPresenter.java @@ -112,8 +112,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { secondaryContainer.setLastRequestedBounds(secondaryRectBounds); // Set adjacent to each other so that the containers below will be invisible. - setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(), - secondaryContainer.getTaskFragmentToken(), rule); + setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule); mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule); @@ -149,8 +148,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { secondaryActivity, secondaryRectBounds, primaryContainer); // Set adjacent to each other so that the containers below will be invisible. - setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(), - secondaryContainer.getTaskFragmentToken(), rule); + setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule); mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule); @@ -269,8 +267,22 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { final TaskFragmentContainer secondaryContainer = splitContainer.getSecondaryContainer(); resizeTaskFragmentIfRegistered(wct, secondaryContainer, secondaryRectBounds); - setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(), - secondaryContainer.getTaskFragmentToken(), rule); + setAdjacentTaskFragments(wct, primaryContainer, secondaryContainer, rule); + } + + private void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct, + @NonNull TaskFragmentContainer primaryContainer, + @NonNull TaskFragmentContainer secondaryContainer, @NonNull SplitRule splitRule) { + final Rect parentBounds = getParentContainerBounds(primaryContainer); + // Clear adjacent TaskFragments if the container is shown in fullscreen, or the + // secondaryContainer could not be finished. + if (!shouldShowSideBySide(parentBounds, splitRule)) { + setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(), + null /* secondary */, null /* splitRule */); + } else { + setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(), + secondaryContainer.getTaskFragmentToken(), splitRule); + } } /** diff --git a/services/core/java/com/android/server/wm/LockTaskController.java b/services/core/java/com/android/server/wm/LockTaskController.java index 94a175caba225..8a2d11636fe37 100644 --- a/services/core/java/com/android/server/wm/LockTaskController.java +++ b/services/core/java/com/android/server/wm/LockTaskController.java @@ -251,15 +251,47 @@ public class LockTaskController { */ boolean activityBlockedFromFinish(ActivityRecord activity) { final Task task = activity.getTask(); - if (activity == task.getRootActivity() - && activity == task.getTopNonFinishingActivity() - && task.mLockTaskAuth != LOCK_TASK_AUTH_LAUNCHABLE_PRIV - && isRootTask(task)) { - Slog.i(TAG, "Not finishing task in lock task mode"); - showLockTaskToast(); - return true; + if (task.mLockTaskAuth == LOCK_TASK_AUTH_LAUNCHABLE_PRIV || !isRootTask(task)) { + return false; } - return false; + + final ActivityRecord taskTop = task.getTopNonFinishingActivity(); + final ActivityRecord taskRoot = task.getRootActivity(); + // If task has more than one Activity, verify if there's only adjacent TaskFragments that + // should be finish together in the Task. + if (activity != taskRoot || activity != taskTop) { + final TaskFragment taskFragment = activity.getTaskFragment(); + final TaskFragment adjacentTaskFragment = taskFragment.getAdjacentTaskFragment(); + if (taskFragment.asTask() != null + || !taskFragment.isDelayLastActivityRemoval() + || adjacentTaskFragment == null) { + // Don't block activity from finishing if the TaskFragment don't have any adjacent + // TaskFragment, or it won't finish together with its adjacent TaskFragment. + return false; + } + + final boolean hasOtherActivityInTaskFragment = + taskFragment.getActivity(a -> !a.finishing && a != activity) != null; + if (hasOtherActivityInTaskFragment) { + // Don't block activity from finishing if there's other Activity in the same + // TaskFragment. + return false; + } + + final boolean hasOtherActivityInTask = task.getActivity(a -> !a.finishing + && a != activity && a.getTaskFragment() != adjacentTaskFragment) != null; + if (hasOtherActivityInTask) { + // Do not block activity from finishing if there are another running activities + // after the current and adjacent TaskFragments are removed. Note that we don't + // check activities in adjacent TaskFragment because it will be finished together + // with TaskFragment regardless of numbers of activities. + return false; + } + } + + Slog.i(TAG, "Not finishing task in lock task mode"); + showLockTaskToast(); + return true; } /** diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index f32ab1e53318d..77d0dd85424b8 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -232,7 +232,7 @@ class TaskFragment extends WindowContainer { /** * Whether to delay the last activity of TaskFragment being immediately removed while finishing. * This should only be set on a embedded TaskFragment, where the organizer can have the - * opportunity to perform other actions or animations. + * opportunity to perform animations and finishing the adjacent TaskFragment. */ private boolean mDelayLastActivityRemoval;