summaryrefslogtreecommitdiff
path: root/libs
diff options
context:
space:
mode:
author Chris Li <lihongyu@google.com> 2022-02-15 09:41:12 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2022-02-15 09:41:12 +0000
commitfddf0a84f0a90bed391723477ade5326567d8718 (patch)
tree48ece30ed54331b27b0a670ad9b75b35aefc3c6c /libs
parentc212c6293b9fa9996aad850b8398471d68a4e1ce (diff)
parent449fceaa1c05726ec0977c49e864147c4bab227b (diff)
Merge "ActivityEmbedding: launch into the same side container"
Diffstat (limited to 'libs')
-rw-r--r--libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java82
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 d35ecbde529b..0bf078d76ada 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
@@ -928,4 +965,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();
+ }
}