Merge "Apply TaskFragmentOrganizer changes in one WCT (1/2)" into tm-qpr-dev
This commit is contained in:
@@ -147,13 +147,25 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when a TaskFragment is created and organized by this organizer. */
|
||||
/**
|
||||
* Called when a TaskFragment is created and organized by this organizer.
|
||||
*
|
||||
* @param taskFragmentInfo Info of the TaskFragment that is created.
|
||||
*/
|
||||
public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {}
|
||||
|
||||
/** Called when the status of an organized TaskFragment is changed. */
|
||||
/**
|
||||
* Called when the status of an organized TaskFragment is changed.
|
||||
*
|
||||
* @param taskFragmentInfo Info of the TaskFragment that is changed.
|
||||
*/
|
||||
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {}
|
||||
|
||||
/** Called when an organized TaskFragment is removed. */
|
||||
/**
|
||||
* Called when an organized TaskFragment is removed.
|
||||
*
|
||||
* @param taskFragmentInfo Info of the TaskFragment that is removed.
|
||||
*/
|
||||
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {}
|
||||
|
||||
/**
|
||||
@@ -176,6 +188,9 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
||||
* For case like screen size change, it will trigger onTaskFragmentParentInfoChanged with new
|
||||
* Task bounds, but may not trigger onTaskFragmentInfoChanged because there can be an override
|
||||
* bounds.
|
||||
*
|
||||
* @param taskId Id of the parent Task that is changed.
|
||||
* @param parentConfig Config of the parent Task.
|
||||
* @hide
|
||||
*/
|
||||
public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
|
||||
@@ -226,7 +241,7 @@ public class TaskFragmentOrganizer extends WindowOrganizer {
|
||||
/**
|
||||
* Called when an Activity is reparented to the Task with organized TaskFragment. For example,
|
||||
* when an Activity enters and then exits Picture-in-picture, it will be reparented back to its
|
||||
* orginial Task. In this case, we need to notify the organizer so that it can check if the
|
||||
* original Task. In this case, we need to notify the organizer so that it can check if the
|
||||
* Activity matches any split rule.
|
||||
*
|
||||
* @param taskId The Task that the activity is reparented to.
|
||||
|
||||
@@ -62,13 +62,18 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
* Callback that notifies the controller about changes to task fragments.
|
||||
*/
|
||||
interface TaskFragmentCallback {
|
||||
void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo);
|
||||
void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo);
|
||||
void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo);
|
||||
void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig);
|
||||
void onActivityReparentedToTask(int taskId, @NonNull Intent activityIntent,
|
||||
@NonNull IBinder activityToken);
|
||||
void onTaskFragmentError(@Nullable TaskFragmentInfo taskFragmentInfo, int opType);
|
||||
void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentInfo taskFragmentInfo);
|
||||
void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentInfo taskFragmentInfo);
|
||||
void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentInfo taskFragmentInfo);
|
||||
void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
|
||||
int taskId, @NonNull Configuration parentConfig);
|
||||
void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct,
|
||||
int taskId, @NonNull Intent activityIntent, @NonNull IBinder activityToken);
|
||||
void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
|
||||
@Nullable TaskFragmentInfo taskFragmentInfo, int opType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,27 +163,16 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
updateWindowingMode(wct, fragmentToken, WINDOWING_MODE_UNDEFINED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands an existing TaskFragment to fill parent.
|
||||
* @param fragmentToken token of an existing TaskFragment.
|
||||
*/
|
||||
void expandTaskFragment(@NonNull IBinder fragmentToken) {
|
||||
WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
expandTaskFragment(wct, fragmentToken);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Expands an Activity to fill parent by moving it to a new TaskFragment.
|
||||
* @param fragmentToken token to create new TaskFragment with.
|
||||
* @param activity activity to move to the fill-parent TaskFragment.
|
||||
*/
|
||||
void expandActivity(@NonNull IBinder fragmentToken, @NonNull Activity activity) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
void expandActivity(@NonNull WindowContainerTransaction wct, @NonNull IBinder fragmentToken,
|
||||
@NonNull Activity activity) {
|
||||
createTaskFragmentAndReparentActivity(
|
||||
wct, fragmentToken, activity.getActivityToken(), new Rect(),
|
||||
WINDOWING_MODE_UNDEFINED, activity);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -278,43 +272,55 @@ class JetpackTaskFragmentOrganizer extends TaskFragmentOrganizer {
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
|
||||
mFragmentInfos.put(fragmentToken, taskFragmentInfo);
|
||||
mCallback.onTaskFragmentAppeared(taskFragmentInfo);
|
||||
mCallback.onTaskFragmentAppeared(wct, taskFragmentInfo);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
|
||||
mFragmentInfos.put(fragmentToken, taskFragmentInfo);
|
||||
mCallback.onTaskFragmentInfoChanged(taskFragmentInfo);
|
||||
mCallback.onTaskFragmentInfoChanged(wct, taskFragmentInfo);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mFragmentInfos.remove(taskFragmentInfo.getFragmentToken());
|
||||
mCallback.onTaskFragmentVanished(taskFragmentInfo);
|
||||
mCallback.onTaskFragmentVanished(wct, taskFragmentInfo);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
|
||||
mCallback.onTaskFragmentParentInfoChanged(taskId, parentConfig);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mCallback.onTaskFragmentParentInfoChanged(wct, taskId, parentConfig);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityReparentedToTask(int taskId, @NonNull Intent activityIntent,
|
||||
@NonNull IBinder activityToken) {
|
||||
mCallback.onActivityReparentedToTask(taskId, activityIntent, activityToken);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mCallback.onActivityReparentedToTask(wct, taskId, activityIntent, activityToken);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentError(@NonNull IBinder errorCallbackToken,
|
||||
@Nullable TaskFragmentInfo taskFragmentInfo,
|
||||
int opType, @NonNull Throwable exception) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
if (taskFragmentInfo != null) {
|
||||
final IBinder fragmentToken = taskFragmentInfo.getFragmentToken();
|
||||
mFragmentInfos.put(fragmentToken, taskFragmentInfo);
|
||||
}
|
||||
mCallback.onTaskFragmentError(taskFragmentInfo, opType);
|
||||
mCallback.onTaskFragmentError(wct, taskFragmentInfo, opType);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,35 +145,36 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentAppeared(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
public void onTaskFragmentAppeared(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
synchronized (mLock) {
|
||||
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
||||
if (container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
container.setInfo(taskFragmentInfo);
|
||||
container.setInfo(wct, taskFragmentInfo);
|
||||
if (container.isFinished()) {
|
||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
|
||||
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
|
||||
} else {
|
||||
// Update with the latest Task configuration.
|
||||
mPresenter.updateContainer(container);
|
||||
updateContainer(wct, container);
|
||||
}
|
||||
updateCallbackIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentInfoChanged(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
public void onTaskFragmentInfoChanged(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
synchronized (mLock) {
|
||||
TaskFragmentContainer container = getContainer(taskFragmentInfo.getFragmentToken());
|
||||
if (container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
final boolean wasInPip = isInPictureInPicture(container);
|
||||
container.setInfo(taskFragmentInfo);
|
||||
container.setInfo(wct, taskFragmentInfo);
|
||||
final boolean isInPip = isInPictureInPicture(container);
|
||||
// Check if there are no running activities - consider the container empty if there are
|
||||
// no non-finishing activities left.
|
||||
@@ -183,15 +184,15 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// Instead, the original split should be cleanup, and the dependent may be
|
||||
// expanded to fullscreen.
|
||||
cleanupForEnterPip(wct, container);
|
||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct);
|
||||
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
|
||||
} else if (taskFragmentInfo.isTaskClearedForReuse()) {
|
||||
// Do not finish the dependents if this TaskFragment was cleared due to
|
||||
// launching activity in the Task.
|
||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */, wct);
|
||||
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
|
||||
} else if (!container.isWaitingActivityAppear()) {
|
||||
// Do not finish the container before the expected activity appear until
|
||||
// timeout.
|
||||
mPresenter.cleanupContainer(container, true /* shouldFinishDependent */, wct);
|
||||
mPresenter.cleanupContainer(wct, container, true /* shouldFinishDependent */);
|
||||
}
|
||||
} else if (wasInPip && isInPip) {
|
||||
// No update until exit PIP.
|
||||
@@ -208,13 +209,13 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// needed.
|
||||
updateContainer(wct, container);
|
||||
}
|
||||
mPresenter.applyTransaction(wct);
|
||||
updateCallbackIfNecessary();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentVanished(@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
public void onTaskFragmentVanished(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentInfo taskFragmentInfo) {
|
||||
synchronized (mLock) {
|
||||
final TaskFragmentContainer container = getContainer(
|
||||
taskFragmentInfo.getFragmentToken());
|
||||
@@ -225,9 +226,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
final TaskFragmentContainer newTopContainer = getTopActiveContainer(
|
||||
container.getTaskId());
|
||||
if (newTopContainer != null) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
updateContainer(wct, newTopContainer);
|
||||
mPresenter.applyTransaction(wct);
|
||||
}
|
||||
updateCallbackIfNecessary();
|
||||
}
|
||||
@@ -236,7 +235,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentParentInfoChanged(int taskId, @NonNull Configuration parentConfig) {
|
||||
public void onTaskFragmentParentInfoChanged(@NonNull WindowContainerTransaction wct,
|
||||
int taskId, @NonNull Configuration parentConfig) {
|
||||
synchronized (mLock) {
|
||||
onTaskConfigurationChanged(taskId, parentConfig);
|
||||
if (isInPictureInPicture(parentConfig)) {
|
||||
@@ -256,7 +256,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
final TaskFragmentContainer container = containers.get(i);
|
||||
// Wait until onTaskFragmentAppeared to update new container.
|
||||
if (!container.isFinished() && !container.isWaitingActivityAppear()) {
|
||||
mPresenter.updateContainer(container);
|
||||
updateContainer(wct, container);
|
||||
}
|
||||
}
|
||||
updateCallbackIfNecessary();
|
||||
@@ -264,7 +264,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityReparentedToTask(int taskId, @NonNull Intent activityIntent,
|
||||
public void onActivityReparentedToTask(@NonNull WindowContainerTransaction wct,
|
||||
int taskId, @NonNull Intent activityIntent,
|
||||
@NonNull IBinder activityToken) {
|
||||
synchronized (mLock) {
|
||||
// If the activity belongs to the current app process, we treat it as a new activity
|
||||
@@ -275,10 +276,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// launching to top. We allow split as primary for activity reparent because the
|
||||
// activity may be split as primary before it is reparented out. In that case, we
|
||||
// want to show it as primary again when it is reparented back.
|
||||
if (!resolveActivityToContainer(activity, true /* isOnReparent */)) {
|
||||
if (!resolveActivityToContainer(wct, activity, true /* isOnReparent */)) {
|
||||
// When there is no embedding rule matched, try to place it in the top container
|
||||
// like a normal launch.
|
||||
placeActivityInTopContainer(activity);
|
||||
placeActivityInTopContainer(wct, activity);
|
||||
}
|
||||
updateCallbackIfNecessary();
|
||||
return;
|
||||
@@ -293,7 +294,6 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// If the activity belongs to a different app process, we treat it as starting new
|
||||
// intent, since both actions might result in a new activity that should appear in an
|
||||
// organized TaskFragment.
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
TaskFragmentContainer targetContainer = resolveStartActivityIntent(wct, taskId,
|
||||
activityIntent, null /* launchingActivity */);
|
||||
if (targetContainer == null) {
|
||||
@@ -306,14 +306,14 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
wct.reparentActivityToTaskFragment(targetContainer.getTaskFragmentToken(),
|
||||
activityToken);
|
||||
mPresenter.applyTransaction(wct);
|
||||
// Because the activity does not belong to the organizer process, we wait until
|
||||
// onTaskFragmentAppeared to trigger updateCallbackIfNecessary().
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTaskFragmentError(@Nullable TaskFragmentInfo taskFragmentInfo, int opType) {
|
||||
public void onTaskFragmentError(@NonNull WindowContainerTransaction wct,
|
||||
@Nullable TaskFragmentInfo taskFragmentInfo, int opType) {
|
||||
synchronized (mLock) {
|
||||
switch (opType) {
|
||||
case HIERARCHY_OP_TYPE_START_ACTIVITY_IN_TASK_FRAGMENT:
|
||||
@@ -329,10 +329,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
// Update the latest taskFragmentInfo and perform necessary clean-up
|
||||
container.setInfo(taskFragmentInfo);
|
||||
container.setInfo(wct, taskFragmentInfo);
|
||||
container.clearPendingAppearedActivities();
|
||||
if (container.isEmpty()) {
|
||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
|
||||
mPresenter.cleanupContainer(wct, container,
|
||||
false /* shouldFinishDependent */);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -343,7 +344,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
}
|
||||
|
||||
/** Called on receiving {@link #onTaskFragmentVanished(TaskFragmentInfo)} for cleanup. */
|
||||
/** Called on receiving {@link #onTaskFragmentVanished} for cleanup. */
|
||||
private void cleanupTaskFragment(@NonNull IBinder taskFragmentToken) {
|
||||
for (int i = mTaskContainers.size() - 1; i >= 0; i--) {
|
||||
final TaskContainer taskContainer = mTaskContainers.valueAt(i);
|
||||
@@ -422,10 +423,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void onActivityCreated(@NonNull Activity launchedActivity) {
|
||||
@GuardedBy("mLock")
|
||||
void onActivityCreated(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity launchedActivity) {
|
||||
// TODO(b/229680885): we don't support launching into primary yet because we want to always
|
||||
// launch the new activity on top.
|
||||
resolveActivityToContainer(launchedActivity, false /* isOnReparent */);
|
||||
resolveActivityToContainer(wct, launchedActivity, false /* isOnReparent */);
|
||||
updateCallbackIfNecessary();
|
||||
}
|
||||
|
||||
@@ -440,7 +443,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
*/
|
||||
@VisibleForTesting
|
||||
@GuardedBy("mLock")
|
||||
boolean resolveActivityToContainer(@NonNull Activity activity, boolean isOnReparent) {
|
||||
boolean resolveActivityToContainer(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity activity, boolean isOnReparent) {
|
||||
if (isInPictureInPicture(activity) || activity.isFinishing()) {
|
||||
// We don't embed activity when it is in PIP, or finishing. Return true since we don't
|
||||
// want any extra handling.
|
||||
@@ -472,12 +476,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
|
||||
// 1. Whether the new launched activity should always expand.
|
||||
if (shouldExpand(activity, null /* intent */)) {
|
||||
expandActivity(activity);
|
||||
expandActivity(wct, activity);
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2. Whether the new launched activity should launch a placeholder.
|
||||
if (launchPlaceholderIfNecessary(activity, !isOnReparent)) {
|
||||
if (launchPlaceholderIfNecessary(wct, activity, !isOnReparent)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -492,11 +496,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// Can't find any activity below.
|
||||
return false;
|
||||
}
|
||||
if (putActivitiesIntoSplitIfNecessary(activityBelow, activity)) {
|
||||
if (putActivitiesIntoSplitIfNecessary(wct, activityBelow, activity)) {
|
||||
// Have split rule of [ activityBelow | launchedActivity ].
|
||||
return true;
|
||||
}
|
||||
if (isOnReparent && putActivitiesIntoSplitIfNecessary(activity, activityBelow)) {
|
||||
if (isOnReparent && putActivitiesIntoSplitIfNecessary(wct, activity, activityBelow)) {
|
||||
// Have split rule of [ launchedActivity | activityBelow].
|
||||
return true;
|
||||
}
|
||||
@@ -519,19 +523,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// Can't find the top activity on the other split TaskFragment.
|
||||
return false;
|
||||
}
|
||||
if (putActivitiesIntoSplitIfNecessary(otherTopActivity, activity)) {
|
||||
if (putActivitiesIntoSplitIfNecessary(wct, otherTopActivity, activity)) {
|
||||
// Have split rule of [ otherTopActivity | launchedActivity ].
|
||||
return true;
|
||||
}
|
||||
// Have split rule of [ launchedActivity | otherTopActivity].
|
||||
return isOnReparent && putActivitiesIntoSplitIfNecessary(activity, otherTopActivity);
|
||||
return isOnReparent && putActivitiesIntoSplitIfNecessary(wct, activity, otherTopActivity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places the given activity to the top most TaskFragment in the task if there is any.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
void placeActivityInTopContainer(@NonNull Activity activity) {
|
||||
void placeActivityInTopContainer(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity activity) {
|
||||
if (getContainerWithActivity(activity) != null) {
|
||||
// The activity has already been put in a TaskFragment. This is likely to be done by
|
||||
// the server when the activity is started.
|
||||
@@ -547,20 +552,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
return;
|
||||
}
|
||||
targetContainer.addPendingAppearedActivity(activity);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
wct.reparentActivityToTaskFragment(targetContainer.getTaskFragmentToken(),
|
||||
activity.getActivityToken());
|
||||
mPresenter.applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts an activity to side of the launchingActivity with the provided split config.
|
||||
*/
|
||||
private void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent intent,
|
||||
@GuardedBy("mLock")
|
||||
private void startActivityToSide(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity launchingActivity, @NonNull Intent intent,
|
||||
@Nullable Bundle options, @NonNull SplitRule sideRule,
|
||||
@Nullable Consumer<Exception> failureCallback, boolean isPlaceholder) {
|
||||
try {
|
||||
mPresenter.startActivityToSide(launchingActivity, intent, options, sideRule,
|
||||
mPresenter.startActivityToSide(wct, launchingActivity, intent, options, sideRule,
|
||||
isPlaceholder);
|
||||
} catch (Exception e) {
|
||||
if (failureCallback != null) {
|
||||
@@ -573,15 +578,17 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
* Expands the given activity by either expanding the TaskFragment it is currently in or putting
|
||||
* it into a new expanded TaskFragment.
|
||||
*/
|
||||
private void expandActivity(@NonNull Activity activity) {
|
||||
@GuardedBy("mLock")
|
||||
private void expandActivity(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity activity) {
|
||||
final TaskFragmentContainer container = getContainerWithActivity(activity);
|
||||
if (shouldContainerBeExpanded(container)) {
|
||||
// Make sure that the existing container is expanded.
|
||||
mPresenter.expandTaskFragment(container.getTaskFragmentToken());
|
||||
mPresenter.expandTaskFragment(wct, container.getTaskFragmentToken());
|
||||
} else {
|
||||
// Put activity into a new expanded container.
|
||||
final TaskFragmentContainer newContainer = newContainer(activity, getTaskId(activity));
|
||||
mPresenter.expandActivity(newContainer.getTaskFragmentToken(), activity);
|
||||
mPresenter.expandActivity(wct, newContainer.getTaskFragmentToken(), activity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -667,8 +674,8 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
* and returns {@code true}. Otherwise, returns {@code false}.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
private boolean putActivitiesIntoSplitIfNecessary(@NonNull Activity primaryActivity,
|
||||
@NonNull Activity secondaryActivity) {
|
||||
private boolean putActivitiesIntoSplitIfNecessary(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity) {
|
||||
final SplitPairRule splitRule = getSplitRule(primaryActivity, secondaryActivity);
|
||||
if (splitRule == null) {
|
||||
return false;
|
||||
@@ -686,23 +693,23 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
return true;
|
||||
}
|
||||
secondaryContainer.addPendingAppearedActivity(secondaryActivity);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
if (mPresenter.expandSplitContainerIfNeeded(wct, splitContainer, primaryActivity,
|
||||
secondaryActivity, null /* secondaryIntent */)
|
||||
!= RESULT_EXPAND_FAILED_NO_TF_INFO) {
|
||||
wct.reparentActivityToTaskFragment(
|
||||
secondaryContainer.getTaskFragmentToken(),
|
||||
secondaryActivity.getActivityToken());
|
||||
mPresenter.applyTransaction(wct);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Create new split pair.
|
||||
mPresenter.createNewSplitContainer(primaryActivity, secondaryActivity, splitRule);
|
||||
mPresenter.createNewSplitContainer(wct, primaryActivity, secondaryActivity, splitRule);
|
||||
return true;
|
||||
}
|
||||
|
||||
private void onActivityConfigurationChanged(@NonNull Activity activity) {
|
||||
@GuardedBy("mLock")
|
||||
private void onActivityConfigurationChanged(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity activity) {
|
||||
if (activity.isFinishing()) {
|
||||
// Do nothing if the activity is currently finishing.
|
||||
return;
|
||||
@@ -721,7 +728,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
// Check if activity requires a placeholder
|
||||
launchPlaceholderIfNecessary(activity, false /* isOnCreated */);
|
||||
launchPlaceholderIfNecessary(wct, activity, false /* isOnCreated */);
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -741,7 +748,22 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
* creation.
|
||||
*/
|
||||
void onTaskFragmentAppearEmptyTimeout(@NonNull TaskFragmentContainer container) {
|
||||
mPresenter.cleanupContainer(container, false /* shouldFinishDependent */);
|
||||
synchronized (mLock) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
onTaskFragmentAppearEmptyTimeout(wct, container);
|
||||
mPresenter.applyTransaction(wct);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when we have been waiting too long for the TaskFragment to become non-empty after
|
||||
* creation.
|
||||
*/
|
||||
void onTaskFragmentAppearEmptyTimeout(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentContainer container) {
|
||||
synchronized (mLock) {
|
||||
mPresenter.cleanupContainer(wct, container, false /* shouldFinishDependent */);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -971,6 +993,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
/** Cleanups all the dependencies when the TaskFragment is entering PIP. */
|
||||
@GuardedBy("mLock")
|
||||
private void cleanupForEnterPip(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentContainer container) {
|
||||
final TaskContainer taskContainer = container.getTaskContainer();
|
||||
@@ -1084,9 +1107,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
* Updates the presentation of the container. If the container is part of the split or should
|
||||
* have a placeholder, it will also update the other part of the split.
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
void updateContainer(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentContainer container) {
|
||||
if (launchPlaceholderIfNecessary(container)) {
|
||||
if (launchPlaceholderIfNecessary(wct, container)) {
|
||||
// Placeholder was launched, the positions will be updated when the activity is added
|
||||
// to the secondary container.
|
||||
return;
|
||||
@@ -1111,7 +1135,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// Skip position update - one or both containers are finished.
|
||||
return;
|
||||
}
|
||||
if (dismissPlaceholderIfNecessary(splitContainer)) {
|
||||
if (dismissPlaceholderIfNecessary(wct, splitContainer)) {
|
||||
// Placeholder was finished, the positions will be updated when its container is emptied
|
||||
return;
|
||||
}
|
||||
@@ -1173,16 +1197,20 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
/**
|
||||
* Checks if the container requires a placeholder and launches it if necessary.
|
||||
*/
|
||||
private boolean launchPlaceholderIfNecessary(@NonNull TaskFragmentContainer container) {
|
||||
@GuardedBy("mLock")
|
||||
private boolean launchPlaceholderIfNecessary(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentContainer container) {
|
||||
final Activity topActivity = container.getTopNonFinishingActivity();
|
||||
if (topActivity == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return launchPlaceholderIfNecessary(topActivity, false /* isOnCreated */);
|
||||
return launchPlaceholderIfNecessary(wct, topActivity, false /* isOnCreated */);
|
||||
}
|
||||
|
||||
boolean launchPlaceholderIfNecessary(@NonNull Activity activity, boolean isOnCreated) {
|
||||
@GuardedBy("mLock")
|
||||
boolean launchPlaceholderIfNecessary(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity activity, boolean isOnCreated) {
|
||||
if (activity.isFinishing()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1216,7 +1244,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
|
||||
// TODO(b/190433398): Handle failed request
|
||||
final Bundle options = getPlaceholderOptions(activity, isOnCreated);
|
||||
startActivityToSide(activity, placeholderRule.getPlaceholderIntent(), options,
|
||||
startActivityToSide(wct, activity, placeholderRule.getPlaceholderIntent(), options,
|
||||
placeholderRule, null /* failureCallback */, true /* isPlaceholder */);
|
||||
return true;
|
||||
}
|
||||
@@ -1243,7 +1271,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean dismissPlaceholderIfNecessary(@NonNull SplitContainer splitContainer) {
|
||||
@GuardedBy("mLock")
|
||||
boolean dismissPlaceholderIfNecessary(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull SplitContainer splitContainer) {
|
||||
if (!splitContainer.isPlaceholderContainer()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1257,7 +1287,7 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
return false;
|
||||
}
|
||||
|
||||
mPresenter.cleanupContainer(splitContainer.getSecondaryContainer(),
|
||||
mPresenter.cleanupContainer(wct, splitContainer.getSecondaryContainer(),
|
||||
false /* shouldFinishDependent */);
|
||||
return true;
|
||||
}
|
||||
@@ -1560,14 +1590,18 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen
|
||||
// that we don't launch it if an activity itself already requested something to be
|
||||
// launched to side.
|
||||
synchronized (mLock) {
|
||||
SplitController.this.onActivityCreated(activity);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
SplitController.this.onActivityCreated(wct, activity);
|
||||
mPresenter.applyTransaction(wct);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityConfigurationChanged(@NonNull Activity activity) {
|
||||
synchronized (mLock) {
|
||||
SplitController.this.onActivityConfigurationChanged(activity);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
SplitController.this.onActivityConfigurationChanged(wct, activity);
|
||||
mPresenter.applyTransaction(wct);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -108,31 +108,12 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
registerOrganizer();
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the presentation of the provided container.
|
||||
*/
|
||||
void updateContainer(@NonNull TaskFragmentContainer container) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mController.updateContainer(wct, container);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the specified container and all other associated and dependent containers in the same
|
||||
* transaction.
|
||||
*/
|
||||
void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
cleanupContainer(container, shouldFinishDependent, wct);
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the specified container and all other associated and dependent containers in the same
|
||||
* transaction.
|
||||
*/
|
||||
void cleanupContainer(@NonNull TaskFragmentContainer container, boolean shouldFinishDependent,
|
||||
@NonNull WindowContainerTransaction wct) {
|
||||
void cleanupContainer(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull TaskFragmentContainer container, boolean shouldFinishDependent) {
|
||||
container.finish(shouldFinishDependent, this, wct, mController);
|
||||
|
||||
final TaskFragmentContainer newTopContainer = mController.getTopActiveContainer(
|
||||
@@ -190,10 +171,9 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
* created and the activity will be re-parented to it.
|
||||
* @param rule The split rule to be applied to the container.
|
||||
*/
|
||||
void createNewSplitContainer(@NonNull Activity primaryActivity,
|
||||
@NonNull Activity secondaryActivity, @NonNull SplitPairRule rule) {
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
|
||||
void createNewSplitContainer(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity primaryActivity, @NonNull Activity secondaryActivity,
|
||||
@NonNull SplitPairRule rule) {
|
||||
final Rect parentBounds = getParentContainerBounds(primaryActivity);
|
||||
final Pair<Size, Size> minDimensionsPair = getActivitiesMinDimensionsPair(primaryActivity,
|
||||
secondaryActivity);
|
||||
@@ -219,8 +199,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
minDimensionsPair);
|
||||
|
||||
mController.registerSplit(wct, primaryContainer, primaryActivity, secondaryContainer, rule);
|
||||
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -262,7 +240,8 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
* @param rule The split rule to be applied to the container.
|
||||
* @param isPlaceholder Whether the launch is a placeholder.
|
||||
*/
|
||||
void startActivityToSide(@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
|
||||
void startActivityToSide(@NonNull WindowContainerTransaction wct,
|
||||
@NonNull Activity launchingActivity, @NonNull Intent activityIntent,
|
||||
@Nullable Bundle activityOptions, @NonNull SplitRule rule, boolean isPlaceholder) {
|
||||
final Rect parentBounds = getParentContainerBounds(launchingActivity);
|
||||
final Pair<Size, Size> minDimensionsPair = getActivityIntentMinDimensionsPair(
|
||||
@@ -284,7 +263,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
launchingActivity, taskId);
|
||||
final int windowingMode = mController.getTaskContainer(taskId)
|
||||
.getWindowingModeForSplitTaskFragment(primaryRectBounds);
|
||||
final WindowContainerTransaction wct = new WindowContainerTransaction();
|
||||
mController.registerSplit(wct, primaryContainer, launchingActivity, secondaryContainer,
|
||||
rule);
|
||||
startActivityToSide(wct, primaryContainer.getTaskFragmentToken(), primaryRectBounds,
|
||||
@@ -294,7 +272,6 @@ class SplitPresenter extends JetpackTaskFragmentOrganizer {
|
||||
// When placeholder is launched in split, we should keep the focus on the primary.
|
||||
wct.requestFocusOnTaskFragment(primaryContainer.getTaskFragmentToken());
|
||||
}
|
||||
applyTransaction(wct);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -251,19 +251,22 @@ class TaskFragmentContainer {
|
||||
return mInfo;
|
||||
}
|
||||
|
||||
void setInfo(@NonNull TaskFragmentInfo info) {
|
||||
void setInfo(@NonNull WindowContainerTransaction wct, @NonNull TaskFragmentInfo info) {
|
||||
if (!mIsFinished && mInfo == null && info.isEmpty()) {
|
||||
// onTaskFragmentAppeared with empty info. We will remove the TaskFragment if no
|
||||
// pending appeared intent/activities. Otherwise, wait and removing the TaskFragment if
|
||||
// it is still empty after timeout.
|
||||
mAppearEmptyTimeout = () -> {
|
||||
mAppearEmptyTimeout = null;
|
||||
mController.onTaskFragmentAppearEmptyTimeout(this);
|
||||
};
|
||||
if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) {
|
||||
mAppearEmptyTimeout = () -> {
|
||||
mAppearEmptyTimeout = null;
|
||||
// Call without the pass-in wct when timeout. We need to applyWct directly
|
||||
// in this case.
|
||||
mController.onTaskFragmentAppearEmptyTimeout(this);
|
||||
};
|
||||
mController.getHandler().postDelayed(mAppearEmptyTimeout, APPEAR_EMPTY_TIMEOUT_MS);
|
||||
} else {
|
||||
mAppearEmptyTimeout.run();
|
||||
mAppearEmptyTimeout = null;
|
||||
mController.onTaskFragmentAppearEmptyTimeout(wct, this);
|
||||
}
|
||||
} else if (mAppearEmptyTimeout != null && !info.isEmpty()) {
|
||||
mController.getHandler().removeCallbacks(mAppearEmptyTimeout);
|
||||
|
||||
@@ -56,6 +56,8 @@ import java.util.ArrayList;
|
||||
* Build/Install/Run:
|
||||
* atest WMJetpackUnitTests:JetpackTaskFragmentOrganizerTest
|
||||
*/
|
||||
// Suppress GuardedBy warning on unit tests
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -119,7 +121,7 @@ public class JetpackTaskFragmentOrganizerTest {
|
||||
new Intent(), taskContainer, mSplitController);
|
||||
final TaskFragmentInfo info = createMockInfo(container);
|
||||
mOrganizer.mFragmentInfos.put(container.getTaskFragmentToken(), info);
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
mOrganizer.expandTaskFragment(mTransaction, container.getTaskFragmentToken());
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ import java.util.List;
|
||||
* Build/Install/Run:
|
||||
* atest WMJetpackUnitTests:SplitControllerTest
|
||||
*/
|
||||
// Suppress GuardedBy warning on unit tests
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -158,14 +160,14 @@ public class SplitControllerTest {
|
||||
final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
|
||||
doReturn(new ArrayList<>()).when(info).getActivities();
|
||||
doReturn(true).when(info).isEmpty();
|
||||
tf1.setInfo(info);
|
||||
tf1.setInfo(mTransaction, info);
|
||||
|
||||
assertWithMessage("Must return tf because we are waiting for tf1 to become non-empty after"
|
||||
+ " creation.")
|
||||
.that(mSplitController.getTopActiveContainer(TASK_ID)).isEqualTo(tf1);
|
||||
|
||||
doReturn(false).when(info).isEmpty();
|
||||
tf1.setInfo(info);
|
||||
tf1.setInfo(mTransaction, info);
|
||||
|
||||
assertWithMessage("Must return null because tf1 becomes empty.")
|
||||
.that(mSplitController.getTopActiveContainer(TASK_ID)).isNull();
|
||||
@@ -177,7 +179,7 @@ public class SplitControllerTest {
|
||||
doReturn(tf.getTaskFragmentToken()).when(mInfo).getFragmentToken();
|
||||
|
||||
// The TaskFragment has been removed in the server, we only need to cleanup the reference.
|
||||
mSplitController.onTaskFragmentVanished(mInfo);
|
||||
mSplitController.onTaskFragmentVanished(mTransaction, mInfo);
|
||||
|
||||
verify(mSplitPresenter, never()).deleteTaskFragment(any(), any());
|
||||
verify(mSplitController).removeContainer(tf);
|
||||
@@ -187,9 +189,10 @@ public class SplitControllerTest {
|
||||
@Test
|
||||
public void testOnTaskFragmentAppearEmptyTimeout() {
|
||||
final TaskFragmentContainer tf = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
mSplitController.onTaskFragmentAppearEmptyTimeout(tf);
|
||||
mSplitController.onTaskFragmentAppearEmptyTimeout(mTransaction, tf);
|
||||
|
||||
verify(mSplitPresenter).cleanupContainer(tf, false /* shouldFinishDependent */);
|
||||
verify(mSplitPresenter).cleanupContainer(mTransaction, tf,
|
||||
false /* shouldFinishDependent */);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -229,8 +232,8 @@ public class SplitControllerTest {
|
||||
spyOn(tf);
|
||||
doReturn(mActivity).when(tf).getTopNonFinishingActivity();
|
||||
doReturn(true).when(tf).isEmpty();
|
||||
doReturn(true).when(mSplitController).launchPlaceholderIfNecessary(mActivity,
|
||||
false /* isOnCreated */);
|
||||
doReturn(true).when(mSplitController).launchPlaceholderIfNecessary(mTransaction,
|
||||
mActivity, false /* isOnCreated */);
|
||||
doNothing().when(mSplitPresenter).updateSplitContainer(any(), any(), any());
|
||||
|
||||
mSplitController.updateContainer(mTransaction, tf);
|
||||
@@ -250,7 +253,7 @@ public class SplitControllerTest {
|
||||
|
||||
mSplitController.updateContainer(mTransaction, tf);
|
||||
|
||||
verify(mSplitController, never()).dismissPlaceholderIfNecessary(any());
|
||||
verify(mSplitController, never()).dismissPlaceholderIfNecessary(any(), any());
|
||||
|
||||
// Verify if tf is not in the top splitContainer,
|
||||
final SplitContainer splitContainer = mock(SplitContainer.class);
|
||||
@@ -264,7 +267,7 @@ public class SplitControllerTest {
|
||||
|
||||
mSplitController.updateContainer(mTransaction, tf);
|
||||
|
||||
verify(mSplitController, never()).dismissPlaceholderIfNecessary(any());
|
||||
verify(mSplitController, never()).dismissPlaceholderIfNecessary(any(), any());
|
||||
|
||||
// Verify if one or both containers in the top SplitContainer are finished,
|
||||
// dismissPlaceholder() won't be called.
|
||||
@@ -273,12 +276,12 @@ public class SplitControllerTest {
|
||||
|
||||
mSplitController.updateContainer(mTransaction, tf);
|
||||
|
||||
verify(mSplitController, never()).dismissPlaceholderIfNecessary(any());
|
||||
verify(mSplitController, never()).dismissPlaceholderIfNecessary(any(), any());
|
||||
|
||||
// Verify if placeholder should be dismissed, updateSplitContainer() won't be called.
|
||||
doReturn(false).when(tf).isFinished();
|
||||
doReturn(true).when(mSplitController)
|
||||
.dismissPlaceholderIfNecessary(splitContainer);
|
||||
.dismissPlaceholderIfNecessary(mTransaction, splitContainer);
|
||||
|
||||
mSplitController.updateContainer(mTransaction, tf);
|
||||
|
||||
@@ -286,7 +289,7 @@ public class SplitControllerTest {
|
||||
|
||||
// Verify if the top active split is updated if both of its containers are not finished.
|
||||
doReturn(false).when(mSplitController)
|
||||
.dismissPlaceholderIfNecessary(splitContainer);
|
||||
.dismissPlaceholderIfNecessary(mTransaction, splitContainer);
|
||||
|
||||
mSplitController.updateContainer(mTransaction, tf);
|
||||
|
||||
@@ -315,21 +318,23 @@ public class SplitControllerTest {
|
||||
|
||||
@Test
|
||||
public void testOnActivityCreated() {
|
||||
mSplitController.onActivityCreated(mActivity);
|
||||
mSplitController.onActivityCreated(mTransaction, mActivity);
|
||||
|
||||
// Disallow to split as primary because we want the new launch to be always on top.
|
||||
verify(mSplitController).resolveActivityToContainer(mActivity, false /* isOnReparent */);
|
||||
verify(mSplitController).resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnActivityReparentedToTask_sameProcess() {
|
||||
mSplitController.onActivityReparentedToTask(TASK_ID, new Intent(),
|
||||
mSplitController.onActivityReparentedToTask(mTransaction, TASK_ID, new Intent(),
|
||||
mActivity.getActivityToken());
|
||||
|
||||
// Treated as on activity created, but allow to split as primary.
|
||||
verify(mSplitController).resolveActivityToContainer(mActivity, true /* isOnReparent */);
|
||||
verify(mSplitController).resolveActivityToContainer(mTransaction,
|
||||
mActivity, true /* isOnReparent */);
|
||||
// Try to place the activity to the top TaskFragment when there is no matched rule.
|
||||
verify(mSplitController).placeActivityInTopContainer(mActivity);
|
||||
verify(mSplitController).placeActivityInTopContainer(mTransaction, mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -339,10 +344,10 @@ public class SplitControllerTest {
|
||||
final IBinder activityToken = new Binder();
|
||||
final Intent intent = new Intent();
|
||||
|
||||
mSplitController.onActivityReparentedToTask(TASK_ID, intent, activityToken);
|
||||
mSplitController.onActivityReparentedToTask(mTransaction, TASK_ID, intent, activityToken);
|
||||
|
||||
// Treated as starting new intent
|
||||
verify(mSplitController, never()).resolveActivityToContainer(any(), anyBoolean());
|
||||
verify(mSplitController, never()).resolveActivityToContainer(any(), any(), anyBoolean());
|
||||
verify(mSplitController).resolveStartActivityIntent(any(), eq(TASK_ID), eq(intent),
|
||||
isNull());
|
||||
}
|
||||
@@ -504,26 +509,29 @@ public class SplitControllerTest {
|
||||
|
||||
@Test
|
||||
public void testPlaceActivityInTopContainer() {
|
||||
mSplitController.placeActivityInTopContainer(mActivity);
|
||||
mSplitController.placeActivityInTopContainer(mTransaction, mActivity);
|
||||
|
||||
verify(mSplitPresenter, never()).applyTransaction(any());
|
||||
verify(mTransaction, never()).reparentActivityToTaskFragment(any(), any());
|
||||
|
||||
mSplitController.newContainer(new Intent(), mActivity, TASK_ID);
|
||||
mSplitController.placeActivityInTopContainer(mActivity);
|
||||
// Place in the top container if there is no other rule matched.
|
||||
final TaskFragmentContainer topContainer = mSplitController
|
||||
.newContainer(new Intent(), mActivity, TASK_ID);
|
||||
mSplitController.placeActivityInTopContainer(mTransaction, mActivity);
|
||||
|
||||
verify(mSplitPresenter).applyTransaction(any());
|
||||
verify(mTransaction).reparentActivityToTaskFragment(topContainer.getTaskFragmentToken(),
|
||||
mActivity.getActivityToken());
|
||||
|
||||
// Not reparent if activity is in a TaskFragment.
|
||||
clearInvocations(mSplitPresenter);
|
||||
clearInvocations(mTransaction);
|
||||
mSplitController.newContainer(mActivity, TASK_ID);
|
||||
mSplitController.placeActivityInTopContainer(mActivity);
|
||||
mSplitController.placeActivityInTopContainer(mTransaction, mActivity);
|
||||
|
||||
verify(mSplitPresenter, never()).applyTransaction(any());
|
||||
verify(mTransaction, never()).reparentActivityToTaskFragment(any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResolveActivityToContainer_noRuleMatched() {
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertFalse(result);
|
||||
@@ -535,7 +543,7 @@ public class SplitControllerTest {
|
||||
setupExpandRule(mActivity);
|
||||
|
||||
// When the activity is not in any TaskFragment, create a new expanded TaskFragment for it.
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
final TaskFragmentContainer container = mSplitController.getContainerWithActivity(
|
||||
mActivity);
|
||||
@@ -543,7 +551,8 @@ public class SplitControllerTest {
|
||||
assertTrue(result);
|
||||
assertNotNull(container);
|
||||
verify(mSplitController).newContainer(mActivity, TASK_ID);
|
||||
verify(mSplitPresenter).expandActivity(container.getTaskFragmentToken(), mActivity);
|
||||
verify(mSplitPresenter).expandActivity(mTransaction, container.getTaskFragmentToken(),
|
||||
mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -552,11 +561,11 @@ public class SplitControllerTest {
|
||||
|
||||
// When the activity is not in any TaskFragment, create a new expanded TaskFragment for it.
|
||||
final TaskFragmentContainer container = mSplitController.newContainer(mActivity, TASK_ID);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
verify(mSplitPresenter).expandTaskFragment(container.getTaskFragmentToken());
|
||||
verify(mSplitPresenter).expandTaskFragment(mTransaction, container.getTaskFragmentToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -566,14 +575,15 @@ public class SplitControllerTest {
|
||||
// When the activity is not in any TaskFragment, create a new expanded TaskFragment for it.
|
||||
final Activity activity = createMockActivity();
|
||||
addSplitTaskFragments(activity, mActivity);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
final TaskFragmentContainer container = mSplitController.getContainerWithActivity(
|
||||
mActivity);
|
||||
|
||||
assertTrue(result);
|
||||
assertNotNull(container);
|
||||
verify(mSplitPresenter).expandActivity(container.getTaskFragmentToken(), mActivity);
|
||||
verify(mSplitPresenter).expandActivity(mTransaction, container.getTaskFragmentToken(),
|
||||
mActivity);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -583,11 +593,11 @@ public class SplitControllerTest {
|
||||
(SplitPlaceholderRule) mSplitController.getSplitRules().get(0);
|
||||
|
||||
// Launch placeholder if the activity is not in any TaskFragment.
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
verify(mSplitPresenter).startActivityToSide(mActivity, PLACEHOLDER_INTENT,
|
||||
verify(mSplitPresenter).startActivityToSide(mTransaction, mActivity, PLACEHOLDER_INTENT,
|
||||
mSplitController.getPlaceholderOptions(mActivity, true /* isOnCreated */),
|
||||
placeholderRule, true /* isPlaceholder */);
|
||||
}
|
||||
@@ -600,11 +610,11 @@ public class SplitControllerTest {
|
||||
final Activity activity = createMockActivity();
|
||||
mSplitController.newContainer(mActivity, TASK_ID);
|
||||
mSplitController.newContainer(activity, TASK_ID);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertFalse(result);
|
||||
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(),
|
||||
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
|
||||
anyBoolean());
|
||||
}
|
||||
|
||||
@@ -616,11 +626,11 @@ public class SplitControllerTest {
|
||||
|
||||
// Launch placeholder if the activity is in the topmost expanded TaskFragment.
|
||||
mSplitController.newContainer(mActivity, TASK_ID);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
verify(mSplitPresenter).startActivityToSide(mActivity, PLACEHOLDER_INTENT,
|
||||
verify(mSplitPresenter).startActivityToSide(mTransaction, mActivity, PLACEHOLDER_INTENT,
|
||||
mSplitController.getPlaceholderOptions(mActivity, true /* isOnCreated */),
|
||||
placeholderRule, true /* isPlaceholder */);
|
||||
}
|
||||
@@ -632,11 +642,11 @@ public class SplitControllerTest {
|
||||
// Don't launch placeholder if the activity is in primary split.
|
||||
final Activity secondaryActivity = createMockActivity();
|
||||
addSplitTaskFragments(mActivity, secondaryActivity);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertFalse(result);
|
||||
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(),
|
||||
verify(mSplitPresenter, never()).startActivityToSide(any(), any(), any(), any(), any(),
|
||||
anyBoolean());
|
||||
}
|
||||
|
||||
@@ -649,11 +659,11 @@ public class SplitControllerTest {
|
||||
// Launch placeholder if the activity is in secondary split.
|
||||
final Activity primaryActivity = createMockActivity();
|
||||
addSplitTaskFragments(primaryActivity, mActivity);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
verify(mSplitPresenter).startActivityToSide(mActivity, PLACEHOLDER_INTENT,
|
||||
verify(mSplitPresenter).startActivityToSide(mTransaction, mActivity, PLACEHOLDER_INTENT,
|
||||
mSplitController.getPlaceholderOptions(mActivity, true /* isOnCreated */),
|
||||
placeholderRule, true /* isPlaceholder */);
|
||||
}
|
||||
@@ -676,7 +686,7 @@ public class SplitControllerTest {
|
||||
secondaryContainer,
|
||||
splitRule);
|
||||
clearInvocations(mSplitController);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
@@ -705,7 +715,7 @@ public class SplitControllerTest {
|
||||
final Activity launchedActivity = createMockActivity();
|
||||
primaryContainer.addPendingAppearedActivity(launchedActivity);
|
||||
|
||||
assertFalse(mSplitController.resolveActivityToContainer(launchedActivity,
|
||||
assertFalse(mSplitController.resolveActivityToContainer(mTransaction, launchedActivity,
|
||||
false /* isOnReparent */));
|
||||
}
|
||||
|
||||
@@ -717,7 +727,7 @@ public class SplitControllerTest {
|
||||
// Activity is already in secondary split, no need to create new split.
|
||||
addSplitTaskFragments(primaryActivity, mActivity);
|
||||
clearInvocations(mSplitController);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
@@ -735,7 +745,7 @@ public class SplitControllerTest {
|
||||
addSplitTaskFragments(primaryActivity, secondaryActivity);
|
||||
mSplitController.getContainerWithActivity(secondaryActivity)
|
||||
.addPendingAppearedActivity(mActivity);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertFalse(result);
|
||||
@@ -760,7 +770,7 @@ public class SplitControllerTest {
|
||||
mActivity,
|
||||
secondaryContainer,
|
||||
placeholderRule);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
@@ -774,7 +784,7 @@ public class SplitControllerTest {
|
||||
final TaskFragmentContainer container = mSplitController.newContainer(activityBelow,
|
||||
TASK_ID);
|
||||
container.addPendingAppearedActivity(mActivity);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
@@ -790,14 +800,15 @@ public class SplitControllerTest {
|
||||
final TaskFragmentContainer container = mSplitController.newContainer(activityBelow,
|
||||
TASK_ID);
|
||||
container.addPendingAppearedActivity(mActivity);
|
||||
boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertFalse(result);
|
||||
assertEquals(container, mSplitController.getContainerWithActivity(mActivity));
|
||||
|
||||
// Allow to split as primary.
|
||||
result = mSplitController.resolveActivityToContainer(mActivity, true /* isOnReparent */);
|
||||
result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
true /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
assertSplitPair(mActivity, activityBelow);
|
||||
@@ -815,7 +826,7 @@ public class SplitControllerTest {
|
||||
final TaskFragmentContainer secondaryContainer = mSplitController.getContainerWithActivity(
|
||||
activityBelow);
|
||||
secondaryContainer.addPendingAppearedActivity(mActivity);
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
final boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
final TaskFragmentContainer container = mSplitController.getContainerWithActivity(
|
||||
mActivity);
|
||||
@@ -836,14 +847,15 @@ public class SplitControllerTest {
|
||||
final TaskFragmentContainer primaryContainer = mSplitController.getContainerWithActivity(
|
||||
primaryActivity);
|
||||
primaryContainer.addPendingAppearedActivity(mActivity);
|
||||
boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertFalse(result);
|
||||
assertEquals(primaryContainer, mSplitController.getContainerWithActivity(mActivity));
|
||||
|
||||
|
||||
result = mSplitController.resolveActivityToContainer(mActivity, true /* isOnReparent */);
|
||||
result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
true /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
assertSplitPair(mActivity, primaryActivity);
|
||||
@@ -861,7 +873,7 @@ public class SplitControllerTest {
|
||||
container.addPendingAppearedActivity(mActivity);
|
||||
|
||||
// Allow to split as primary.
|
||||
boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
true /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
@@ -879,15 +891,13 @@ public class SplitControllerTest {
|
||||
TASK_ID);
|
||||
container.addPendingAppearedActivity(mActivity);
|
||||
|
||||
boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
assertSplitPair(activityBelow, mActivity, true /* matchParentBounds */);
|
||||
}
|
||||
|
||||
// Suppress GuardedBy warning on unit tests
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Test
|
||||
public void testResolveActivityToContainer_minDimensions_shouldExpandSplitContainer() {
|
||||
final Activity primaryActivity = createMockActivity();
|
||||
@@ -899,14 +909,14 @@ public class SplitControllerTest {
|
||||
doReturn(secondaryActivity).when(mSplitController).findActivityBelow(eq(mActivity));
|
||||
|
||||
clearInvocations(mSplitPresenter);
|
||||
boolean result = mSplitController.resolveActivityToContainer(mActivity,
|
||||
boolean result = mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */);
|
||||
|
||||
assertTrue(result);
|
||||
assertSplitPair(primaryActivity, mActivity, true /* matchParentBounds */);
|
||||
assertEquals(mSplitController.getContainerWithActivity(secondaryActivity),
|
||||
mSplitController.getContainerWithActivity(mActivity));
|
||||
verify(mSplitPresenter, never()).createNewSplitContainer(any(), any(), any());
|
||||
verify(mSplitPresenter, never()).createNewSplitContainer(any(), any(), any(), any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -914,7 +924,7 @@ public class SplitControllerTest {
|
||||
doReturn(new Binder()).when(mSplitController).getInitialTaskFragmentToken(mActivity);
|
||||
|
||||
// No need to handle when the new launched activity is in an unknown TaskFragment.
|
||||
assertTrue(mSplitController.resolveActivityToContainer(mActivity,
|
||||
assertTrue(mSplitController.resolveActivityToContainer(mTransaction, mActivity,
|
||||
false /* isOnReparent */));
|
||||
}
|
||||
|
||||
@@ -993,7 +1003,7 @@ public class SplitControllerTest {
|
||||
private void setupTaskFragmentInfo(@NonNull TaskFragmentContainer container,
|
||||
@NonNull Activity activity) {
|
||||
final TaskFragmentInfo info = createMockTaskFragmentInfo(container, activity);
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
mSplitPresenter.mFragmentInfos.put(container.getTaskFragmentToken(), info);
|
||||
}
|
||||
|
||||
|
||||
@@ -78,6 +78,8 @@ import org.mockito.MockitoAnnotations;
|
||||
* Build/Install/Run:
|
||||
* atest WMJetpackUnitTests:SplitPresenterTest
|
||||
*/
|
||||
// Suppress GuardedBy warning on unit tests
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@@ -226,8 +228,9 @@ public class SplitPresenterTest {
|
||||
mTransaction, splitContainer, mActivity, secondaryActivity,
|
||||
null /* secondaryIntent */));
|
||||
|
||||
primaryTf.setInfo(createMockTaskFragmentInfo(primaryTf, mActivity));
|
||||
secondaryTf.setInfo(createMockTaskFragmentInfo(secondaryTf, secondaryActivity));
|
||||
primaryTf.setInfo(mTransaction, createMockTaskFragmentInfo(primaryTf, mActivity));
|
||||
secondaryTf.setInfo(mTransaction,
|
||||
createMockTaskFragmentInfo(secondaryTf, secondaryActivity));
|
||||
|
||||
assertEquals(RESULT_EXPANDED, mPresenter.expandSplitContainerIfNeeded(mTransaction,
|
||||
splitContainer, mActivity, secondaryActivity, null /* secondaryIntent */));
|
||||
|
||||
@@ -19,6 +19,8 @@ package androidx.window.extensions.embedding;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.TASK_ID;
|
||||
import static androidx.window.extensions.embedding.EmbeddingTestUtils.createMockTaskFragmentInfo;
|
||||
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doNothing;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
@@ -36,7 +38,6 @@ import static org.mockito.Mockito.never;
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.window.TaskFragmentInfo;
|
||||
@@ -62,25 +63,27 @@ import java.util.List;
|
||||
* Build/Install/Run:
|
||||
* atest WMJetpackUnitTests:TaskFragmentContainerTest
|
||||
*/
|
||||
// Suppress GuardedBy warning on unit tests
|
||||
@SuppressWarnings("GuardedBy")
|
||||
@Presubmit
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public class TaskFragmentContainerTest {
|
||||
@Mock
|
||||
private SplitPresenter mPresenter;
|
||||
@Mock
|
||||
private SplitController mController;
|
||||
@Mock
|
||||
private TaskFragmentInfo mInfo;
|
||||
@Mock
|
||||
private Handler mHandler;
|
||||
private WindowContainerTransaction mTransaction;
|
||||
private Activity mActivity;
|
||||
private Intent mIntent;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
doReturn(mHandler).when(mController).getHandler();
|
||||
mController = new SplitController();
|
||||
spyOn(mController);
|
||||
mActivity = createMockActivity();
|
||||
mIntent = new Intent();
|
||||
}
|
||||
@@ -123,7 +126,7 @@ public class TaskFragmentContainerTest {
|
||||
|
||||
// Remove all references after the container has appeared in server.
|
||||
doReturn(new ArrayList<>()).when(mInfo).getActivities();
|
||||
container.setInfo(mInfo);
|
||||
container.setInfo(mTransaction, mInfo);
|
||||
container.finish(true /* shouldFinishDependent */, mPresenter, wct, mController);
|
||||
|
||||
verify(mActivity, never()).finish();
|
||||
@@ -137,7 +140,7 @@ public class TaskFragmentContainerTest {
|
||||
final TaskFragmentContainer container0 = new TaskFragmentContainer(mActivity,
|
||||
null /* pendingAppearedIntent */, taskContainer, mController);
|
||||
final TaskFragmentInfo info = createMockTaskFragmentInfo(container0, mActivity);
|
||||
container0.setInfo(info);
|
||||
container0.setInfo(mTransaction, info);
|
||||
// Request to reparent the activity to a new TaskFragment.
|
||||
final TaskFragmentContainer container1 = new TaskFragmentContainer(mActivity,
|
||||
null /* pendingAppearedIntent */, taskContainer, mController);
|
||||
@@ -163,7 +166,7 @@ public class TaskFragmentContainerTest {
|
||||
|
||||
final TaskFragmentInfo info0 = createMockTaskFragmentInfo(pendingActivityContainer,
|
||||
mActivity);
|
||||
pendingActivityContainer.setInfo(info0);
|
||||
pendingActivityContainer.setInfo(mTransaction, info0);
|
||||
|
||||
assertTrue(pendingActivityContainer.mPendingAppearedActivities.isEmpty());
|
||||
|
||||
@@ -175,7 +178,7 @@ public class TaskFragmentContainerTest {
|
||||
|
||||
final TaskFragmentInfo info1 = createMockTaskFragmentInfo(pendingIntentContainer,
|
||||
mActivity);
|
||||
pendingIntentContainer.setInfo(info1);
|
||||
pendingIntentContainer.setInfo(mTransaction, info1);
|
||||
|
||||
assertNull(pendingIntentContainer.getPendingAppearedIntent());
|
||||
}
|
||||
@@ -191,18 +194,19 @@ public class TaskFragmentContainerTest {
|
||||
final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
|
||||
doReturn(new ArrayList<>()).when(info).getActivities();
|
||||
doReturn(true).when(info).isEmpty();
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertTrue(container.isWaitingActivityAppear());
|
||||
|
||||
doReturn(false).when(info).isEmpty();
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertFalse(container.isWaitingActivityAppear());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAppearEmptyTimeout() {
|
||||
doNothing().when(mController).onTaskFragmentAppearEmptyTimeout(any(), any());
|
||||
final TaskContainer taskContainer = new TaskContainer(TASK_ID);
|
||||
final TaskFragmentContainer container = new TaskFragmentContainer(null /* activity */,
|
||||
mIntent, taskContainer, mController);
|
||||
@@ -213,20 +217,20 @@ public class TaskFragmentContainerTest {
|
||||
final TaskFragmentInfo info = mock(TaskFragmentInfo.class);
|
||||
container.mInfo = null;
|
||||
doReturn(true).when(info).isEmpty();
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertNotNull(container.mAppearEmptyTimeout);
|
||||
|
||||
// Not set if it is not appeared empty.
|
||||
doReturn(new ArrayList<>()).when(info).getActivities();
|
||||
doReturn(false).when(info).isEmpty();
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertNull(container.mAppearEmptyTimeout);
|
||||
|
||||
// Remove timeout after the container becomes non-empty.
|
||||
doReturn(false).when(info).isEmpty();
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
|
||||
assertNull(container.mAppearEmptyTimeout);
|
||||
|
||||
@@ -234,7 +238,7 @@ public class TaskFragmentContainerTest {
|
||||
container.mInfo = null;
|
||||
container.setPendingAppearedIntent(mIntent);
|
||||
doReturn(true).when(info).isEmpty();
|
||||
container.setInfo(info);
|
||||
container.setInfo(mTransaction, info);
|
||||
container.mAppearEmptyTimeout.run();
|
||||
|
||||
assertNull(container.mAppearEmptyTimeout);
|
||||
@@ -260,7 +264,7 @@ public class TaskFragmentContainerTest {
|
||||
final List<IBinder> runningActivities = Lists.newArrayList(activity0.getActivityToken(),
|
||||
activity1.getActivityToken());
|
||||
doReturn(runningActivities).when(mInfo).getActivities();
|
||||
container.setInfo(mInfo);
|
||||
container.setInfo(mTransaction, mInfo);
|
||||
activities = container.collectNonFinishingActivities();
|
||||
|
||||
assertEquals(3, activities.size());
|
||||
@@ -295,7 +299,7 @@ public class TaskFragmentContainerTest {
|
||||
final Activity activity = createMockActivity();
|
||||
final List<IBinder> runningActivities = Lists.newArrayList(activity.getActivityToken());
|
||||
doReturn(runningActivities).when(mInfo).getActivities();
|
||||
container.setInfo(mInfo);
|
||||
container.setInfo(mTransaction, mInfo);
|
||||
|
||||
assertEquals(activity, container.getBottomMostActivity());
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
mTaskFragment);
|
||||
mController.dispatchPendingEvents();
|
||||
|
||||
verify(mOrganizer).onTaskFragmentInfoChanged(mTaskFragmentInfo);
|
||||
verify(mOrganizer).onTaskFragmentInfoChanged(eq(mTaskFragmentInfo));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -231,7 +231,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
verify(mOrganizer, never()).onTaskFragmentAppeared(any());
|
||||
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
|
||||
verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
|
||||
verify(mOrganizer).onTaskFragmentVanished(mTaskFragmentInfo);
|
||||
verify(mOrganizer).onTaskFragmentVanished(eq(mTaskFragmentInfo));
|
||||
|
||||
// Not trigger onTaskFragmentInfoChanged.
|
||||
// Call onTaskFragmentAppeared before calling onTaskFragmentInfoChanged.
|
||||
@@ -247,7 +247,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
verify(mOrganizer, never()).onTaskFragmentAppeared(any());
|
||||
verify(mOrganizer, never()).onTaskFragmentInfoChanged(any());
|
||||
verify(mOrganizer, never()).onTaskFragmentParentInfoChanged(anyInt(), any());
|
||||
verify(mOrganizer).onTaskFragmentVanished(mTaskFragmentInfo);
|
||||
verify(mOrganizer).onTaskFragmentVanished(eq(mTaskFragmentInfo));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -298,7 +298,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
mErrorToken, null /* taskFragment */, -1 /* opType */, exception);
|
||||
mController.dispatchPendingEvents();
|
||||
|
||||
verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), eq(null), eq(-1), eq(exception));
|
||||
verify(mOrganizer).onTaskFragmentError(eq(mErrorToken), eq(null), eq(-1),
|
||||
eq(exception));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -324,8 +325,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
mController.onActivityReparentedToTask(activity);
|
||||
mController.dispatchPendingEvents();
|
||||
|
||||
verify(mOrganizer).onActivityReparentedToTask(task.mTaskId, activity.intent,
|
||||
activity.token);
|
||||
verify(mOrganizer).onActivityReparentedToTask(eq(task.mTaskId), eq(activity.intent),
|
||||
eq(activity.token));
|
||||
|
||||
// Notify organizer if there is any embedded in the Task.
|
||||
final TaskFragment taskFragment = new TaskFragmentBuilder(mAtm)
|
||||
@@ -340,7 +341,8 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase {
|
||||
mController.dispatchPendingEvents();
|
||||
|
||||
verify(mOrganizer, times(2))
|
||||
.onActivityReparentedToTask(task.mTaskId, activity.intent, activity.token);
|
||||
.onActivityReparentedToTask(eq(task.mTaskId), eq(activity.intent),
|
||||
eq(activity.token));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user