From f45a4644090317132215b62d0d7bf0a1971f7c57 Mon Sep 17 00:00:00 2001 From: Andrii Kulian Date: Tue, 3 Aug 2021 19:24:58 -0700 Subject: [PATCH] Finish existing secondary containers when starting to side When a new activity is started to side of a primary container in an existing split, finish the old secondary container by default to replace it instead of putting on top. Note that this rule only applies for new activity launches to side via rules or dedicated APIs. If an activity is started regularly, it would normally be placed in the existing secondary container on top, not creating a new one and replacing. Bug: 194996352 Test: Start to side from the primary container several times, observe secondary container being replaced with subsequent launches. Change-Id: If4439368a669c6252c97471f0e77286357285c9d --- .../JetpackTaskFragmentOrganizer.java | 10 +++---- .../extensions/organizer/SplitController.java | 28 +++++++++++++++++-- .../extensions/organizer/SplitPresenter.java | 28 +++++++++---------- 3 files changed, 42 insertions(+), 24 deletions(-) diff --git a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java index 531df30a4e2cb..dd00189c3bf12 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/JetpackTaskFragmentOrganizer.java @@ -96,11 +96,11 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { * @param activityIntent Intent to start the secondary Activity with. * @param activityOptions ActivityOptions to start the secondary Activity with. */ - void startActivityToSide(IBinder launchingFragmentToken, Rect launchingFragmentBounds, - Activity launchingActivity, IBinder secondaryFragmentToken, - Rect secondaryFragmentBounds, Intent activityIntent, + void startActivityToSide(@NonNull WindowContainerTransaction wct, + @NonNull IBinder launchingFragmentToken, @NonNull Rect launchingFragmentBounds, + @NonNull Activity launchingActivity, @NonNull IBinder secondaryFragmentToken, + @NonNull Rect secondaryFragmentBounds, @NonNull Intent activityIntent, @Nullable Bundle activityOptions) { - final WindowContainerTransaction wct = new WindowContainerTransaction(); final IBinder ownerToken = launchingActivity.getActivityToken(); // Create or resize the launching TaskFragment. @@ -118,8 +118,6 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer { // Set adjacent to each other so that the containers below will be invisible. wct.setAdjacentTaskFragments(launchingFragmentToken, secondaryFragmentToken); - - applyTransaction(wct); } /** 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 802976fbfc6d9..5b379c0db52b8 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitController.java @@ -296,12 +296,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** - * Creates and registers a new split with the provided containers and configuration. + * Creates and registers a new split with the provided containers and configuration. Finishes + * existing secondary containers if found for the given primary container. */ - void registerSplit(@NonNull TaskFragmentContainer primaryContainer, - @NonNull Activity primaryActivity, + void registerSplit(@NonNull WindowContainerTransaction wct, + @NonNull TaskFragmentContainer primaryContainer, @NonNull Activity primaryActivity, @NonNull TaskFragmentContainer secondaryContainer, @NonNull ExtensionSplitPairRule splitPairRule) { + removeExistingSecondaryContainers(wct, primaryContainer); + SplitContainer splitContainer = new SplitContainer(primaryContainer, primaryActivity, secondaryContainer, splitPairRule); mSplitContainers.add(splitContainer); @@ -323,6 +326,25 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mSplitContainers.removeAll(containersToRemove); } + /** + * Removes a secondary container for the given primary container if an existing split is + * already registered. + */ + void removeExistingSecondaryContainers(@NonNull WindowContainerTransaction wct, + @NonNull TaskFragmentContainer primaryContainer) { + // If the primary container was already in a split - remove the secondary container that + // is now covered by the new one that replaced it. + final SplitContainer existingSplitContainer = getActiveSplitForContainer( + primaryContainer); + if (existingSplitContainer == null + || primaryContainer == existingSplitContainer.getSecondaryContainer()) { + return; + } + + existingSplitContainer.getSecondaryContainer().finish( + false /* shouldFinishDependent */, mPresenter, wct, this); + } + /** * Returns the topmost not finished container. */ 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 0f356291f50e5..47a1519ee6052 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/organizer/SplitPresenter.java @@ -108,9 +108,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { // Set adjacent to each other so that the containers below will be invisible. wct.setAdjacentTaskFragments( primaryContainer.getTaskFragmentToken(), secondaryContainer.getTaskFragmentToken()); - applyTransaction(wct); - mController.registerSplit(primaryContainer, primaryActivity, secondaryContainer, rule); + mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule); + + applyTransaction(wct); return secondaryContainer; } @@ -142,9 +143,10 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { // Set adjacent to each other so that the containers below will be invisible. wct.setAdjacentTaskFragments( primaryContainer.getTaskFragmentToken(), secondaryContainer.getTaskFragmentToken()); - applyTransaction(wct); - mController.registerSplit(primaryContainer, primaryActivity, secondaryContainer, rule); + mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule); + + applyTransaction(wct); } /** @@ -202,20 +204,16 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer { } TaskFragmentContainer secondaryContainer = mController.newContainer(null); - startActivityToSide( - primaryContainer.getTaskFragmentToken(), - primaryRectBounds, - launchingActivity, - secondaryContainer.getTaskFragmentToken(), - secondaryRectBounds, - activityIntent, - activityOptions); + final WindowContainerTransaction wct = new WindowContainerTransaction(); + mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer, + rule); + startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds, + launchingActivity, secondaryContainer.getTaskFragmentToken(), secondaryRectBounds, + activityIntent, activityOptions); + applyTransaction(wct); primaryContainer.setLastRequestedBounds(primaryRectBounds); secondaryContainer.setLastRequestedBounds(secondaryRectBounds); - - mController.registerSplit(primaryContainer, launchingActivity, secondaryContainer, - rule); } /**