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