Merge "Avoid duplicated WindowContainerTransaction for TaskFragment"
This commit is contained in:
@@ -154,7 +154,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
activityOptions);
|
||||
|
||||
// Set adjacent to each other so that the containers below will be invisible.
|
||||
setAdjacentTaskFragments(wct, launchingFragmentToken, secondaryFragmentToken, rule);
|
||||
setAdjacentTaskFragmentsWithRule(wct, launchingFragmentToken, secondaryFragmentToken, rule);
|
||||
setCompanionTaskFragment(wct, launchingFragmentToken, secondaryFragmentToken, rule,
|
||||
false /* isStacked */);
|
||||
}
|
||||
@@ -167,7 +167,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
void expandTaskFragment(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder fragmentToken) {
|
||||
resizeTaskFragment(wct, fragmentToken, new Rect());
|
||||
setAdjacentTaskFragments(wct, fragmentToken, null /* secondary */, null /* splitRule */);
|
||||
clearAdjacentTaskFragments(wct, fragmentToken);
|
||||
updateWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
|
||||
updateAnimationParams(wct, fragmentToken, TaskFragmentAnimationParams.DEFAULT);
|
||||
}
|
||||
@@ -238,26 +238,37 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
wct.reparentActivityToTaskFragment(fragmentToken, reparentActivityToken);
|
||||
}
|
||||
|
||||
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder primary, @Nullable IBinder secondary, @Nullable SplitRule splitRule) {
|
||||
if (secondary == null) {
|
||||
wct.clearAdjacentTaskFragments(primary);
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the two given TaskFragments as adjacent to each other with respecting the given
|
||||
* {@link SplitRule} for {@link WindowContainerTransaction.TaskFragmentAdjacentParams}.
|
||||
*/
|
||||
void setAdjacentTaskFragmentsWithRule(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder primary, @NonNull IBinder secondary, @NonNull SplitRule splitRule) {
|
||||
WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams = null;
|
||||
final boolean finishSecondaryWithPrimary =
|
||||
splitRule != null && SplitContainer.shouldFinishSecondaryWithPrimary(splitRule);
|
||||
SplitContainer.shouldFinishSecondaryWithPrimary(splitRule);
|
||||
final boolean finishPrimaryWithSecondary =
|
||||
splitRule != null && SplitContainer.shouldFinishPrimaryWithSecondary(splitRule);
|
||||
SplitContainer.shouldFinishPrimaryWithSecondary(splitRule);
|
||||
if (finishSecondaryWithPrimary || finishPrimaryWithSecondary) {
|
||||
adjacentParams = new WindowContainerTransaction.TaskFragmentAdjacentParams();
|
||||
adjacentParams.setShouldDelayPrimaryLastActivityRemoval(finishSecondaryWithPrimary);
|
||||
adjacentParams.setShouldDelaySecondaryLastActivityRemoval(finishPrimaryWithSecondary);
|
||||
}
|
||||
setAdjacentTaskFragments(wct, primary, secondary, adjacentParams);
|
||||
}
|
||||
|
||||
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder primary, @NonNull IBinder secondary,
|
||||
@Nullable WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams) {
|
||||
wct.setAdjacentTaskFragments(primary, secondary, adjacentParams);
|
||||
}
|
||||
|
||||
void clearAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder fragmentToken) {
|
||||
// Clear primary will also clear secondary.
|
||||
wct.clearAdjacentTaskFragments(fragmentToken);
|
||||
}
|
||||
|
||||
void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder primary, @NonNull IBinder secondary, @NonNull SplitRule splitRule,
|
||||
boolean isStacked) {
|
||||
@@ -268,7 +279,7 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
} else {
|
||||
finishPrimaryWithSecondary = shouldFinishPrimaryWithSecondary(splitRule);
|
||||
}
|
||||
wct.setCompanionTaskFragment(primary, finishPrimaryWithSecondary ? secondary : null);
|
||||
setCompanionTaskFragment(wct, primary, finishPrimaryWithSecondary ? secondary : null);
|
||||
|
||||
final boolean finishSecondaryWithPrimary;
|
||||
if (isStacked) {
|
||||
@@ -277,7 +288,12 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
} else {
|
||||
finishSecondaryWithPrimary = shouldFinishSecondaryWithPrimary(splitRule);
|
||||
}
|
||||
wct.setCompanionTaskFragment(secondary, finishSecondaryWithPrimary ? primary : null);
|
||||
setCompanionTaskFragment(wct, secondary, finishSecondaryWithPrimary ? primary : null);
|
||||
}
|
||||
|
||||
void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder primary,
|
||||
@Nullable IBinder secondary) {
|
||||
wct.setCompanionTaskFragment(primary, secondary);
|
||||
}
|
||||
|
||||
void resizeTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
||||
|
||||
@@ -525,6 +525,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// All overrides will be cleanup.
|
||||
container.setLastRequestedBounds(null /* bounds */);
|
||||
container.setLastRequestedWindowingMode(WINDOWING_MODE_UNDEFINED);
|
||||
container.clearLastAdjacentTaskFragment();
|
||||
container.setLastCompanionTaskFragment(null /* fragmentToken */);
|
||||
container.setLastRequestAnimationParams(TaskFragmentAnimationParams.DEFAULT);
|
||||
cleanupForEnterPip(wct, container);
|
||||
} else if (wasInPip) {
|
||||
// Exit PIP.
|
||||
|
||||
@@ -385,10 +385,9 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
// secondaryContainer could not be finished.
|
||||
boolean isStacked = !shouldShowSplit(splitAttributes);
|
||||
if (isStacked) {
|
||||
setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
|
||||
null /* secondary */, null /* splitRule */);
|
||||
clearAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken());
|
||||
} else {
|
||||
setAdjacentTaskFragments(wct, primaryContainer.getTaskFragmentToken(),
|
||||
setAdjacentTaskFragmentsWithRule(wct, primaryContainer.getTaskFragmentToken(),
|
||||
secondaryContainer.getTaskFragmentToken(), splitRule);
|
||||
}
|
||||
setCompanionTaskFragment(wct, primaryContainer.getTaskFragmentToken(),
|
||||
@@ -425,7 +424,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
fragmentOptions.getFragmentToken());
|
||||
if (container == null) {
|
||||
throw new IllegalStateException(
|
||||
"Creating a task fragment that is not registered with controller.");
|
||||
"Creating a TaskFragment that is not registered with controller.");
|
||||
}
|
||||
|
||||
container.setLastRequestedBounds(fragmentOptions.getInitialRelativeBounds());
|
||||
@@ -439,7 +438,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
TaskFragmentContainer container = mController.getContainer(fragmentToken);
|
||||
if (container == null) {
|
||||
throw new IllegalStateException(
|
||||
"Resizing a task fragment that is not registered with controller.");
|
||||
"Resizing a TaskFragment that is not registered with controller.");
|
||||
}
|
||||
|
||||
if (container.areLastRequestedBoundsEqual(relBounds)) {
|
||||
@@ -456,7 +455,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
@NonNull IBinder fragmentToken, @WindowingMode int windowingMode) {
|
||||
final TaskFragmentContainer container = mController.getContainer(fragmentToken);
|
||||
if (container == null) {
|
||||
throw new IllegalStateException("Setting windowing mode for a task fragment that is"
|
||||
throw new IllegalStateException("Setting windowing mode for a TaskFragment that is"
|
||||
+ " not registered with controller.");
|
||||
}
|
||||
|
||||
@@ -474,7 +473,7 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
@NonNull IBinder fragmentToken, @NonNull TaskFragmentAnimationParams animationParams) {
|
||||
final TaskFragmentContainer container = mController.getContainer(fragmentToken);
|
||||
if (container == null) {
|
||||
throw new IllegalStateException("Setting animation params for a task fragment that is"
|
||||
throw new IllegalStateException("Setting animation params for a TaskFragment that is"
|
||||
+ " not registered with controller.");
|
||||
}
|
||||
|
||||
@@ -487,6 +486,64 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
super.updateAnimationParams(wct, fragmentToken, animationParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder primary, @NonNull IBinder secondary,
|
||||
@Nullable WindowContainerTransaction.TaskFragmentAdjacentParams adjacentParams) {
|
||||
final TaskFragmentContainer primaryContainer = mController.getContainer(primary);
|
||||
final TaskFragmentContainer secondaryContainer = mController.getContainer(secondary);
|
||||
if (primaryContainer == null || secondaryContainer == null) {
|
||||
throw new IllegalStateException("setAdjacentTaskFragments on TaskFragment that is"
|
||||
+ " not registered with controller.");
|
||||
}
|
||||
|
||||
if (primaryContainer.isLastAdjacentTaskFragmentEqual(secondary, adjacentParams)
|
||||
&& secondaryContainer.isLastAdjacentTaskFragmentEqual(primary, adjacentParams)) {
|
||||
// Return early if the same adjacent TaskFragments were already requested
|
||||
return;
|
||||
}
|
||||
|
||||
primaryContainer.setLastAdjacentTaskFragment(secondary, adjacentParams);
|
||||
secondaryContainer.setLastAdjacentTaskFragment(primary, adjacentParams);
|
||||
super.setAdjacentTaskFragments(wct, primary, secondary, adjacentParams);
|
||||
}
|
||||
|
||||
@Override
|
||||
void clearAdjacentTaskFragments(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull IBinder fragmentToken) {
|
||||
final TaskFragmentContainer container = mController.getContainer(fragmentToken);
|
||||
if (container == null) {
|
||||
throw new IllegalStateException("clearAdjacentTaskFragments on TaskFragment that is"
|
||||
+ " not registered with controller.");
|
||||
}
|
||||
|
||||
if (container.isLastAdjacentTaskFragmentEqual(null /* fragmentToken*/, null /* params */)) {
|
||||
// Return early if no adjacent TaskFragment was yet requested
|
||||
return;
|
||||
}
|
||||
|
||||
container.clearLastAdjacentTaskFragment();
|
||||
super.clearAdjacentTaskFragments(wct, fragmentToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
void setCompanionTaskFragment(@NonNull WindowContainerTransaction wct, @NonNull IBinder primary,
|
||||
@Nullable IBinder secondary) {
|
||||
final TaskFragmentContainer container = mController.getContainer(primary);
|
||||
if (container == null) {
|
||||
throw new IllegalStateException("setCompanionTaskFragment on TaskFragment that is"
|
||||
+ " not registered with controller.");
|
||||
}
|
||||
|
||||
if (container.isLastCompanionTaskFragmentEqual(secondary)) {
|
||||
// Return early if the same companion TaskFragment was already requested
|
||||
return;
|
||||
}
|
||||
|
||||
container.setLastCompanionTaskFragment(secondary);
|
||||
super.setCompanionTaskFragment(wct, primary, secondary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands the split container if the current split bounds are smaller than the Activity or
|
||||
* Intent that is added to the container.
|
||||
|
||||
@@ -40,6 +40,7 @@ import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Client-side container for a stack of activities. Corresponds to an instance of TaskFragment
|
||||
@@ -116,6 +117,27 @@ class TaskFragmentContainer {
|
||||
@NonNull
|
||||
private TaskFragmentAnimationParams mLastAnimationParams = TaskFragmentAnimationParams.DEFAULT;
|
||||
|
||||
/**
|
||||
* TaskFragment token that was requested last via
|
||||
* {@link android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS}.
|
||||
*/
|
||||
@Nullable
|
||||
private IBinder mLastAdjacentTaskFragment;
|
||||
|
||||
/**
|
||||
* {@link WindowContainerTransaction.TaskFragmentAdjacentParams} token that was requested last
|
||||
* via {@link android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS}.
|
||||
*/
|
||||
@Nullable
|
||||
private WindowContainerTransaction.TaskFragmentAdjacentParams mLastAdjacentParams;
|
||||
|
||||
/**
|
||||
* TaskFragment token that was requested last via
|
||||
* {@link android.window.TaskFragmentOperation#OP_TYPE_SET_COMPANION_TASK_FRAGMENT}.
|
||||
*/
|
||||
@Nullable
|
||||
private IBinder mLastCompanionTaskFragment;
|
||||
|
||||
/**
|
||||
* When the TaskFragment has appeared in server, but is empty, we should remove the TaskFragment
|
||||
* if it is still empty after the timeout.
|
||||
@@ -591,6 +613,7 @@ class TaskFragmentContainer {
|
||||
/**
|
||||
* Checks if last requested bounds are equal to the provided value.
|
||||
* The requested bounds are relative bounds in parent coordinate.
|
||||
* @see WindowContainerTransaction#setRelativeBounds
|
||||
*/
|
||||
boolean areLastRequestedBoundsEqual(@Nullable Rect relBounds) {
|
||||
return (relBounds == null && mLastRequestedBounds.isEmpty())
|
||||
@@ -600,6 +623,7 @@ class TaskFragmentContainer {
|
||||
/**
|
||||
* Updates the last requested bounds.
|
||||
* The requested bounds are relative bounds in parent coordinate.
|
||||
* @see WindowContainerTransaction#setRelativeBounds
|
||||
*/
|
||||
void setLastRequestedBounds(@Nullable Rect relBounds) {
|
||||
if (relBounds == null) {
|
||||
@@ -609,13 +633,9 @@ class TaskFragmentContainer {
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
Rect getLastRequestedBounds() {
|
||||
return mLastRequestedBounds;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if last requested windowing mode is equal to the provided value.
|
||||
* @see WindowContainerTransaction#setWindowingMode
|
||||
*/
|
||||
boolean isLastRequestedWindowingModeEqual(@WindowingMode int windowingMode) {
|
||||
return mLastRequestedWindowingMode == windowingMode;
|
||||
@@ -623,6 +643,7 @@ class TaskFragmentContainer {
|
||||
|
||||
/**
|
||||
* Updates the last requested windowing mode.
|
||||
* @see WindowContainerTransaction#setWindowingMode
|
||||
*/
|
||||
void setLastRequestedWindowingMode(@WindowingMode int windowingModes) {
|
||||
mLastRequestedWindowingMode = windowingModes;
|
||||
@@ -630,6 +651,7 @@ class TaskFragmentContainer {
|
||||
|
||||
/**
|
||||
* Checks if last requested {@link TaskFragmentAnimationParams} are equal to the provided value.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_SET_ANIMATION_PARAMS
|
||||
*/
|
||||
boolean areLastRequestedAnimationParamsEqual(
|
||||
@NonNull TaskFragmentAnimationParams animationParams) {
|
||||
@@ -638,11 +660,66 @@ class TaskFragmentContainer {
|
||||
|
||||
/**
|
||||
* Updates the last requested {@link TaskFragmentAnimationParams}.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_SET_ANIMATION_PARAMS
|
||||
*/
|
||||
void setLastRequestAnimationParams(@NonNull TaskFragmentAnimationParams animationParams) {
|
||||
mLastAnimationParams = animationParams;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if last requested adjacent TaskFragment token and params are equal to the provided
|
||||
* values.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS
|
||||
*/
|
||||
boolean isLastAdjacentTaskFragmentEqual(@Nullable IBinder fragmentToken,
|
||||
@Nullable WindowContainerTransaction.TaskFragmentAdjacentParams params) {
|
||||
return Objects.equals(mLastAdjacentTaskFragment, fragmentToken)
|
||||
&& Objects.equals(mLastAdjacentParams, params);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last requested adjacent TaskFragment token and params.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_SET_ADJACENT_TASK_FRAGMENTS
|
||||
*/
|
||||
void setLastAdjacentTaskFragment(@NonNull IBinder fragmentToken,
|
||||
@NonNull WindowContainerTransaction.TaskFragmentAdjacentParams params) {
|
||||
mLastAdjacentTaskFragment = fragmentToken;
|
||||
mLastAdjacentParams = params;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the last requested adjacent TaskFragment token and params.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_CLEAR_ADJACENT_TASK_FRAGMENTS
|
||||
*/
|
||||
void clearLastAdjacentTaskFragment() {
|
||||
final TaskFragmentContainer lastAdjacentTaskFragment = mLastAdjacentTaskFragment != null
|
||||
? mController.getContainer(mLastAdjacentTaskFragment)
|
||||
: null;
|
||||
mLastAdjacentTaskFragment = null;
|
||||
mLastAdjacentParams = null;
|
||||
if (lastAdjacentTaskFragment != null) {
|
||||
// Clear the previous adjacent TaskFragment as well.
|
||||
lastAdjacentTaskFragment.clearLastAdjacentTaskFragment();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if last requested companion TaskFragment token is equal to the provided value.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_SET_COMPANION_TASK_FRAGMENT
|
||||
*/
|
||||
boolean isLastCompanionTaskFragmentEqual(@Nullable IBinder fragmentToken) {
|
||||
return Objects.equals(mLastCompanionTaskFragment, fragmentToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the last requested companion TaskFragment token.
|
||||
* @see android.window.TaskFragmentOperation#OP_TYPE_SET_COMPANION_TASK_FRAGMENT
|
||||
*/
|
||||
void setLastCompanionTaskFragment(@Nullable IBinder fragmentToken) {
|
||||
mLastCompanionTaskFragment = fragmentToken;
|
||||
}
|
||||
|
||||
/** Gets the parent leaf Task id. */
|
||||
int getTaskId() {
|
||||
return mTaskContainer.getTaskId();
|
||||
|
||||
@@ -176,6 +176,64 @@ public class SplitPresenterTest {
|
||||
verify(mTransaction, never()).setWindowingMode(any(), anyInt());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAdjacentTaskFragments() {
|
||||
final TaskFragmentContainer container0 = mController.newContainer(mActivity, TASK_ID);
|
||||
final TaskFragmentContainer container1 = mController.newContainer(mActivity, TASK_ID);
|
||||
|
||||
mPresenter.setAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken(), null /* adjacentParams */);
|
||||
verify(mTransaction).setAdjacentTaskFragments(container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken(), null /* adjacentParams */);
|
||||
|
||||
// No request to set the same adjacent TaskFragments.
|
||||
clearInvocations(mTransaction);
|
||||
mPresenter.setAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken(), null /* adjacentParams */);
|
||||
|
||||
verify(mTransaction, never()).setAdjacentTaskFragments(any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClearAdjacentTaskFragments() {
|
||||
final TaskFragmentContainer container0 = mController.newContainer(mActivity, TASK_ID);
|
||||
final TaskFragmentContainer container1 = mController.newContainer(mActivity, TASK_ID);
|
||||
|
||||
// No request to clear as it is not set by default.
|
||||
mPresenter.clearAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken());
|
||||
verify(mTransaction, never()).clearAdjacentTaskFragments(any());
|
||||
|
||||
mPresenter.setAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken(), null /* adjacentParams */);
|
||||
mPresenter.clearAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken());
|
||||
verify(mTransaction).clearAdjacentTaskFragments(container0.getTaskFragmentToken());
|
||||
|
||||
// No request to clear on either of the previous cleared TasKFragments.
|
||||
clearInvocations(mTransaction);
|
||||
mPresenter.clearAdjacentTaskFragments(mTransaction, container0.getTaskFragmentToken());
|
||||
mPresenter.clearAdjacentTaskFragments(mTransaction, container1.getTaskFragmentToken());
|
||||
|
||||
verify(mTransaction, never()).clearAdjacentTaskFragments(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetCompanionTaskFragment() {
|
||||
final TaskFragmentContainer container0 = mController.newContainer(mActivity, TASK_ID);
|
||||
final TaskFragmentContainer container1 = mController.newContainer(mActivity, TASK_ID);
|
||||
|
||||
mPresenter.setCompanionTaskFragment(mTransaction, container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken());
|
||||
verify(mTransaction).setCompanionTaskFragment(container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken());
|
||||
|
||||
// No request to set the same adjacent TaskFragments.
|
||||
clearInvocations(mTransaction);
|
||||
mPresenter.setCompanionTaskFragment(mTransaction, container0.getTaskFragmentToken(),
|
||||
container1.getTaskFragmentToken());
|
||||
|
||||
verify(mTransaction, never()).setCompanionTaskFragment(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUpdateAnimationParams() {
|
||||
final TaskFragmentContainer container = mController.newContainer(mActivity, TASK_ID);
|
||||
|
||||
@@ -136,6 +136,7 @@ import android.view.Display;
|
||||
import android.view.DisplayInfo;
|
||||
import android.view.SurfaceControl;
|
||||
import android.view.WindowManager;
|
||||
import android.window.TaskFragmentAnimationParams;
|
||||
import android.window.WindowContainerToken;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
@@ -2093,6 +2094,8 @@ class RootWindowContainer extends WindowContainer<DisplayContent>
|
||||
return;
|
||||
}
|
||||
tf.resetAdjacentTaskFragment();
|
||||
tf.setCompanionTaskFragment(null /* companionTaskFragment */);
|
||||
tf.setAnimationParams(TaskFragmentAnimationParams.DEFAULT);
|
||||
if (tf.getTopNonFinishingActivity() != null) {
|
||||
// When the Task is entering picture-in-picture, we should clear all override
|
||||
// from the client organizer, so the PIP activity can get the correct config
|
||||
|
||||
@@ -2813,7 +2813,7 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
void removeImmediately() {
|
||||
mIsRemovalRequested = false;
|
||||
resetAdjacentTaskFragment();
|
||||
cleanUp();
|
||||
cleanUpEmbeddedTaskFragment();
|
||||
final boolean shouldExecuteAppTransition =
|
||||
mClearedTaskFragmentForPip && isTaskVisibleRequested();
|
||||
super.removeImmediately();
|
||||
@@ -2830,10 +2830,20 @@ class TaskFragment extends WindowContainer<WindowContainer> {
|
||||
}
|
||||
|
||||
/** Called on remove to cleanup. */
|
||||
private void cleanUp() {
|
||||
if (mIsEmbedded) {
|
||||
mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
|
||||
private void cleanUpEmbeddedTaskFragment() {
|
||||
if (!mIsEmbedded) {
|
||||
return;
|
||||
}
|
||||
mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this);
|
||||
final Task task = getTask();
|
||||
if (task == null) {
|
||||
return;
|
||||
}
|
||||
task.forAllLeafTaskFragments(taskFragment -> {
|
||||
if (taskFragment.getCompanionTaskFragment() == this) {
|
||||
taskFragment.setCompanionTaskFragment(null /* companionTaskFragment */);
|
||||
}
|
||||
}, false /* traverseTopToBottom */);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -45,11 +45,13 @@ import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.clearInvocations;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Binder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.SurfaceControl;
|
||||
import android.window.ITaskFragmentOrganizer;
|
||||
import android.window.TaskFragmentAnimationParams;
|
||||
import android.window.TaskFragmentInfo;
|
||||
import android.window.TaskFragmentOrganizer;
|
||||
|
||||
@@ -299,35 +301,44 @@ public class TaskFragmentTest extends WindowTestsBase {
|
||||
|
||||
@Test
|
||||
public void testEmbeddedTaskFragmentEnterPip_singleActivity_resetOrganizerOverrideConfig() {
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||
.setOrganizer(mOrganizer)
|
||||
.setFragmentToken(new Binder())
|
||||
.setCreateParentTask()
|
||||
.createActivityCount(1)
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment taskFragment0 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
|
||||
final TaskFragment taskFragment1 = new TaskFragmentBuilder(mAtm)
|
||||
.setParentTask(task)
|
||||
.build();
|
||||
final Task task = taskFragment.getTask();
|
||||
final ActivityRecord activity = taskFragment.getTopMostActivity();
|
||||
final ActivityRecord activity = taskFragment0.getTopMostActivity();
|
||||
final Rect taskFragmentBounds = new Rect(0, 0, 300, 1000);
|
||||
task.setWindowingMode(WINDOWING_MODE_FULLSCREEN);
|
||||
taskFragment.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
||||
taskFragment.setBounds(taskFragmentBounds);
|
||||
taskFragment0.setWindowingMode(WINDOWING_MODE_MULTI_WINDOW);
|
||||
taskFragment0.setBounds(taskFragmentBounds);
|
||||
taskFragment0.setAdjacentTaskFragment(taskFragment1);
|
||||
taskFragment0.setCompanionTaskFragment(taskFragment1);
|
||||
taskFragment0.setAnimationParams(new TaskFragmentAnimationParams.Builder()
|
||||
.setAnimationBackgroundColor(Color.GREEN)
|
||||
.build());
|
||||
|
||||
assertEquals(taskFragmentBounds, activity.getBounds());
|
||||
assertEquals(WINDOWING_MODE_MULTI_WINDOW, activity.getWindowingMode());
|
||||
assertEquals(taskFragment1, taskFragment0.getAdjacentTaskFragment());
|
||||
assertEquals(taskFragment1, taskFragment0.getCompanionTaskFragment());
|
||||
assertNotEquals(TaskFragmentAnimationParams.DEFAULT, taskFragment0.getAnimationParams());
|
||||
|
||||
// Move activity to pinned root task.
|
||||
mRootWindowContainer.moveActivityToPinnedRootTask(activity,
|
||||
null /* launchIntoPipHostActivity */, "test");
|
||||
|
||||
// Ensure taskFragment requested config is reset.
|
||||
assertEquals(taskFragment, activity.getOrganizedTaskFragment());
|
||||
assertEquals(taskFragment0, activity.getOrganizedTaskFragment());
|
||||
assertEquals(task, activity.getTask());
|
||||
assertTrue(task.inPinnedWindowingMode());
|
||||
assertTrue(taskFragment.inPinnedWindowingMode());
|
||||
assertTrue(taskFragment0.inPinnedWindowingMode());
|
||||
final Rect taskBounds = task.getBounds();
|
||||
assertEquals(taskBounds, taskFragment.getBounds());
|
||||
assertEquals(taskBounds, taskFragment0.getBounds());
|
||||
assertEquals(taskBounds, activity.getBounds());
|
||||
assertEquals(Configuration.EMPTY, taskFragment.getRequestedOverrideConfiguration());
|
||||
assertEquals(Configuration.EMPTY, taskFragment0.getRequestedOverrideConfiguration());
|
||||
assertNull(taskFragment0.getAdjacentTaskFragment());
|
||||
assertNull(taskFragment0.getCompanionTaskFragment());
|
||||
assertEquals(TaskFragmentAnimationParams.DEFAULT, taskFragment0.getAnimationParams());
|
||||
// Because the whole Task is entering PiP, no need to record for future reparent.
|
||||
assertNull(activity.mLastTaskFragmentOrganizerBeforePip);
|
||||
}
|
||||
@@ -335,18 +346,8 @@ public class TaskFragmentTest extends WindowTestsBase {
|
||||
@Test
|
||||
public void testEmbeddedTaskFragmentEnterPip_multiActivities_notifyOrganizer() {
|
||||
final Task task = createTask(mDisplayContent);
|
||||
final TaskFragment taskFragment0 = new TaskFragmentBuilder(mAtm)
|
||||
.setParentTask(task)
|
||||
.setOrganizer(mOrganizer)
|
||||
.setFragmentToken(new Binder())
|
||||
.createActivityCount(1)
|
||||
.build();
|
||||
final TaskFragment taskFragment1 = new TaskFragmentBuilder(mAtm)
|
||||
.setParentTask(task)
|
||||
.setOrganizer(mOrganizer)
|
||||
.setFragmentToken(new Binder())
|
||||
.createActivityCount(1)
|
||||
.build();
|
||||
final TaskFragment taskFragment0 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
|
||||
final TaskFragment taskFragment1 = createTaskFragmentWithEmbeddedActivity(task, mOrganizer);
|
||||
final ActivityRecord activity0 = taskFragment0.getTopMostActivity();
|
||||
final ActivityRecord activity1 = taskFragment1.getTopMostActivity();
|
||||
activity0.setVisibility(true /* visible */, false /* deferHidingClient */);
|
||||
|
||||
@@ -79,6 +79,7 @@ import android.graphics.Insets;
|
||||
import android.graphics.Rect;
|
||||
import android.hardware.HardwareBuffer;
|
||||
import android.hardware.display.DisplayManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
@@ -750,11 +751,11 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link TaskFragment} with {@link ActivityRecord} and attach it to the
|
||||
* Creates a {@link TaskFragment} with {@link ActivityRecord}, and attaches it to the
|
||||
* {@code parentTask}.
|
||||
*
|
||||
* @param parentTask the {@link Task} this TaskFragment is going to be attached
|
||||
* @return the created TaskFragment
|
||||
* @param parentTask the {@link Task} this {@link TaskFragment} is going to be attached.
|
||||
* @return the created {@link TaskFragment}
|
||||
*/
|
||||
static TaskFragment createTaskFragmentWithActivity(@NonNull Task parentTask) {
|
||||
return new TaskFragmentBuilder(parentTask.mAtmService)
|
||||
@@ -763,13 +764,27 @@ class WindowTestsBase extends SystemServiceTestsBase {
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an embedded {@link TaskFragment} organized by {@code organizer} with
|
||||
* {@link ActivityRecord}, and attaches it to the {@code parentTask}.
|
||||
*
|
||||
* @param parentTask the {@link Task} this {@link TaskFragment} is going to be attached.
|
||||
* @param organizer the {@link TaskFragmentOrganizer} this {@link TaskFragment} is going to be
|
||||
* organized by.
|
||||
* @return the created {@link TaskFragment}
|
||||
*/
|
||||
static TaskFragment createTaskFragmentWithEmbeddedActivity(@NonNull Task parentTask,
|
||||
TaskFragmentOrganizer organizer) {
|
||||
return new TaskFragmentBuilder(parentTask.mAtmService)
|
||||
@NonNull TaskFragmentOrganizer organizer) {
|
||||
final IBinder fragmentToken = new Binder();
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(parentTask.mAtmService)
|
||||
.setParentTask(parentTask)
|
||||
.createActivityCount(1)
|
||||
.setOrganizer(organizer)
|
||||
.setFragmentToken(fragmentToken)
|
||||
.build();
|
||||
parentTask.mAtmService.mWindowOrganizerController.mLaunchTaskFragments
|
||||
.put(fragmentToken, taskFragment);
|
||||
return taskFragment;
|
||||
}
|
||||
|
||||
/** Creates a {@link DisplayContent} that supports IME and adds it to the system. */
|
||||
|
||||
Reference in New Issue
Block a user