From e82c67504dfc5bd8415f1cb530dfe6c0db1be6ad Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Tue, 3 Aug 2021 14:29:35 -0700 Subject: [PATCH] Delete dependent TaskFragments in the same transaction When finishing the last activity in a container that has dependent containers, make sure to delete those in addition to just finishing activities. This will ensure that containers with activities from different apps will be properly cleaned up. Bug: 195108809 Test: Launch a container to side with 'finishSecondaryWithPrimary' configuration, finish the primary container with swipe from side. Test: Do the above for activities in different apps. Change-Id: I746055fd02894d8221cace10d556992e2dba31b5 --- .../extensions/organizer/SplitController.java | 19 +++++++------------ .../extensions/organizer/SplitPresenter.java | 8 +++++--- .../organizer/TaskFragmentContainer.java | 12 ++++++++++-- 3 files changed, 22 insertions(+), 17 deletions(-) diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java index a1ebb59c38220..912c61b0c8b46 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java @@ -128,7 +128,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // Check if there are no running activities - consider the container empty if there are no // non-finishing activities left. if (!taskFragmentInfo.hasRunningActivity()) { - cleanupContainer(container, true /* shouldFinishDependent */); + mPresenter.cleanupContainer(container, true /* shouldFinishDependent */); updateCallbackIfNecessary(); } } @@ -140,7 +140,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } - cleanupContainer(container, true /* shouldFinishDependent */); + mPresenter.cleanupContainer(container, true /* shouldFinishDependent */); updateCallbackIfNecessary(); } @@ -307,13 +307,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mSplitContainers.add(splitContainer); } - void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) { - if (container.isFinished()) { - return; - } - - container.finish(shouldFinishDependent); - + /** + * Removes the container from bookkeeping records. + */ + void removeContainer(@NonNull TaskFragmentContainer container) { // Remove all split containers that included this one mContainers.remove(container); List containersToRemove = new ArrayList<>(); @@ -324,8 +321,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } mSplitContainers.removeAll(containersToRemove); - - mPresenter.deleteContainer(container); } /** @@ -462,7 +457,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return false; } - cleanupContainer(splitContainer.getSecondaryContainer(), + mPresenter.cleanupContainer(splitContainer.getSecondaryContainer(), false /* shouldFinishDependent */); return true; } diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java index d8b1d2a623833..0f356291f50e5 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java @@ -68,11 +68,13 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { } /** - * Deletes the provided container and updates the presentation if necessary. + * Deletes the specified container and all other associated and dependent containers in the same + * transaction. */ - void deleteContainer(TaskFragmentContainer container) { + void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) { final WindowContainerTransaction wct = new WindowContainerTransaction(); - deleteTaskFragment(wct, container.getTaskFragmentToken()); + + container.finish(shouldFinishDependent, this, wct, mController); final TaskFragmentContainer newTopContainer = mController.getTopActiveContainer(); if (newTopContainer != null) { diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java index f47dc245d2b07..a4f5c75276f5e 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/TaskFragmentContainer.java @@ -24,6 +24,7 @@ import android.graphics.Rect; import android.os.Binder; import android.os.IBinder; import android.window.TaskFragmentInfo; +import android.window.WindowContainerTransaction; import java.util.ArrayList; import java.util.List; @@ -179,7 +180,8 @@ class TaskFragmentContainer { * Removes all activities that belong to this process and finishes other containers/activities * configured to finish together. */ - void finish(boolean shouldFinishDependent) { + void finish(boolean shouldFinishDependent, @NonNull SplitPresenter presenter, + @NonNull WindowContainerTransaction wct, @NonNull SplitController controller) { if (mIsFinished) { return; } @@ -190,13 +192,19 @@ class TaskFragmentContainer { activity.finish(); } + // Cleanup the visuals + presenter.deleteTaskFragment(wct, getTaskFragmentToken()); + // Cleanup the records + controller.removeContainer(this); + if (!shouldFinishDependent) { return; } // Finish dependent containers for (TaskFragmentContainer container : mContainersToFinishOnExit) { - container.finish(true /* shouldFinishDependent */); + container.finish(true /* shouldFinishDependent */, presenter, + wct, controller); } mContainersToFinishOnExit.clear();