Merge "ActivityEmbedding: launch into the same side container" into sc-v2-dev

This commit is contained in:
Chris Li
2022-03-17 10:33:42 +00:00
committed by Android (Google) Code Review

View File

@@ -806,8 +806,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
if (shouldExpand(null, intent, getSplitRules())) { if (shouldExpand(null, intent, getSplitRules())) {
setLaunchingInExpandedContainer(launchingActivity, options); setLaunchingInExpandedContainer(launchingActivity, options);
} else if (!setLaunchingToSideContainer(launchingActivity, intent, options)) { } else if (!splitWithLaunchingActivity(launchingActivity, intent, options)) {
setLaunchingInSameContainer(launchingActivity, intent, options); setLaunchingInSameSideContainer(launchingActivity, intent, options);
} }
return super.onStartActivity(who, intent, options); return super.onStartActivity(who, intent, options);
@@ -826,9 +826,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
/** /**
* Returns {@code true} if the activity that is going to be started via the * 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 * {@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) { Bundle options) {
final SplitPairRule splitPairRule = getSplitRule(launchingActivity, intent, final SplitPairRule splitPairRule = getSplitRule(launchingActivity, intent,
getSplitRules()); getSplitRules());
@@ -836,9 +836,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return false; return false;
} }
// Create a new split with an empty side container // Check if there is any existing side container to launch into.
final TaskFragmentContainer secondaryContainer = mPresenter TaskFragmentContainer secondaryContainer = findSideContainerForNewLaunch(
.createNewSplitWithEmptySideContainer(launchingActivity, splitPairRule); 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 // Amend the request to let the WM know that the activity should be placed in the
// dedicated container. // dedicated container.
@@ -847,13 +852,40 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return true; return true;
} }
/**
* 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 * 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 * 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}. * container of the {@code launchingActivity}.
*/ */
private void setLaunchingInSameContainer(Activity launchingActivity, Intent intent, private void setLaunchingInSameSideContainer(Activity launchingActivity, Intent intent,
Bundle options) { Bundle options) {
final TaskFragmentContainer launchingContainer = getContainerWithActivity( final TaskFragmentContainer launchingContainer = getContainerWithActivity(
launchingActivity.getActivityToken()); launchingActivity.getActivityToken());
@@ -884,6 +916,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
return; 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 // 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 // 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 // into a new Task, or new Task will be escaped from the current host Task and be
@@ -900,4 +937,31 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
public boolean isActivityEmbedded(@NonNull Activity activity) { public boolean isActivityEmbedded(@NonNull Activity activity) {
return mPresenter.isActivityEmbedded(activity.getActivityToken()); 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();
}
} }