diff options
| author | 2022-02-09 10:24:26 +0800 | |
|---|---|---|
| committer | 2022-02-15 15:02:59 +0800 | |
| commit | 449fceaa1c05726ec0977c49e864147c4bab227b (patch) | |
| tree | bd86776497a1ffb31eab75fe478c8d047ae47515 /libs | |
| parent | 27f6e1ca15153df645fe46e7db2d934964116a32 (diff) | |
ActivityEmbedding: launch into the same side container
When primary activity launches a new intent with a split rule with same
presentation (split ratio), we can launch the new activity to the
existing secondary container.
Bug: 216492188
Test: manual
Change-Id: Iad6d238c6dfb009402376a725136be6c6fdab98c
Diffstat (limited to 'libs')
| -rw-r--r-- | libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java | 82 |
1 files changed, 73 insertions, 9 deletions
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 8f368c2bee22..2919789217bf 100644 --- a/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +++ b/libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java @@ -833,8 +833,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen if (shouldExpand(null, intent, getSplitRules())) { setLaunchingInExpandedContainer(launchingActivity, options); - } else if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { - setLaunchingInSameContainer(launchingActivity, intent, options); + } else if (!splitWithLaunchingActivity(launchingActivity, intent, options)) { + setLaunchingInSameSideContainer(launchingActivity, intent, options); } return super.onStartActivity(who, intent, options); @@ -853,9 +853,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen /** * Returns {@code true} if the activity that is going to be started via the * {@code intent} should be paired with the {@code launchingActivity} and is set to be - * launched in an empty side container. + * launched in the side container. */ - private boolean setLaunchingToSideContainer(Activity launchingActivity, Intent intent, + private boolean splitWithLaunchingActivity(Activity launchingActivity, Intent intent, Bundle options) { final SplitPairRule splitPairRule = getSplitRule(launchingActivity, intent, getSplitRules()); @@ -863,9 +863,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return false; } - // Create a new split with an empty side container - final TaskFragmentContainer secondaryContainer = mPresenter - .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); + // Check if there is any existing side container to launch into. + TaskFragmentContainer secondaryContainer = findSideContainerForNewLaunch( + launchingActivity, splitPairRule); + if (secondaryContainer == null) { + // Create a new split with an empty side container. + secondaryContainer = mPresenter + .createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); + } // Amend the request to let the WM know that the activity should be placed in the // dedicated container. @@ -875,12 +880,39 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } /** + * Finds if there is an existing split side {@link TaskFragmentContainer} that can be used + * for the new rule. + */ + @Nullable + private TaskFragmentContainer findSideContainerForNewLaunch(Activity launchingActivity, + SplitPairRule splitPairRule) { + final TaskFragmentContainer launchingContainer = getContainerWithActivity( + launchingActivity.getActivityToken()); + if (launchingContainer == null) { + return null; + } + + // We only check if the launching activity is the primary of the split. We will check + // if the launching activity is the secondary in #setLaunchingInSameSideContainer. + final SplitContainer splitContainer = getActiveSplitForContainer(launchingContainer); + if (splitContainer == null + || splitContainer.getPrimaryContainer() != launchingContainer) { + return null; + } + + if (canReuseContainer(splitPairRule, splitContainer.getSplitRule())) { + return splitContainer.getSecondaryContainer(); + } + return null; + } + + /** * Checks if the activity that is going to be started via the {@code intent} should be * paired with the existing top activity which is currently paired with the - * {@code launchingActivity}. If so, set the activity to be launched in the same + * {@code launchingActivity}. If so, set the activity to be launched in the same side * container of the {@code launchingActivity}. */ - private void setLaunchingInSameContainer(Activity launchingActivity, Intent intent, + private void setLaunchingInSameSideContainer(Activity launchingActivity, Intent intent, Bundle options) { final TaskFragmentContainer launchingContainer = getContainerWithActivity( launchingActivity.getActivityToken()); @@ -911,6 +943,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } + // Can only launch in the same container if the rules share the same presentation. + if (!canReuseContainer(splitPairRule, splitContainer.getSplitRule())) { + return; + } + // Amend the request to let the WM know that the activity should be placed in the // dedicated container. This is necessary for the case that the activity is started // into a new Task, or new Task will be escaped from the current host Task and be @@ -927,4 +964,31 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen public boolean isActivityEmbedded(@NonNull Activity activity) { return mPresenter.isActivityEmbedded(activity.getActivityToken()); } + + /** + * If the two rules have the same presentation, we can reuse the same {@link SplitContainer} if + * there is any. + */ + private static boolean canReuseContainer(SplitRule rule1, SplitRule rule2) { + if (!isContainerReusableRule(rule1) || !isContainerReusableRule(rule2)) { + return false; + } + return rule1.getSplitRatio() == rule2.getSplitRatio() + && rule1.getLayoutDirection() == rule2.getLayoutDirection(); + } + + /** + * Whether it is ok for other rule to reuse the {@link TaskFragmentContainer} of the given + * rule. + */ + private static boolean isContainerReusableRule(SplitRule rule) { + // We don't expect to reuse the placeholder rule. + if (!(rule instanceof SplitPairRule)) { + return false; + } + final SplitPairRule pairRule = (SplitPairRule) rule; + + // Not reuse if it needs to destroy the existing. + return !pairRule.shouldClearTop(); + } } |