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
(cherry picked from commit 449fceaa1c)
This commit is contained in:
@@ -806,8 +806,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);
|
||||
@@ -826,9 +826,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());
|
||||
@@ -836,9 +836,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.
|
||||
@@ -847,13 +852,40 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
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
|
||||
* 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());
|
||||
@@ -884,6 +916,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
|
||||
@@ -900,4 +937,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();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user